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 79371c9d4SSatish Balay static inline PetscInt DMPlex_GlobalID(PetscInt point) { 89371c9d4SSatish Balay return point >= 0 ? point : -(point + 1); 99371c9d4SSatish Balay } 100134a67bSLisandro Dalcin 119371c9d4SSatish Balay static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) { 125a107427SMatthew G. Knepley DM ovdm; 135a107427SMatthew G. Knepley PetscSF sfPoint; 145a107427SMatthew G. Knepley IS cellNumbering; 155a107427SMatthew G. Knepley const PetscInt *cellNum; 165a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL; 175a107427SMatthew G. Knepley PetscBool useCone, useClosure; 185a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v; 195a107427SMatthew G. Knepley PetscMPIInt rank, size; 205a107427SMatthew G. Knepley 215a107427SMatthew G. Knepley PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 249566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 265a107427SMatthew G. Knepley if (dim != depth) { 275a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 295a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 309566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 315a107427SMatthew G. Knepley /* Different behavior for empty graphs */ 325a107427SMatthew G. Knepley if (!*numVertices) { 339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 345a107427SMatthew G. Knepley (*offsets)[0] = 0; 355a107427SMatthew G. Knepley } 365a107427SMatthew G. Knepley /* Broken in parallel */ 375f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 385a107427SMatthew G. Knepley PetscFunctionReturn(0); 395a107427SMatthew G. Knepley } 405a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */ 419566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 429566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 435a107427SMatthew G. Knepley /* Need overlap >= 1 */ 449566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 455a107427SMatthew G. Knepley if (size && overlap < 1) { 469566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(dm, 1, NULL, &ovdm)); 475a107427SMatthew G. Knepley } else { 489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 495a107427SMatthew G. Knepley ovdm = dm; 505a107427SMatthew G. Knepley } 519566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(ovdm, &sfPoint)); 529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd)); 539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering)); 545a107427SMatthew G. Knepley if (globalNumbering) { 559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 565a107427SMatthew G. Knepley *globalNumbering = cellNumbering; 575a107427SMatthew G. Knepley } 589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 595a107427SMatthew G. Knepley /* Determine sizes */ 605a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) { 615a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 62b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 635a107427SMatthew G. Knepley (*numVertices)++; 645a107427SMatthew G. Knepley } 659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(*numVertices + 1, &vOffsets)); 665a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 675a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0; 685a107427SMatthew G. Knepley 69b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 709566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 715a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 725a107427SMatthew G. Knepley const PetscInt point = adj[a]; 735a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize; 745a107427SMatthew G. Knepley } 755a107427SMatthew G. Knepley vOffsets[v + 1] = vOffsets[v] + vsize; 765a107427SMatthew G. Knepley ++v; 775a107427SMatthew G. Knepley } 785a107427SMatthew G. Knepley /* Determine adjacency */ 799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vOffsets[*numVertices], &vAdj)); 805a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 815a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v]; 825a107427SMatthew G. Knepley 835a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 84b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 859566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 865a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 875a107427SMatthew G. Knepley const PetscInt point = adj[a]; 889371c9d4SSatish Balay if (point != c && cStart <= point && point < cEnd) { vAdj[off++] = DMPlex_GlobalID(cellNum[point - cStart]); } 895a107427SMatthew G. Knepley } 9063a3b9bcSJacob Faibussowitsch PetscCheck(off == vOffsets[v + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %" PetscInt_FMT " should be %" PetscInt_FMT, off, vOffsets[v + 1]); 915a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */ 929566063dSJacob Faibussowitsch PetscCall(PetscSortInt(off - vOffsets[v], &vAdj[vOffsets[v]])); 935a107427SMatthew G. Knepley ++v; 945a107427SMatthew G. Knepley } 959566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 989566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 999566063dSJacob Faibussowitsch PetscCall(DMDestroy(&ovdm)); 1009371c9d4SSatish Balay if (offsets) { 1019371c9d4SSatish Balay *offsets = vOffsets; 1029371c9d4SSatish Balay } else PetscCall(PetscFree(vOffsets)); 1039371c9d4SSatish Balay if (adjacency) { 1049371c9d4SSatish Balay *adjacency = vAdj; 1059371c9d4SSatish Balay } else PetscCall(PetscFree(vAdj)); 1065a107427SMatthew G. Knepley PetscFunctionReturn(0); 1075a107427SMatthew G. Knepley } 1085a107427SMatthew G. Knepley 1099371c9d4SSatish Balay static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) { 110ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 111389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 1128cfe4c1fSMichael Lange IS cellNumbering; 1138cfe4c1fSMichael Lange const PetscInt *cellNum; 114532c4e7dSMichael Lange PetscBool useCone, useClosure; 115532c4e7dSMichael Lange PetscSection section; 116532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 1178cfe4c1fSMichael Lange PetscSF sfPoint; 1188f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 1198f4e72b9SMatthew G. Knepley const PetscInt *local; 1208f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 121532c4e7dSMichael Lange PetscMPIInt rank; 122532c4e7dSMichael Lange 123532c4e7dSMichael Lange PetscFunctionBegin; 1249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 127ffbd6163SMatthew G. Knepley if (dim != depth) { 128ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 1299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 130ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 1319566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 132ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 133ffbd6163SMatthew G. Knepley if (!*numVertices) { 1349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 135ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 136ffbd6163SMatthew G. Knepley } 137ffbd6163SMatthew G. Knepley /* Broken in parallel */ 1385f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 139ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 140ffbd6163SMatthew G. Knepley } 1419566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1429566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &pStart, &pEnd)); 143532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 1449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 1459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 1469566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 147532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 1489566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 1499566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 1509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering)); 1513fa7752dSToby Isaac if (globalNumbering) { 1529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 1533fa7752dSToby Isaac *globalNumbering = cellNumbering; 1543fa7752dSToby Isaac } 1559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 1568f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 1578f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 1588f4e72b9SMatthew G. Knepley */ 1599566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL)); 1608f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1618f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1628f4e72b9SMatthew G. Knepley 1639566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nroots, &adjCells, nroots, &remoteCells)); 1649566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd)); 1658f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1668f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1678f4e72b9SMatthew G. Knepley const PetscInt *support; 1688f4e72b9SMatthew G. Knepley PetscInt supportSize; 1698f4e72b9SMatthew G. Knepley 1709566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 1719566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 172b68380d8SVaclav Hapla if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1738f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 1749566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p)); 175b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1] - pStart]); 1769566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 177b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1780134a67bSLisandro Dalcin } 1790134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1800134a67bSLisandro Dalcin if (supportSize > 2) { 1810134a67bSLisandro Dalcin PetscInt numChildren, i; 1820134a67bSLisandro Dalcin const PetscInt *children; 1830134a67bSLisandro Dalcin 1849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, &children)); 1850134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1860134a67bSLisandro Dalcin const PetscInt child = children[i]; 1870134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, child, &support)); 1899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, child, &supportSize)); 190b68380d8SVaclav Hapla if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1910134a67bSLisandro Dalcin else if (supportSize == 2) { 1929566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p)); 193b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1] - pStart]); 1949566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 195b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1960134a67bSLisandro Dalcin } 1970134a67bSLisandro Dalcin } 1980134a67bSLisandro Dalcin } 1998f4e72b9SMatthew G. Knepley } 2008f4e72b9SMatthew G. Knepley } 2018f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 2029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE)); 2039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE)); 2049566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 2059566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 2068f4e72b9SMatthew G. Knepley } 2078f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 2088cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 2098cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 2109371c9d4SSatish Balay if (nroots > 0) { 2119371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue; 2129371c9d4SSatish Balay } 2138f4e72b9SMatthew G. Knepley /* Add remote cells */ 2148f4e72b9SMatthew G. Knepley if (remoteCells) { 215b68380d8SVaclav Hapla const PetscInt gp = DMPlex_GlobalID(cellNum[p - pStart]); 2160134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 2170134a67bSLisandro Dalcin const PetscInt *cone, *children; 2180134a67bSLisandro Dalcin 2199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 2209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 2218f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 2220134a67bSLisandro Dalcin const PetscInt point = cone[c]; 2230134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 2248f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 2259566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2269566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2270134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 2280134a67bSLisandro Dalcin } 2290134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 2309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 2310134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 2320134a67bSLisandro Dalcin const PetscInt child = children[i]; 2330134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 2340134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 2359566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2369566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2370134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 2380134a67bSLisandro Dalcin } 2398f4e72b9SMatthew G. Knepley } 2408f4e72b9SMatthew G. Knepley } 2418f4e72b9SMatthew G. Knepley } 2428f4e72b9SMatthew G. Knepley /* Add local cells */ 243532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 2449566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 245532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 246532c4e7dSMichael Lange const PetscInt point = adj[a]; 247532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 248532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 2499566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2509566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 251b68380d8SVaclav Hapla *pBuf = DMPlex_GlobalID(cellNum[point - pStart]); 252532c4e7dSMichael Lange } 253532c4e7dSMichael Lange } 2548cfe4c1fSMichael Lange (*numVertices)++; 255532c4e7dSMichael Lange } 2569566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2579566063dSJacob Faibussowitsch PetscCall(PetscFree2(adjCells, remoteCells)); 2589566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2594e468a93SLisandro Dalcin 260532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 2619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets)); 26443f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 2659371c9d4SSatish Balay if (nroots > 0) { 2669371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue; 2679371c9d4SSatish Balay } 2689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 26943f7d02bSMichael Lange } 270532c4e7dSMichael Lange vOffsets[*numVertices] = size; 2719566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2724e468a93SLisandro Dalcin 2734e468a93SLisandro Dalcin if (nroots >= 0) { 2744e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 2759566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(section)); 2769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, 0, *numVertices)); 2774e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2784e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1]; 2794e468a93SLisandro Dalcin PetscInt numEdges = end - start, *PETSC_RESTRICT edges; 2809566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&numEdges, &graph[start])); 2819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numEdges)); 2829566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, numEdges, &edges)); 2839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(edges, &graph[start], numEdges)); 2844e468a93SLisandro Dalcin } 2859566063dSJacob Faibussowitsch PetscCall(PetscFree(vOffsets)); 2869566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2874e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets)); 291*48a46eb9SPierre Jolivet for (idx = 0, p = 0; p < *numVertices; p++) PetscCall(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 2924e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2939566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2944e468a93SLisandro Dalcin } else { 2954e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2964e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2974e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1]; 2989566063dSJacob Faibussowitsch PetscCall(PetscSortInt(end - start, &graph[start])); 2994e468a93SLisandro Dalcin } 3004e468a93SLisandro Dalcin } 3014e468a93SLisandro Dalcin 3024e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 303389e55d8SMichael Lange if (adjacency) *adjacency = graph; 3044e468a93SLisandro Dalcin 305532c4e7dSMichael Lange /* Cleanup */ 3069566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 3079566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 3089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 3099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 310532c4e7dSMichael Lange PetscFunctionReturn(0); 311532c4e7dSMichael Lange } 312532c4e7dSMichael Lange 3139371c9d4SSatish Balay static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) { 314bbbc8e51SStefano Zampini Mat conn, CSR; 315bbbc8e51SStefano Zampini IS fis, cis, cis_own; 316bbbc8e51SStefano Zampini PetscSF sfPoint; 317bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 318bbbc8e51SStefano Zampini PetscInt *idxs, *idxs2; 31983c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 320bbbc8e51SStefano Zampini PetscMPIInt rank; 321bbbc8e51SStefano Zampini PetscBool flg; 322bbbc8e51SStefano Zampini 323bbbc8e51SStefano Zampini PetscFunctionBegin; 3249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 327bbbc8e51SStefano Zampini if (dim != depth) { 328bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 3299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 330bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 3319566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 332bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 333bbbc8e51SStefano Zampini if (!*numVertices) { 3349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 335bbbc8e51SStefano Zampini (*offsets)[0] = 0; 336bbbc8e51SStefano Zampini } 337bbbc8e51SStefano Zampini /* Broken in parallel */ 3385f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 339bbbc8e51SStefano Zampini PetscFunctionReturn(0); 340bbbc8e51SStefano Zampini } 341bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 342bbbc8e51SStefano Zampini 343bbbc8e51SStefano Zampini /* numbering */ 3449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 3459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 3469566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd)); 3479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis)); 3489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis)); 3491baa6e33SBarry Smith if (globalNumbering) PetscCall(ISDuplicate(cis, globalNumbering)); 350bbbc8e51SStefano Zampini 351bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 3529566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fis, &m)); 3539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 355bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 356bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 357bbbc8e51SStefano Zampini 358bbbc8e51SStefano Zampini if (p < 0) { 359bbbc8e51SStefano Zampini idxs[i] = -(p + 1); 360bbbc8e51SStefano Zampini } else { 361bbbc8e51SStefano Zampini idxs[i] = p; 362bbbc8e51SStefano Zampini floc += 1; 363bbbc8e51SStefano Zampini } 364bbbc8e51SStefano Zampini } 3659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 3669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis)); 368bbbc8e51SStefano Zampini 3699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cis, &m)); 3709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 3719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 3729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs2)); 373bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 374bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 375bbbc8e51SStefano Zampini 376bbbc8e51SStefano Zampini if (p < 0) { 377bbbc8e51SStefano Zampini idxs[i] = -(p + 1); 378bbbc8e51SStefano Zampini } else { 379bbbc8e51SStefano Zampini idxs[i] = p; 380bbbc8e51SStefano Zampini idxs2[cloc++] = p; 381bbbc8e51SStefano Zampini } 382bbbc8e51SStefano Zampini } 3839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 3849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 3859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis)); 3869566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own)); 387bbbc8e51SStefano Zampini 388bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 3899566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &conn)); 3909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(conn, floc, cloc, M, N)); 3919566063dSJacob Faibussowitsch PetscCall(MatSetType(conn, MATMPIAIJ)); 3929566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, NULL, &lm)); 3939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 3949566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL)); 395bbbc8e51SStefano Zampini 396bbbc8e51SStefano Zampini /* Assemble matrix */ 3979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 399bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 400bbbc8e51SStefano Zampini const PetscInt *cone; 401bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 402bbbc8e51SStefano Zampini 403bbbc8e51SStefano Zampini col = cols[c - cStart]; 4049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 4059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 406bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 407bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 408bbbc8e51SStefano Zampini const PetscInt *children; 409bbbc8e51SStefano Zampini PetscInt numChildren, ch; 410bbbc8e51SStefano Zampini 411bbbc8e51SStefano Zampini row = rows[cone[f] - fStart]; 4129566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 413bbbc8e51SStefano Zampini 414bbbc8e51SStefano Zampini /* non-conforming meshes */ 4159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children)); 416bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 417bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 418bbbc8e51SStefano Zampini 419bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 420bbbc8e51SStefano Zampini row = rows[child - fStart]; 4219566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 422bbbc8e51SStefano Zampini } 423bbbc8e51SStefano Zampini } 424bbbc8e51SStefano Zampini } 4259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 4269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 4279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 4299566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY)); 4309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY)); 431bbbc8e51SStefano Zampini 432bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 4339566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR)); 4349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 435bbbc8e51SStefano Zampini 436bbbc8e51SStefano Zampini /* extract local part of the CSR */ 4379566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn)); 4389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CSR)); 4399566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4405f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 441bbbc8e51SStefano Zampini 442bbbc8e51SStefano Zampini /* get back requested output */ 443bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 444bbbc8e51SStefano Zampini if (offsets) { 4459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m + 1, &idxs)); 446bbbc8e51SStefano Zampini for (i = 1; i < m + 1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 447bbbc8e51SStefano Zampini *offsets = idxs; 448bbbc8e51SStefano Zampini } 449bbbc8e51SStefano Zampini if (adjacency) { 4509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ii[m] - m, &idxs)); 4519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis_own, &rows)); 452bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 453bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 454bbbc8e51SStefano Zampini 455bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 456bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 457bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 458bbbc8e51SStefano Zampini } 459bbbc8e51SStefano Zampini } 46063a3b9bcSJacob Faibussowitsch PetscCheck(c == ii[m] - m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, c, ii[m] - m); 4619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis_own, &rows)); 462bbbc8e51SStefano Zampini *adjacency = idxs; 463bbbc8e51SStefano Zampini } 464bbbc8e51SStefano Zampini 465bbbc8e51SStefano Zampini /* cleanup */ 4669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis_own)); 4679566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4685f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 4699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 470bbbc8e51SStefano Zampini PetscFunctionReturn(0); 471bbbc8e51SStefano Zampini } 472bbbc8e51SStefano Zampini 473bbbc8e51SStefano Zampini /*@C 474bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 475bbbc8e51SStefano Zampini 476bbbc8e51SStefano Zampini Input Parameters: 477bbbc8e51SStefano Zampini + dm - The mesh DM dm 478bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 479bbbc8e51SStefano Zampini 480d8d19677SJose E. Roman Output Parameters: 481bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 482bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 483bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 484bbbc8e51SStefano 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. 485bbbc8e51SStefano Zampini 486bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 487bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 488bbbc8e51SStefano Zampini 4895a107427SMatthew G. Knepley Options Database Keys: 4905a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4915a107427SMatthew G. Knepley 492bbbc8e51SStefano Zampini Level: developer 493bbbc8e51SStefano Zampini 494db781477SPatrick Sanan .seealso: `PetscPartitionerGetType()`, `PetscPartitionerCreate()`, `DMSetAdjacency()` 495bbbc8e51SStefano Zampini @*/ 4969371c9d4SSatish Balay PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) { 4975a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH; 498bbbc8e51SStefano Zampini 499bbbc8e51SStefano Zampini PetscFunctionBegin; 5009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *)&alg, NULL)); 5015a107427SMatthew G. Knepley switch (alg) { 5029371c9d4SSatish Balay case DM_PLEX_CSR_MAT: PetscCall(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering)); break; 5039371c9d4SSatish Balay case DM_PLEX_CSR_GRAPH: PetscCall(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering)); break; 5049371c9d4SSatish Balay case DM_PLEX_CSR_OVERLAP: PetscCall(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering)); break; 505bbbc8e51SStefano Zampini } 506bbbc8e51SStefano Zampini PetscFunctionReturn(0); 507bbbc8e51SStefano Zampini } 508bbbc8e51SStefano Zampini 509d5577e40SMatthew G. Knepley /*@C 510d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 511d5577e40SMatthew G. Knepley 512fe2efc57SMark Collective on DM 513d5577e40SMatthew G. Knepley 5144165533cSJose E. Roman Input Parameters: 515d5577e40SMatthew G. Knepley + dm - The DMPlex 516d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 517d5577e40SMatthew G. Knepley 5184165533cSJose E. Roman Output Parameters: 519d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 520d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 521d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 522d5577e40SMatthew G. Knepley 523d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 524d5577e40SMatthew G. Knepley 525d5577e40SMatthew G. Knepley Level: advanced 526d5577e40SMatthew G. Knepley 527db781477SPatrick Sanan .seealso: `DMPlexCreate()` 528d5577e40SMatthew G. Knepley @*/ 5299371c9d4SSatish Balay PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) { 53070034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 53170034214SMatthew G. Knepley PetscInt numFaceCases = 0; 53270034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 53370034214SMatthew G. Knepley PetscInt *off, *adj; 53470034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 53570034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 53670034214SMatthew G. Knepley 53770034214SMatthew G. Knepley PetscFunctionBegin; 53870034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 5399566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 54070034214SMatthew G. Knepley cellDim = dim - cellHeight; 5419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5429566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 54370034214SMatthew G. Knepley if (cEnd - cStart == 0) { 54470034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 54570034214SMatthew G. Knepley if (offsets) *offsets = NULL; 54670034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 54770034214SMatthew G. Knepley PetscFunctionReturn(0); 54870034214SMatthew G. Knepley } 54970034214SMatthew G. Knepley numCells = cEnd - cStart; 55070034214SMatthew G. Knepley faceDepth = depth - cellHeight; 55170034214SMatthew G. Knepley if (dim == depth) { 55270034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 55370034214SMatthew G. Knepley 5549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off)); 55570034214SMatthew G. Knepley /* Count neighboring cells */ 5569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight + 1, &fStart, &fEnd)); 55770034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 55870034214SMatthew G. Knepley const PetscInt *support; 55970034214SMatthew G. Knepley PetscInt supportSize; 5609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 56270034214SMatthew G. Knepley if (supportSize == 2) { 5639ffc88e4SToby Isaac PetscInt numChildren; 5649ffc88e4SToby Isaac 5659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL)); 5669ffc88e4SToby Isaac if (!numChildren) { 56770034214SMatthew G. Knepley ++off[support[0] - cStart + 1]; 56870034214SMatthew G. Knepley ++off[support[1] - cStart + 1]; 56970034214SMatthew G. Knepley } 57070034214SMatthew G. Knepley } 5719ffc88e4SToby Isaac } 57270034214SMatthew G. Knepley /* Prefix sum */ 57370034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c - 1]; 57470034214SMatthew G. Knepley if (adjacency) { 57570034214SMatthew G. Knepley PetscInt *tmp; 57670034214SMatthew G. Knepley 5779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 5789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells + 1, &tmp)); 5799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(tmp, off, numCells + 1)); 58070034214SMatthew G. Knepley /* Get neighboring cells */ 58170034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 58270034214SMatthew G. Knepley const PetscInt *support; 58370034214SMatthew G. Knepley PetscInt supportSize; 5849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5859566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 58670034214SMatthew G. Knepley if (supportSize == 2) { 5879ffc88e4SToby Isaac PetscInt numChildren; 5889ffc88e4SToby Isaac 5899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL)); 5909ffc88e4SToby Isaac if (!numChildren) { 59170034214SMatthew G. Knepley adj[tmp[support[0] - cStart]++] = support[1]; 59270034214SMatthew G. Knepley adj[tmp[support[1] - cStart]++] = support[0]; 59370034214SMatthew G. Knepley } 59470034214SMatthew G. Knepley } 5959ffc88e4SToby Isaac } 59663a3b9bcSJacob 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); 5979566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 59870034214SMatthew G. Knepley } 59970034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 60070034214SMatthew G. Knepley if (offsets) *offsets = off; 60170034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 60270034214SMatthew G. Knepley PetscFunctionReturn(0); 60370034214SMatthew G. Knepley } 60470034214SMatthew G. Knepley /* Setup face recognition */ 60570034214SMatthew G. Knepley if (faceDepth == 1) { 60670034214SMatthew 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 */ 60770034214SMatthew G. Knepley 60870034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 60970034214SMatthew G. Knepley PetscInt corners; 61070034214SMatthew G. Knepley 6119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &corners)); 61270034214SMatthew G. Knepley if (!cornersSeen[corners]) { 61370034214SMatthew G. Knepley PetscInt nFV; 61470034214SMatthew G. Knepley 6155f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 61670034214SMatthew G. Knepley cornersSeen[corners] = 1; 61770034214SMatthew G. Knepley 6189566063dSJacob Faibussowitsch PetscCall(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV)); 61970034214SMatthew G. Knepley 62070034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 62170034214SMatthew G. Knepley } 62270034214SMatthew G. Knepley } 62370034214SMatthew G. Knepley } 6249566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off)); 62570034214SMatthew G. Knepley /* Count neighboring cells */ 62670034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 62770034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 62870034214SMatthew G. Knepley 6299566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 63070034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 63170034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 63270034214SMatthew G. Knepley PetscInt cellPair[2]; 63370034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 63470034214SMatthew G. Knepley PetscInt meetSize = 0; 63570034214SMatthew G. Knepley const PetscInt *meet = NULL; 63670034214SMatthew G. Knepley 6379371c9d4SSatish Balay cellPair[0] = cell; 6389371c9d4SSatish Balay cellPair[1] = neighborCells[n]; 63970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 64070034214SMatthew G. Knepley if (!found) { 6419566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 64270034214SMatthew G. Knepley if (meetSize) { 64370034214SMatthew G. Knepley PetscInt f; 64470034214SMatthew G. Knepley 64570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 64670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 64770034214SMatthew G. Knepley found = PETSC_TRUE; 64870034214SMatthew G. Knepley break; 64970034214SMatthew G. Knepley } 65070034214SMatthew G. Knepley } 65170034214SMatthew G. Knepley } 6529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 65370034214SMatthew G. Knepley } 65470034214SMatthew G. Knepley if (found) ++off[cell - cStart + 1]; 65570034214SMatthew G. Knepley } 65670034214SMatthew G. Knepley } 65770034214SMatthew G. Knepley /* Prefix sum */ 65870034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell - 1]; 65970034214SMatthew G. Knepley 66070034214SMatthew G. Knepley if (adjacency) { 6619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 66270034214SMatthew G. Knepley /* Get neighboring cells */ 66370034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 66470034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 66570034214SMatthew G. Knepley PetscInt cellOffset = 0; 66670034214SMatthew G. Knepley 6679566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 66870034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 66970034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 67070034214SMatthew G. Knepley PetscInt cellPair[2]; 67170034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 67270034214SMatthew G. Knepley PetscInt meetSize = 0; 67370034214SMatthew G. Knepley const PetscInt *meet = NULL; 67470034214SMatthew G. Knepley 6759371c9d4SSatish Balay cellPair[0] = cell; 6769371c9d4SSatish Balay cellPair[1] = neighborCells[n]; 67770034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 67870034214SMatthew G. Knepley if (!found) { 6799566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 68070034214SMatthew G. Knepley if (meetSize) { 68170034214SMatthew G. Knepley PetscInt f; 68270034214SMatthew G. Knepley 68370034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 68470034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 68570034214SMatthew G. Knepley found = PETSC_TRUE; 68670034214SMatthew G. Knepley break; 68770034214SMatthew G. Knepley } 68870034214SMatthew G. Knepley } 68970034214SMatthew G. Knepley } 6909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 69170034214SMatthew G. Knepley } 69270034214SMatthew G. Knepley if (found) { 69370034214SMatthew G. Knepley adj[off[cell - cStart] + cellOffset] = neighborCells[n]; 69470034214SMatthew G. Knepley ++cellOffset; 69570034214SMatthew G. Knepley } 69670034214SMatthew G. Knepley } 69770034214SMatthew G. Knepley } 69870034214SMatthew G. Knepley } 6999566063dSJacob Faibussowitsch PetscCall(PetscFree(neighborCells)); 70070034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 70170034214SMatthew G. Knepley if (offsets) *offsets = off; 70270034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 70370034214SMatthew G. Knepley PetscFunctionReturn(0); 70470034214SMatthew G. Knepley } 70570034214SMatthew G. Knepley 70677623264SMatthew G. Knepley /*@ 7073c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 70877623264SMatthew G. Knepley 709fe2efc57SMark Collective on PetscPartitioner 71077623264SMatthew G. Knepley 71177623264SMatthew G. Knepley Input Parameters: 71277623264SMatthew G. Knepley + part - The PetscPartitioner 7133c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 714f8987ae8SMichael Lange - dm - The mesh DM 71577623264SMatthew G. Knepley 71677623264SMatthew G. Knepley Output Parameters: 71777623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 718f8987ae8SMichael Lange - partition - The list of points by partition 71977623264SMatthew G. Knepley 7203c41b853SStefano Zampini Notes: 7213c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 7223c41b853SStefano Zampini by the section in the transitive closure of the point. 72377623264SMatthew G. Knepley 72477623264SMatthew G. Knepley Level: developer 72577623264SMatthew G. Knepley 726db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `PetscPartitionerCreate()`, `PetscSectionCreate()`, `PetscSectionSetChart()`, `PetscPartitionerPartition()` 7274b15ede2SMatthew G. Knepley @*/ 7289371c9d4SSatish Balay PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) { 72977623264SMatthew G. Knepley PetscMPIInt size; 7303c41b853SStefano Zampini PetscBool isplex; 7313c41b853SStefano Zampini PetscSection vertSection = NULL; 73277623264SMatthew G. Knepley 73377623264SMatthew G. Knepley PetscFunctionBegin; 73477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 73577623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7363c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 73777623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 73877623264SMatthew G. Knepley PetscValidPointer(partition, 5); 7399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isplex)); 7405f80ce2aSJacob Faibussowitsch PetscCheck(isplex, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not for type %s", ((PetscObject)dm)->type_name); 7419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)part), &size)); 74277623264SMatthew G. Knepley if (size == 1) { 74377623264SMatthew G. Knepley PetscInt *points; 74477623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 74577623264SMatthew G. Knepley 7469566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 7479566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(partSection)); 7489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(partSection, 0, size)); 7499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(partSection, 0, cEnd - cStart)); 7509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(partSection)); 7519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &points)); 75277623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 7539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), cEnd - cStart, points, PETSC_OWN_POINTER, partition)); 75477623264SMatthew G. Knepley PetscFunctionReturn(0); 75577623264SMatthew G. Knepley } 75677623264SMatthew G. Knepley if (part->height == 0) { 757074d466cSStefano Zampini PetscInt numVertices = 0; 75877623264SMatthew G. Knepley PetscInt *start = NULL; 75977623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7603fa7752dSToby Isaac IS globalNumbering; 76177623264SMatthew G. Knepley 762074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 7639566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering)); 76413911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 765074d466cSStefano Zampini const PetscInt *idxs; 766074d466cSStefano Zampini PetscInt p, pStart, pEnd; 767074d466cSStefano Zampini 7689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering)); 7709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &idxs)); 771074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 7729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &idxs)); 773074d466cSStefano Zampini } 7743c41b853SStefano Zampini if (part->usevwgt) { 7753c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7763c41b853SStefano Zampini IS clPoints = NULL; 7773c41b853SStefano Zampini const PetscInt *gid, *clIdx; 7783c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7790358368aSMatthew G. Knepley 7803c41b853SStefano 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) */ 7813c41b853SStefano Zampini /* We do this only if the local section has been set */ 7823c41b853SStefano Zampini if (section) { 7839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL)); 784*48a46eb9SPierre Jolivet if (!clSection) PetscCall(DMPlexCreateClosureIndex(dm, NULL)); 7859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints)); 7869566063dSJacob Faibussowitsch PetscCall(ISGetIndices(clPoints, &clIdx)); 7873c41b853SStefano Zampini } 7889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7899566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &vertSection)); 7909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(vertSection, 0, numVertices)); 7913c41b853SStefano Zampini if (globalNumbering) { 7929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &gid)); 7933c41b853SStefano Zampini } else gid = NULL; 7943c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 7953c41b853SStefano Zampini PetscInt dof = 1; 7960358368aSMatthew G. Knepley 7973c41b853SStefano Zampini /* skip cells in the overlap */ 7983c41b853SStefano Zampini if (gid && gid[p - pStart] < 0) continue; 7993c41b853SStefano Zampini 8003c41b853SStefano Zampini if (section) { 8013c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8023c41b853SStefano Zampini 8033c41b853SStefano Zampini dof = 0; 8049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(clSection, p, &clSize)); 8059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(clSection, p, &clOff)); 8063c41b853SStefano Zampini for (cl = 0; cl < clSize; cl += 2) { 8073c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8083c41b853SStefano Zampini 8099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, clPoint, &clDof)); 8103c41b853SStefano Zampini dof += clDof; 8110358368aSMatthew G. Knepley } 8120358368aSMatthew G. Knepley } 81363a3b9bcSJacob Faibussowitsch PetscCheck(dof, PETSC_COMM_SELF, PETSC_ERR_SUP, "Number of dofs for point %" PetscInt_FMT " in the local section should be positive", p); 8149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(vertSection, v, dof)); 8153c41b853SStefano Zampini v++; 8163c41b853SStefano Zampini } 817*48a46eb9SPierre Jolivet if (globalNumbering) PetscCall(ISRestoreIndices(globalNumbering, &gid)); 818*48a46eb9SPierre Jolivet if (clPoints) PetscCall(ISRestoreIndices(clPoints, &clIdx)); 8199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(vertSection)); 8203c41b853SStefano Zampini } 8219566063dSJacob Faibussowitsch PetscCall(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition)); 8229566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 8239566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 8243fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8253fa7752dSToby Isaac const PetscInt *globalNum; 8263fa7752dSToby Isaac const PetscInt *partIdx; 8273fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8283fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8293fa7752dSToby Isaac IS newPartition; 8303fa7752dSToby Isaac 8319566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*partition, &localSize)); 8329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &adjusted)); 8339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &globalNum)); 8349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*partition, &partIdx)); 8359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &map)); 8369566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 8373fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8383fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8393fa7752dSToby Isaac } 8409371c9d4SSatish Balay for (i = 0; i < localSize; i++) { adjusted[i] = map[partIdx[i]]; } 8419566063dSJacob Faibussowitsch PetscCall(PetscFree(map)); 8429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*partition, &partIdx)); 8439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &globalNum)); 8449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, localSize, adjusted, PETSC_OWN_POINTER, &newPartition)); 8459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalNumbering)); 8469566063dSJacob Faibussowitsch PetscCall(ISDestroy(partition)); 8473fa7752dSToby Isaac *partition = newPartition; 8483fa7752dSToby Isaac } 84963a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %" PetscInt_FMT " for points to partition", part->height); 8509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&vertSection)); 85177623264SMatthew G. Knepley PetscFunctionReturn(0); 85277623264SMatthew G. Knepley } 85377623264SMatthew G. Knepley 8545680f57bSMatthew G. Knepley /*@ 8555680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8565680f57bSMatthew G. Knepley 8575680f57bSMatthew G. Knepley Not collective 8585680f57bSMatthew G. Knepley 8595680f57bSMatthew G. Knepley Input Parameter: 8605680f57bSMatthew G. Knepley . dm - The DM 8615680f57bSMatthew G. Knepley 8625680f57bSMatthew G. Knepley Output Parameter: 8635680f57bSMatthew G. Knepley . part - The PetscPartitioner 8645680f57bSMatthew G. Knepley 8655680f57bSMatthew G. Knepley Level: developer 8665680f57bSMatthew G. Knepley 86798599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 86898599a47SLawrence Mitchell 869db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `DMPlexSetPartitioner()`, `PetscPartitionerDMPlexPartition()`, `PetscPartitionerCreate()` 8705680f57bSMatthew G. Knepley @*/ 8719371c9d4SSatish Balay PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) { 8725680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 8735680f57bSMatthew G. Knepley 8745680f57bSMatthew G. Knepley PetscFunctionBegin; 8755680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8765680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 8775680f57bSMatthew G. Knepley *part = mesh->partitioner; 8785680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8795680f57bSMatthew G. Knepley } 8805680f57bSMatthew G. Knepley 88171bb2955SLawrence Mitchell /*@ 88271bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 88371bb2955SLawrence Mitchell 884fe2efc57SMark logically collective on DM 88571bb2955SLawrence Mitchell 88671bb2955SLawrence Mitchell Input Parameters: 88771bb2955SLawrence Mitchell + dm - The DM 88871bb2955SLawrence Mitchell - part - The partitioner 88971bb2955SLawrence Mitchell 89071bb2955SLawrence Mitchell Level: developer 89171bb2955SLawrence Mitchell 89271bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 89371bb2955SLawrence Mitchell 894db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `DMPlexGetPartitioner()`, `PetscPartitionerCreate()` 89571bb2955SLawrence Mitchell @*/ 8969371c9d4SSatish Balay PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) { 89771bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 89871bb2955SLawrence Mitchell 89971bb2955SLawrence Mitchell PetscFunctionBegin; 90071bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90171bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 9029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)part)); 9039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 90471bb2955SLawrence Mitchell mesh->partitioner = part; 90571bb2955SLawrence Mitchell PetscFunctionReturn(0); 90671bb2955SLawrence Mitchell } 90771bb2955SLawrence Mitchell 9089371c9d4SSatish Balay static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) { 9098e330a33SStefano Zampini const PetscInt *cone; 9108e330a33SStefano Zampini PetscInt coneSize, c; 9118e330a33SStefano Zampini PetscBool missing; 9128e330a33SStefano Zampini 9138e330a33SStefano Zampini PetscFunctionBeginHot; 9149566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, point, &missing)); 9158e330a33SStefano Zampini if (missing) { 9169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 918*48a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosure_Private(dm, ht, cone[c])); 9198e330a33SStefano Zampini } 9208e330a33SStefano Zampini PetscFunctionReturn(0); 9218e330a33SStefano Zampini } 9228e330a33SStefano Zampini 9239371c9d4SSatish Balay PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) { 924270bba0cSToby Isaac PetscFunctionBegin; 9256a5a2ffdSToby Isaac if (up) { 9266a5a2ffdSToby Isaac PetscInt parent; 9276a5a2ffdSToby Isaac 9289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 9296a5a2ffdSToby Isaac if (parent != point) { 9306a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9316a5a2ffdSToby Isaac 9329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 933270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 934270bba0cSToby Isaac PetscInt cpoint = closure[2 * i]; 935270bba0cSToby Isaac 9369566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9379566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_TRUE, PETSC_FALSE)); 938270bba0cSToby Isaac } 9399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 9406a5a2ffdSToby Isaac } 9416a5a2ffdSToby Isaac } 9426a5a2ffdSToby Isaac if (down) { 9436a5a2ffdSToby Isaac PetscInt numChildren; 9446a5a2ffdSToby Isaac const PetscInt *children; 9456a5a2ffdSToby Isaac 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 9476a5a2ffdSToby Isaac if (numChildren) { 9486a5a2ffdSToby Isaac PetscInt i; 9496a5a2ffdSToby Isaac 9506a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9516a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9526a5a2ffdSToby Isaac 9539566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9549566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_FALSE, PETSC_TRUE)); 9556a5a2ffdSToby Isaac } 9566a5a2ffdSToby Isaac } 9576a5a2ffdSToby Isaac } 958270bba0cSToby Isaac PetscFunctionReturn(0); 959270bba0cSToby Isaac } 960270bba0cSToby Isaac 9619371c9d4SSatish Balay static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) { 9628e330a33SStefano Zampini PetscInt parent; 963825f8a23SLisandro Dalcin 9648e330a33SStefano Zampini PetscFunctionBeginHot; 9659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 9668e330a33SStefano Zampini if (point != parent) { 9678e330a33SStefano Zampini const PetscInt *cone; 9688e330a33SStefano Zampini PetscInt coneSize, c; 9698e330a33SStefano Zampini 9709566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, parent)); 9719566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, parent)); 9729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, parent, &cone)); 9739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 9748e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9758e330a33SStefano Zampini const PetscInt cp = cone[c]; 9768e330a33SStefano Zampini 9779566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, cp)); 9788e330a33SStefano Zampini } 9798e330a33SStefano Zampini } 9808e330a33SStefano Zampini PetscFunctionReturn(0); 9818e330a33SStefano Zampini } 9828e330a33SStefano Zampini 9839371c9d4SSatish Balay static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) { 9848e330a33SStefano Zampini PetscInt i, numChildren; 9858e330a33SStefano Zampini const PetscInt *children; 9868e330a33SStefano Zampini 9878e330a33SStefano Zampini PetscFunctionBeginHot; 9889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 989*48a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(PetscHSetIAdd(ht, children[i])); 9908e330a33SStefano Zampini PetscFunctionReturn(0); 9918e330a33SStefano Zampini } 9928e330a33SStefano Zampini 9939371c9d4SSatish Balay static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) { 9948e330a33SStefano Zampini const PetscInt *cone; 9958e330a33SStefano Zampini PetscInt coneSize, c; 9968e330a33SStefano Zampini 9978e330a33SStefano Zampini PetscFunctionBeginHot; 9989566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 9999566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, point)); 10009566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Down_Private(dm, ht, point)); 10019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 10029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 1003*48a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosureTree_Private(dm, ht, cone[c])); 10048e330a33SStefano Zampini PetscFunctionReturn(0); 10058e330a33SStefano Zampini } 10068e330a33SStefano Zampini 10079371c9d4SSatish Balay PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) { 1008825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10098e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10108e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 101127104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1012825f8a23SLisandro Dalcin 1013825f8a23SLisandro Dalcin PetscFunctionBegin; 10149566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 10159566063dSJacob Faibussowitsch PetscCall(PetscHSetIResize(ht, numPoints * 16)); 10168e330a33SStefano Zampini if (!hasTree) { 1017*48a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosure_Private(dm, ht, points[p])); 10188e330a33SStefano Zampini } else { 10198e330a33SStefano Zampini #if 1 1020*48a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosureTree_Private(dm, ht, points[p])); 10218e330a33SStefano Zampini #else 10228e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1023825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 10249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 1025825f8a23SLisandro Dalcin for (c = 0; c < closureSize * 2; c += 2) { 10269566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closure[c])); 10279566063dSJacob Faibussowitsch if (hasTree) PetscCall(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE)); 1028825f8a23SLisandro Dalcin } 1029825f8a23SLisandro Dalcin } 10309566063dSJacob Faibussowitsch if (closure) PetscCall(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure)); 10318e330a33SStefano Zampini #endif 10328e330a33SStefano Zampini } 10339566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nelems)); 10349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nelems, &elems)); 10359566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &off, elems)); 10369566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 10379566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nelems, elems)); 10389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS)); 1039825f8a23SLisandro Dalcin PetscFunctionReturn(0); 1040825f8a23SLisandro Dalcin } 1041825f8a23SLisandro Dalcin 10425abbe4feSMichael Lange /*@ 10435abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10445abbe4feSMichael Lange 10455abbe4feSMichael Lange Input Parameters: 10465abbe4feSMichael Lange + dm - The DM 1047a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 10485abbe4feSMichael Lange 10495abbe4feSMichael Lange Level: developer 10505abbe4feSMichael Lange 1051db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 10525abbe4feSMichael Lange @*/ 10539371c9d4SSatish Balay PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) { 1054825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 10555abbe4feSMichael Lange const PetscInt *ranks, *points; 1056825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 10579ffc88e4SToby Isaac 10589ffc88e4SToby Isaac PetscFunctionBegin; 10599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 10609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 10619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 10625abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10635abbe4feSMichael Lange const PetscInt rank = ranks[r]; 10649566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 10659566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 10669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 10679566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS)); 10689566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 10699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 10709566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, rank, closureIS)); 10719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&closureIS)); 10729ffc88e4SToby Isaac } 10739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 10749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 10759ffc88e4SToby Isaac PetscFunctionReturn(0); 10769ffc88e4SToby Isaac } 10779ffc88e4SToby Isaac 107824d039d7SMichael Lange /*@ 107924d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 108024d039d7SMichael Lange 108124d039d7SMichael Lange Input Parameters: 108224d039d7SMichael Lange + dm - The DM 1083a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 108424d039d7SMichael Lange 108524d039d7SMichael Lange Level: developer 108624d039d7SMichael Lange 1087db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 108824d039d7SMichael Lange @*/ 10899371c9d4SSatish Balay PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) { 109024d039d7SMichael Lange IS rankIS, pointIS; 109124d039d7SMichael Lange const PetscInt *ranks, *points; 109224d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 109324d039d7SMichael Lange PetscInt *adj = NULL; 109470034214SMatthew G. Knepley 109570034214SMatthew G. Knepley PetscFunctionBegin; 10969566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 10979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 10989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 109924d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 110024d039d7SMichael Lange const PetscInt rank = ranks[r]; 110170034214SMatthew G. Knepley 11029566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 11039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 11049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 110570034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 110624d039d7SMichael Lange adjSize = PETSC_DETERMINE; 11079566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj)); 11089566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(label, adj[a], rank)); 110970034214SMatthew G. Knepley } 11109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 11119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 111270034214SMatthew G. Knepley } 11139566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11159566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 111624d039d7SMichael Lange PetscFunctionReturn(0); 111770034214SMatthew G. Knepley } 111870034214SMatthew G. Knepley 1119be200f8dSMichael Lange /*@ 1120be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1121be200f8dSMichael Lange 1122be200f8dSMichael Lange Input Parameters: 1123be200f8dSMichael Lange + dm - The DM 1124a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1125be200f8dSMichael Lange 1126be200f8dSMichael Lange Level: developer 1127be200f8dSMichael Lange 1128be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1129be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1130be200f8dSMichael Lange 1131db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1132be200f8dSMichael Lange @*/ 11339371c9d4SSatish Balay PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) { 1134be200f8dSMichael Lange MPI_Comm comm; 1135be200f8dSMichael Lange PetscMPIInt rank; 1136be200f8dSMichael Lange PetscSF sfPoint; 11375d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1138be200f8dSMichael Lange IS rankIS, pointIS; 1139be200f8dSMichael Lange const PetscInt *ranks; 1140be200f8dSMichael Lange PetscInt numRanks, r; 1141be200f8dSMichael Lange 1142be200f8dSMichael Lange PetscFunctionBegin; 11439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11459566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 11465d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 11479566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 11489566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &rankIS)); 11499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 11515d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 11525d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 11535d04f6ebSMichael Lange if (remoteRank == rank) continue; 11549566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS)); 11559566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 11569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11575d04f6ebSMichael Lange } 11589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11609566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 1161be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 11629566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 11639566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &rankIS)); 11649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 1166be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1167be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1168be200f8dSMichael Lange if (remoteRank == rank) continue; 11699566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS)); 11709566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 11719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 1172be200f8dSMichael Lange } 11739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11759566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 1176be200f8dSMichael Lange PetscFunctionReturn(0); 1177be200f8dSMichael Lange } 1178be200f8dSMichael Lange 11791fd9873aSMichael Lange /*@ 11801fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 11811fd9873aSMichael Lange 11821fd9873aSMichael Lange Input Parameters: 11831fd9873aSMichael Lange + dm - The DM 1184a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots 1185fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 11861fd9873aSMichael Lange 11871fd9873aSMichael Lange Output Parameter: 1188a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots 11891fd9873aSMichael Lange 11901fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 11911fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 11921fd9873aSMichael Lange 11931fd9873aSMichael Lange Level: developer 11941fd9873aSMichael Lange 1195db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 11961fd9873aSMichael Lange @*/ 11979371c9d4SSatish Balay PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) { 11981fd9873aSMichael Lange MPI_Comm comm; 1199874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1200874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12011fd9873aSMichael Lange PetscSF sfPoint; 1202874ddda9SLisandro Dalcin PetscSection rootSection; 12031fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12041fd9873aSMichael Lange const PetscSFNode *remote; 12051fd9873aSMichael Lange const PetscInt *local, *neighbors; 12061fd9873aSMichael Lange IS valueIS; 1207874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12081fd9873aSMichael Lange 12091fd9873aSMichael Lange PetscFunctionBegin; 12109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelInvert, dm, 0, 0, 0)); 12119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 12149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 12151fd9873aSMichael Lange 12161fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 12179566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 12189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, 0, size)); 12199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(rootLabel, &valueIS)); 12209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numNeighbors)); 12219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &neighbors)); 12221fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12239566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints)); 12249566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(rootSection, neighbors[n], numPoints)); 12251fd9873aSMichael Lange } 12269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 12279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &rootSize)); 12289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rootSize, &rootPoints)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 12301fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12311fd9873aSMichael Lange IS pointIS; 12321fd9873aSMichael Lange const PetscInt *points; 12331fd9873aSMichael Lange 12349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 12359566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS)); 12369566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 12379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 12381fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 12399566063dSJacob Faibussowitsch if (local) PetscCall(PetscFindInt(points[p], nleaves, local, &l)); 1240f8987ae8SMichael Lange else { l = -1; } 12419371c9d4SSatish Balay if (l >= 0) { 12429371c9d4SSatish Balay rootPoints[off + p] = remote[l]; 12439371c9d4SSatish Balay } else { 12449371c9d4SSatish Balay rootPoints[off + p].index = points[p]; 12459371c9d4SSatish Balay rootPoints[off + p].rank = rank; 12469371c9d4SSatish Balay } 12471fd9873aSMichael Lange } 12489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 12499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 12501fd9873aSMichael Lange } 1251874ddda9SLisandro Dalcin 1252874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1253874ddda9SLisandro Dalcin if (!processSF) { 1254874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1255874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1256874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1257874ddda9SLisandro Dalcin 12589566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls)); 1259874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 12609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, neighbors[n], &dof)); 12619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1262874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 12639371c9d4SSatish Balay if (dof > PETSC_MPI_INT_MAX) { 12649371c9d4SSatish Balay locOverflow = PETSC_TRUE; 12659371c9d4SSatish Balay break; 12669371c9d4SSatish Balay } 12679371c9d4SSatish Balay if (off > PETSC_MPI_INT_MAX) { 12689371c9d4SSatish Balay locOverflow = PETSC_TRUE; 12699371c9d4SSatish Balay break; 12709371c9d4SSatish Balay } 1271874ddda9SLisandro Dalcin #endif 1272874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt)dof; 1273874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt)off; 1274874ddda9SLisandro Dalcin } 12759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm)); 12769371c9d4SSatish Balay for (r = 0; r < size; ++r) { 12779371c9d4SSatish Balay rdispls[r] = (int)counter; 12789371c9d4SSatish Balay counter += rcounts[r]; 12799371c9d4SSatish Balay } 1280874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 12819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm)); 1282874ddda9SLisandro Dalcin if (!mpiOverflow) { 12839566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using Alltoallv for mesh distribution\n")); 1284874ddda9SLisandro Dalcin leafSize = (PetscInt)counter; 12859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafSize, &leafPoints)); 12869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm)); 1287874ddda9SLisandro Dalcin } 12889566063dSJacob Faibussowitsch PetscCall(PetscFree4(scounts, sdispls, rcounts, rdispls)); 1289874ddda9SLisandro Dalcin } 1290874ddda9SLisandro Dalcin 1291874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1292874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1293874ddda9SLisandro Dalcin PetscSF procSF; 1294874ddda9SLisandro Dalcin PetscSection leafSection; 1295874ddda9SLisandro Dalcin 1296874ddda9SLisandro Dalcin if (processSF) { 12979566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution\n")); 12989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)processSF)); 1299874ddda9SLisandro Dalcin procSF = processSF; 1300874ddda9SLisandro Dalcin } else { 13019566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution (MPI overflow)\n")); 13029566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &procSF)); 13039566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphWithPattern(procSF, NULL, PETSCSF_PATTERN_ALLTOALL)); 1304874ddda9SLisandro Dalcin } 1305874ddda9SLisandro Dalcin 13069566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection)); 13079566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void **)&leafPoints)); 13089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSection, &leafSize)); 13099566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 13109566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&procSF)); 1311874ddda9SLisandro Dalcin } 1312874ddda9SLisandro Dalcin 1313*48a46eb9SPierre Jolivet for (p = 0; p < leafSize; p++) PetscCall(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank)); 1314874ddda9SLisandro Dalcin 13159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &neighbors)); 13169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 13179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 13189566063dSJacob Faibussowitsch PetscCall(PetscFree(rootPoints)); 13199566063dSJacob Faibussowitsch PetscCall(PetscFree(leafPoints)); 13209566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelInvert, dm, 0, 0, 0)); 13211fd9873aSMichael Lange PetscFunctionReturn(0); 13221fd9873aSMichael Lange } 13231fd9873aSMichael Lange 1324aa3148a8SMichael Lange /*@ 1325aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1326aa3148a8SMichael Lange 1327aa3148a8SMichael Lange Input Parameters: 1328aa3148a8SMichael Lange + dm - The DM 1329a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1330aa3148a8SMichael Lange 1331aa3148a8SMichael Lange Output Parameter: 1332fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1333aa3148a8SMichael Lange 1334aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1335aa3148a8SMichael Lange 1336aa3148a8SMichael Lange Level: developer 1337aa3148a8SMichael Lange 1338db781477SPatrick Sanan .seealso: `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1339aa3148a8SMichael Lange @*/ 13409371c9d4SSatish Balay PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) { 13416e203dd9SStefano Zampini PetscMPIInt rank; 13426e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1343aa3148a8SMichael Lange PetscSFNode *remotePoints; 13446e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13456e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1346aa3148a8SMichael Lange 1347aa3148a8SMichael Lange PetscFunctionBegin; 13489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0)); 13499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1350aa3148a8SMichael Lange 13519566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &neighborsIS)); 13526e203dd9SStefano Zampini #if 0 13536e203dd9SStefano Zampini { 13546e203dd9SStefano Zampini IS is; 13559566063dSJacob Faibussowitsch PetscCall(ISDuplicate(neighborsIS, &is)); 13569566063dSJacob Faibussowitsch PetscCall(ISSort(is)); 13579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 13586e203dd9SStefano Zampini neighborsIS = is; 13596e203dd9SStefano Zampini } 13606e203dd9SStefano Zampini #endif 13619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neighborsIS, &nNeighbors)); 13629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(neighborsIS, &neighbors)); 13636e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 13649566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, neighbors[n], &numPoints)); 1365aa3148a8SMichael Lange numRemote += numPoints; 1366aa3148a8SMichael Lange } 13679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRemote, &remotePoints)); 136843f7d02bSMichael Lange /* Put owned points first */ 13699566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, rank, &numPoints)); 137043f7d02bSMichael Lange if (numPoints > 0) { 13719566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &remoteRootIS)); 13729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 137343f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 137443f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 137543f7d02bSMichael Lange remotePoints[idx].rank = rank; 137643f7d02bSMichael Lange idx++; 137743f7d02bSMichael Lange } 13789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 13799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 138043f7d02bSMichael Lange } 138143f7d02bSMichael Lange /* Now add remote points */ 13826e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 13836e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 13846e203dd9SStefano Zampini 13859566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, nn, &numPoints)); 13866e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 13879566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, nn, &remoteRootIS)); 13889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 1389aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1390aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 13916e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1392aa3148a8SMichael Lange idx++; 1393aa3148a8SMichael Lange } 13949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 13959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 1396aa3148a8SMichael Lange } 13979566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sf)); 13989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 13999566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, pEnd - pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 14009566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sf)); 14019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 14029566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0)); 140370034214SMatthew G. Knepley PetscFunctionReturn(0); 140470034214SMatthew G. Knepley } 1405cb87ef4cSFlorian Wechsung 1406abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1407abe9303eSLisandro Dalcin #include <parmetis.h> 1408abe9303eSLisandro Dalcin #endif 1409abe9303eSLisandro Dalcin 14106a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14116a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14126a3739e5SFlorian Wechsung * them out in that case. */ 14136a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 14147a82c785SFlorian Wechsung /*@C 14157f57c1a4SFlorian Wechsung 14167f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 14177f57c1a4SFlorian Wechsung 14187f57c1a4SFlorian Wechsung Input parameters: 14197f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1420fe2efc57SMark . n - The number of points. 1421fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1422fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1423fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 14247f57c1a4SFlorian Wechsung 14257f57c1a4SFlorian Wechsung Level: developer 14267f57c1a4SFlorian Wechsung 14277f57c1a4SFlorian Wechsung @*/ 14289371c9d4SSatish Balay static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) { 14295f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14307f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14317f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14327f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14337f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14347f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14357f57c1a4SFlorian Wechsung PetscSF sf; 14367f57c1a4SFlorian Wechsung MPI_Comm comm; 14375a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14387f57c1a4SFlorian Wechsung 14397f57c1a4SFlorian Wechsung PetscFunctionBegin; 14409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14439566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14447f57c1a4SFlorian Wechsung 14459566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 14469566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 14479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf)); 14489371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) { isLeaf[i] = PETSC_FALSE; } 14499371c9d4SSatish Balay for (i = 0; i < nleafs; i++) { isLeaf[ilocal[i] - pStart] = PETSC_TRUE; } 14507f57c1a4SFlorian Wechsung 14519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + 1, &cumSumDegrees)); 14527f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 14539371c9d4SSatish Balay for (i = 1; i <= pEnd - pStart; i++) { cumSumDegrees[i] = cumSumDegrees[i - 1] + degrees[i - 1]; } 14547f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd - pStart]; 14557f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 14567f57c1a4SFlorian Wechsung 14579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &locationsOfLeafs)); 14589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &rankOnLeafs)); 14599371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) { rankOnLeafs[i] = rank; } 14609566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14619566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14629566063dSJacob Faibussowitsch PetscCall(PetscFree(rankOnLeafs)); 14637f57c1a4SFlorian Wechsung 14647f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 14659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs)); 14669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &points)); 14679371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) { points[i] = pStart + i; } 14689566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 14699566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 14709566063dSJacob Faibussowitsch PetscCall(PetscFree(points)); 14717f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 14729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newOwners)); 14739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newNumbers)); 14747f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 14757f57c1a4SFlorian Wechsung newOwners[i] = -1; 14767f57c1a4SFlorian Wechsung newNumbers[i] = -1; 14777f57c1a4SFlorian Wechsung } 14787f57c1a4SFlorian Wechsung { 14797f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 14807f57c1a4SFlorian Wechsung for (i = 0; i < n; i++) { 14817f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 14827f57c1a4SFlorian Wechsung newNumber = -1; 14837f57c1a4SFlorian Wechsung oldOwner = rank; 14847f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 14857f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 14867f57c1a4SFlorian Wechsung newNumber = oldNumber; 14877f57c1a4SFlorian Wechsung } else { 14887f57c1a4SFlorian Wechsung for (j = 0; j < degrees[oldNumber]; j++) { 14897f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber] + j] == newOwner) { 14907f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber] + j]; 14917f57c1a4SFlorian Wechsung break; 14927f57c1a4SFlorian Wechsung } 14937f57c1a4SFlorian Wechsung } 14947f57c1a4SFlorian Wechsung } 14955f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 14967f57c1a4SFlorian Wechsung 14977f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 14987f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 14997f57c1a4SFlorian Wechsung } 15007f57c1a4SFlorian Wechsung } 15019566063dSJacob Faibussowitsch PetscCall(PetscFree(cumSumDegrees)); 15029566063dSJacob Faibussowitsch PetscCall(PetscFree(locationsOfLeafs)); 15039566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteLocalPointOfLeafs)); 15047f57c1a4SFlorian Wechsung 15059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE)); 15069566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE)); 15079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE)); 15089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE)); 15097f57c1a4SFlorian Wechsung 15107f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15117f57c1a4SFlorian Wechsung leafCounter = 0; 15127f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 15137f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15149371c9d4SSatish Balay if (newOwners[i] != rank) { leafCounter++; } 15157f57c1a4SFlorian Wechsung } else { 15169371c9d4SSatish Balay if (isLeaf[i]) { leafCounter++; } 15177f57c1a4SFlorian Wechsung } 15187f57c1a4SFlorian Wechsung } 15197f57c1a4SFlorian Wechsung 15207f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 15219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafsNew)); 15229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafLocationsNew)); 15237f57c1a4SFlorian Wechsung 15247f57c1a4SFlorian Wechsung leafCounter = 0; 15257f57c1a4SFlorian Wechsung counter = 0; 15267f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 15277f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15287f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15297f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15307f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15317f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15327f57c1a4SFlorian Wechsung leafCounter++; 15337f57c1a4SFlorian Wechsung } 15347f57c1a4SFlorian Wechsung } else { 15357f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15367f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15377f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15387f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 15397f57c1a4SFlorian Wechsung leafCounter++; 15407f57c1a4SFlorian Wechsung } 15417f57c1a4SFlorian Wechsung } 15429371c9d4SSatish Balay if (isLeaf[i]) { counter++; } 15437f57c1a4SFlorian Wechsung } 15447f57c1a4SFlorian Wechsung 15459566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER)); 15469566063dSJacob Faibussowitsch PetscCall(PetscFree(newOwners)); 15479566063dSJacob Faibussowitsch PetscCall(PetscFree(newNumbers)); 15489566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 15497f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 15507f57c1a4SFlorian Wechsung } 15517f57c1a4SFlorian Wechsung 15529371c9d4SSatish Balay static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) { 15535f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum; 15545a30b08bSFlorian Wechsung PetscMPIInt rank, size; 15555f80ce2aSJacob Faibussowitsch 1556125d2a8fSFlorian Wechsung PetscFunctionBegin; 15579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15599566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &distribution)); 15605f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < n; i++) { 1561125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip * i]; 1562125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip * i]; 1563125d2a8fSFlorian Wechsung } 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm)); 1565125d2a8fSFlorian Wechsung min = distribution[0]; 1566125d2a8fSFlorian Wechsung max = distribution[0]; 1567125d2a8fSFlorian Wechsung sum = distribution[0]; 15685f80ce2aSJacob Faibussowitsch for (PetscInt i = 1; i < size; i++) { 1569125d2a8fSFlorian Wechsung if (distribution[i] < min) min = distribution[i]; 1570125d2a8fSFlorian Wechsung if (distribution[i] > max) max = distribution[i]; 1571125d2a8fSFlorian Wechsung sum += distribution[i]; 1572125d2a8fSFlorian Wechsung } 157363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Min: %" PetscInt_FMT ", Avg: %" PetscInt_FMT ", Max: %" PetscInt_FMT ", Balance: %f\n", min, sum / size, max, (max * 1. * size) / sum)); 15749566063dSJacob Faibussowitsch PetscCall(PetscFree(distribution)); 1575125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1576125d2a8fSFlorian Wechsung } 1577125d2a8fSFlorian Wechsung 15786a3739e5SFlorian Wechsung #endif 15796a3739e5SFlorian Wechsung 1580cb87ef4cSFlorian Wechsung /*@ 15815dc86ac1SFlorian Wechsung DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace. 1582cb87ef4cSFlorian Wechsung 1583cb87ef4cSFlorian Wechsung Input parameters: 1584ed44d270SFlorian Wechsung + dm - The DMPlex object. 1585fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1586fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1587fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1588cb87ef4cSFlorian Wechsung 15898b879b41SFlorian Wechsung Output parameters: 1590252a1336SBarry Smith . success - whether the graph partitioning was successful or not, optional. Unsuccessful simply means no change to the partitioning 1591252a1336SBarry Smith 1592252a1336SBarry Smith Options Database: 1593252a1336SBarry Smith + -dm_plex_rebalance_shared_points_parmetis - Use ParMetis instead of Metis for the partitioner 1594252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_initial_guess - Use current partition to bootstrap ParMetis partition 1595252a1336SBarry 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_ 1596252a1336SBarry Smith - -dm_plex_rebalance_shared_points_monitor - Monitor the shared points rebalance process 1597252a1336SBarry Smith 1598252a1336SBarry Smith Developer Notes: 1599252a1336SBarry Smith This should use MatPartitioning to allow the use of any partitioner and not be hardwired to use ParMetis 16008b879b41SFlorian Wechsung 160190ea27d8SSatish Balay Level: intermediate 1602cb87ef4cSFlorian Wechsung @*/ 16039371c9d4SSatish Balay PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) { 160441525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1605cb87ef4cSFlorian Wechsung PetscSF sf; 16060faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16077f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16087f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16097f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1610cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1611cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1612cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16137f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16145dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1615cb87ef4cSFlorian Wechsung PetscInt offset, counter; 1616252a1336SBarry Smith PetscInt *vtxwgt; 1617252a1336SBarry Smith const PetscInt *xadj, *adjncy; 1618cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1619cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1620cb87ef4cSFlorian Wechsung real_t *ubvec; 1621cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1622cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1623cb87ef4cSFlorian Wechsung MPI_Comm comm; 1624252a1336SBarry Smith Mat A; 16257d197802SFlorian Wechsung PetscViewer viewer; 16267d197802SFlorian Wechsung PetscViewerFormat format; 16275a30b08bSFlorian Wechsung PetscLayout layout; 1628252a1336SBarry Smith real_t *tpwgts; 1629252a1336SBarry Smith PetscMPIInt *counts, *mpiCumSumVertices; 1630252a1336SBarry Smith PetscInt *pointsToRewrite; 1631252a1336SBarry Smith PetscInt numRows; 1632252a1336SBarry Smith PetscBool done, usematpartitioning = PETSC_FALSE; 1633252a1336SBarry Smith IS ispart = NULL; 1634252a1336SBarry Smith MatPartitioning mp; 1635252a1336SBarry Smith const char *prefix; 163612617df9SFlorian Wechsung 163712617df9SFlorian Wechsung PetscFunctionBegin; 16389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1640252a1336SBarry Smith if (size == 1) { 1641252a1336SBarry Smith if (success) *success = PETSC_TRUE; 1642252a1336SBarry Smith PetscFunctionReturn(0); 1643252a1336SBarry Smith } 1644252a1336SBarry Smith if (success) *success = PETSC_FALSE; 1645252a1336SBarry Smith PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1646252a1336SBarry Smith 1647252a1336SBarry Smith parallel = PETSC_FALSE; 1648252a1336SBarry Smith useInitialGuess = PETSC_FALSE; 1649252a1336SBarry Smith PetscObjectOptionsBegin((PetscObject)dm); 1650252a1336SBarry Smith PetscCall(PetscOptionsName("-dm_plex_rebalance_shared_points_parmetis", "Use ParMetis instead of Metis for the partitioner", "DMPlexRebalanceSharedPoints", ¶llel)); 1651252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_initial_guess", "Use current partition to bootstrap ParMetis partition", "DMPlexRebalanceSharedPoints", useInitialGuess, &useInitialGuess, NULL)); 1652252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_mat_partitioning", "Use the MatPartitioning object to partition", "DMPlexRebalanceSharedPoints", usematpartitioning, &usematpartitioning, NULL)); 1653252a1336SBarry Smith PetscCall(PetscOptionsViewer("-dm_plex_rebalance_shared_points_monitor", "Monitor the shared points rebalance process", "DMPlexRebalanceSharedPoints", &viewer, &format, NULL)); 1654252a1336SBarry Smith PetscOptionsEnd(); 1655252a1336SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format)); 16567f57c1a4SFlorian Wechsung 16579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 165841525646SFlorian Wechsung 1659252a1336SBarry Smith PetscCall(DMGetOptionsPrefix(dm, &prefix)); 16609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)dm)->options, prefix, "-dm_rebalance_partition_view", &viewer, &format, NULL)); 16611baa6e33SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format)); 16627d197802SFlorian Wechsung 1663ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 16649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd)); 16659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &toBalance)); 16679371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) { toBalance[i] = (PetscBool)(i >= eBegin && i < eEnd); } 1668cb87ef4cSFlorian Wechsung 1669cf818975SFlorian Wechsung /* There are three types of points: 1670cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1671cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1672cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1673cf818975SFlorian Wechsung */ 16749566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 16759566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 16769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf)); 16779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isNonExclusivelyOwned)); 16789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isExclusivelyOwned)); 1679cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1680cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1681cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1682cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1683cb87ef4cSFlorian Wechsung } 1684cf818975SFlorian Wechsung 1685252a1336SBarry Smith /* mark all the leafs */ 16869371c9d4SSatish Balay for (i = 0; i < nleafs; i++) { isLeaf[ilocal[i] - pStart] = PETSC_TRUE; } 1687cb87ef4cSFlorian Wechsung 1688cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1689cf818975SFlorian Wechsung * not by calculating its degree */ 16909566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, °rees)); 16919566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, °rees)); 1692cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1693cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1694cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1695cb87ef4cSFlorian Wechsung if (toBalance[i]) { 16967f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1697cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1698cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1699cb87ef4cSFlorian Wechsung } else { 1700cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1701cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1702cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1703cb87ef4cSFlorian Wechsung } 1704cb87ef4cSFlorian Wechsung } 1705cb87ef4cSFlorian Wechsung } 1706cb87ef4cSFlorian Wechsung } 1707cb87ef4cSFlorian Wechsung 1708252a1336SBarry Smith /* Build a graph with one vertex per core representing the 1709cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1710cf818975SFlorian Wechsung * point. */ 17119566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout)); 17129566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned)); 17139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 17149566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &cumSumVertices)); 17159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &globalNumbersOfLocalOwnedVertices)); 17165a427404SJunchao Zhang for (i = 0; i < pEnd - pStart; i++) { globalNumbersOfLocalOwnedVertices[i] = pStart - 1; } 1717cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1718cb87ef4cSFlorian Wechsung counter = 0; 1719cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1720cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17217f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1722cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1723cb87ef4cSFlorian Wechsung counter++; 1724cb87ef4cSFlorian Wechsung } 1725cb87ef4cSFlorian Wechsung } 1726cb87ef4cSFlorian Wechsung } 1727cb87ef4cSFlorian Wechsung 1728cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 17299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &leafGlobalNumbers)); 17309566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE)); 17319566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE)); 1732cb87ef4cSFlorian Wechsung 1733252a1336SBarry Smith /* Build the graph for partitioning */ 1734252a1336SBarry Smith numRows = 1 + numNonExclusivelyOwned; 1735252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 17369566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 1737252a1336SBarry Smith PetscCall(MatSetType(A, MATMPIADJ)); 1738252a1336SBarry Smith PetscCall(MatSetSizes(A, numRows, numRows, cumSumVertices[size], cumSumVertices[size])); 1739252a1336SBarry Smith idx = cumSumVertices[rank]; 17404baf1206SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 17414baf1206SFlorian Wechsung if (toBalance[i]) { 17420faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17430faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17440faf6628SFlorian Wechsung else continue; 17459566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, idx, jdx, 1, INSERT_VALUES)); 17469566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, jdx, idx, 1, INSERT_VALUES)); 17470941debbSFlorian Wechsung } 17480941debbSFlorian Wechsung } 1749252a1336SBarry Smith PetscCall(PetscFree(globalNumbersOfLocalOwnedVertices)); 1750252a1336SBarry Smith PetscCall(PetscFree(leafGlobalNumbers)); 17519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 1753252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 17544baf1206SFlorian Wechsung 175541525646SFlorian Wechsung nparts = size; 1756252a1336SBarry Smith ncon = 1; 17579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * nparts, &tpwgts)); 17589371c9d4SSatish Balay for (i = 0; i < ncon * nparts; i++) { tpwgts[i] = 1. / (nparts); } 17599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon, &ubvec)); 1760252a1336SBarry Smith ubvec[0] = 1.05; 1761252a1336SBarry Smith ubvec[1] = 1.05; 17628c9a1619SFlorian Wechsung 17639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * (1 + numNonExclusivelyOwned), &vtxwgt)); 1764252a1336SBarry Smith if (ncon == 2) { 176541525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 1766252a1336SBarry Smith vtxwgt[1] = 1; 176741525646SFlorian Wechsung for (i = 0; i < numNonExclusivelyOwned; i++) { 176841525646SFlorian Wechsung vtxwgt[ncon * (i + 1)] = 1; 1769252a1336SBarry Smith vtxwgt[ncon * (i + 1) + 1] = 0; 1770252a1336SBarry Smith } 1771252a1336SBarry Smith } else { 1772252a1336SBarry Smith PetscInt base, ms; 1773252a1336SBarry Smith PetscCallMPI(MPI_Allreduce(&numExclusivelyOwned, &base, 1, MPIU_INT, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1774252a1336SBarry Smith PetscCall(MatGetSize(A, &ms, NULL)); 1775252a1336SBarry Smith ms -= size; 1776252a1336SBarry Smith base = PetscMax(base, ms); 1777252a1336SBarry Smith vtxwgt[0] = base + numExclusivelyOwned; 17789371c9d4SSatish Balay for (i = 0; i < numNonExclusivelyOwned; i++) { vtxwgt[i + 1] = 1; } 177941525646SFlorian Wechsung } 17808c9a1619SFlorian Wechsung 17815dc86ac1SFlorian Wechsung if (viewer) { 178263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %" PetscInt_FMT " on interface of mesh distribution.\n", entityDepth)); 178363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %" PetscInt_FMT "\n", cumSumVertices[size])); 178412617df9SFlorian Wechsung } 1785252a1336SBarry Smith /* TODO: Drop the parallel/sequential choice here and just use MatPartioner for much more flexibility */ 1786252a1336SBarry Smith if (usematpartitioning) { 1787252a1336SBarry Smith const char *prefix; 1788252a1336SBarry Smith 1789252a1336SBarry Smith PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)dm), &mp)); 1790252a1336SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mp, "dm_plex_rebalance_shared_points_")); 1791252a1336SBarry Smith PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1792252a1336SBarry Smith PetscCall(PetscObjectPrependOptionsPrefix((PetscObject)mp, prefix)); 1793252a1336SBarry Smith PetscCall(MatPartitioningSetAdjacency(mp, A)); 1794252a1336SBarry Smith PetscCall(MatPartitioningSetNumberVertexWeights(mp, ncon)); 1795252a1336SBarry Smith PetscCall(MatPartitioningSetVertexWeights(mp, vtxwgt)); 1796252a1336SBarry Smith PetscCall(MatPartitioningSetFromOptions(mp)); 1797252a1336SBarry Smith PetscCall(MatPartitioningApply(mp, &ispart)); 1798252a1336SBarry Smith PetscCall(ISGetIndices(ispart, (const PetscInt **)&part)); 1799252a1336SBarry Smith } else if (parallel) { 1800252a1336SBarry Smith if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n")); 1801252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part)); 1802252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done)); 1803252a1336SBarry Smith PetscCheck(done, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Could not get adjacency information"); 18049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(4, &options)); 18055a30b08bSFlorian Wechsung options[0] = 1; 18065a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 1807252a1336SBarry Smith if (viewer) options[1] = 1; 18085a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18095a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 1810252a1336SBarry Smith wgtflag = 2; 1811252a1336SBarry Smith numflag = 0; 18128c9a1619SFlorian Wechsung if (useInitialGuess) { 1813252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "THIS DOES NOT WORK! I don't know why. Using current distribution of points as initial guess.\n")); 1814252a1336SBarry Smith for (i = 0; i < numRows; i++) part[i] = rank; 18159566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n")); 1816792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_RefineKway"); 1817252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1818252a1336SBarry 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); 1819252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 18208c9a1619SFlorian Wechsung PetscStackPop; 1821252a1336SBarry Smith PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18228c9a1619SFlorian Wechsung } else { 1823792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_PartKway"); 1824252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1825252a1336SBarry 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); 1826252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 18278c9a1619SFlorian Wechsung PetscStackPop; 18285f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18298c9a1619SFlorian Wechsung } 1830252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done)); 18319566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 183241525646SFlorian Wechsung } else { 18339566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n")); 183441525646SFlorian Wechsung Mat As; 183541525646SFlorian Wechsung PetscInt *partGlobal; 183641525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 1837252a1336SBarry Smith 1838252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part)); 1839252a1336SBarry Smith PetscCall(MatGetSize(A, &numRows, NULL)); 1840252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1841252a1336SBarry Smith PetscCall(MatMPIAdjToSeqRankZero(A, &As)); 1842252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1843252a1336SBarry Smith 18449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &numExclusivelyOwnedAll)); 184541525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 18469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, numExclusivelyOwnedAll, 1, MPIU_INT, comm)); 1847cb87ef4cSFlorian Wechsung 18489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &partGlobal)); 1849252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1850dd400576SPatrick Sanan if (rank == 0) { 1851252a1336SBarry Smith PetscInt *vtxwgt_g, numRows_g; 185241525646SFlorian Wechsung 1853252a1336SBarry Smith PetscCall(MatGetRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done)); 1854252a1336SBarry Smith PetscCall(PetscMalloc1(2 * numRows_g, &vtxwgt_g)); 185541525646SFlorian Wechsung for (i = 0; i < size; i++) { 185641525646SFlorian Wechsung vtxwgt_g[ncon * cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 185741525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[ncon * cumSumVertices[i] + 1] = 1; 185841525646SFlorian Wechsung for (j = cumSumVertices[i] + 1; j < cumSumVertices[i + 1]; j++) { 185941525646SFlorian Wechsung vtxwgt_g[ncon * j] = 1; 186041525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[2 * j + 1] = 0; 186141525646SFlorian Wechsung } 186241525646SFlorian Wechsung } 1863252a1336SBarry Smith 18649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(64, &options)); 186541525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 18665f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 186741525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 1868792fecdfSBarry Smith PetscStackPushExternal("METIS_PartGraphKway"); 1869252a1336SBarry Smith ierr = METIS_PartGraphKway(&numRows_g, &ncon, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 187041525646SFlorian Wechsung PetscStackPop; 18715f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 18729566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 18739566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt_g)); 1874252a1336SBarry Smith PetscCall(MatRestoreRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done)); 1875252a1336SBarry Smith PetscCall(MatDestroy(&As)); 187641525646SFlorian Wechsung } 1877252a1336SBarry Smith PetscCall(PetscBarrier((PetscObject)dm)); 1878252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 18799566063dSJacob Faibussowitsch PetscCall(PetscFree(numExclusivelyOwnedAll)); 188041525646SFlorian Wechsung 1881252a1336SBarry Smith /* scatter the partitioning information to ranks */ 1882252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalScatterPart, 0, 0, 0, 0)); 18839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &counts)); 18849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size + 1, &mpiCumSumVertices)); 1885*48a46eb9SPierre Jolivet for (i = 0; i < size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i + 1] - cumSumVertices[i], &(counts[i]))); 1886*48a46eb9SPierre Jolivet for (i = 0; i <= size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]))); 18879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm)); 18889566063dSJacob Faibussowitsch PetscCall(PetscFree(counts)); 18899566063dSJacob Faibussowitsch PetscCall(PetscFree(mpiCumSumVertices)); 18909566063dSJacob Faibussowitsch PetscCall(PetscFree(partGlobal)); 1891252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalScatterPart, 0, 0, 0, 0)); 189241525646SFlorian Wechsung } 18939566063dSJacob Faibussowitsch PetscCall(PetscFree(ubvec)); 18949566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts)); 1895cb87ef4cSFlorian Wechsung 1896252a1336SBarry Smith /* Rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1897252a1336SBarry Smith PetscCall(PetscMalloc2(size, &firstVertices, size, &renumbering)); 1898cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 18999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, firstVertices, 1, MPIU_INT, comm)); 19009371c9d4SSatish Balay for (i = 0; i < size; i++) { renumbering[firstVertices[i]] = i; } 19019371c9d4SSatish Balay for (i = 0; i < cumSumVertices[rank + 1] - cumSumVertices[rank]; i++) { part[i] = renumbering[part[i]]; } 1902252a1336SBarry Smith PetscCall(PetscFree2(firstVertices, renumbering)); 1903252a1336SBarry Smith 1904cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1905cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 19069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm)); 1907cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 1908252a1336SBarry Smith PetscCheck(failedGlobal <= 0, comm, PETSC_ERR_LIB, "Metis/Parmetis returned a bad partion"); 19099566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt)); 19109566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 19119566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 19129566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 19139566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 1914252a1336SBarry Smith if (usematpartitioning) { 1915252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part)); 1916252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 1917252a1336SBarry Smith } else PetscCall(PetscFree(part)); 19187f57c1a4SFlorian Wechsung if (viewer) { 19199566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 19209566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 19217f57c1a4SFlorian Wechsung } 19229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 19238b879b41SFlorian Wechsung PetscFunctionReturn(0); 1924cb87ef4cSFlorian Wechsung } 1925cb87ef4cSFlorian Wechsung 1926252a1336SBarry Smith /* Check how well we did distributing points*/ 19275dc86ac1SFlorian Wechsung if (viewer) { 1928252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Number of owned entities of depth %" PetscInt_FMT ".\n", entityDepth)); 1929252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Initial ")); 19309566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, NULL, viewer)); 1931252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Rebalanced ")); 19329566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 19337407ba93SFlorian Wechsung } 19347407ba93SFlorian Wechsung 1935252a1336SBarry Smith /* Check that every vertex is owned by a process that it is actually connected to. */ 1936252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 193741525646SFlorian Wechsung for (i = 1; i <= numNonExclusivelyOwned; i++) { 1938cb87ef4cSFlorian Wechsung PetscInt loc = 0; 19399566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cumSumVertices[part[i]], xadj[i + 1] - xadj[i], &adjncy[xadj[i]], &loc)); 19407407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 19419371c9d4SSatish Balay if (loc < 0) { part[i] = rank; } 1942cb87ef4cSFlorian Wechsung } 1943252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 1944252a1336SBarry Smith PetscCall(MatDestroy(&A)); 1945cb87ef4cSFlorian Wechsung 1946252a1336SBarry Smith /* See how significant the influences of the previous fixing up step was.*/ 19475dc86ac1SFlorian Wechsung if (viewer) { 1948252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "After fix ")); 19499566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 19507407ba93SFlorian Wechsung } 1951252a1336SBarry Smith if (!usematpartitioning) PetscCall(PetscFree(vtxwgt)); 1952252a1336SBarry Smith else PetscCall(MatPartitioningDestroy(&mp)); 19537407ba93SFlorian Wechsung 19549566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 1955cb87ef4cSFlorian Wechsung 1956252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 1957252a1336SBarry Smith /* Rewrite the SF to reflect the new ownership. */ 19589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite)); 19597f57c1a4SFlorian Wechsung counter = 0; 1960cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1961cb87ef4cSFlorian Wechsung if (toBalance[i]) { 1962cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 19637f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 1964cb87ef4cSFlorian Wechsung counter++; 1965cb87ef4cSFlorian Wechsung } 1966cb87ef4cSFlorian Wechsung } 1967cb87ef4cSFlorian Wechsung } 19689566063dSJacob Faibussowitsch PetscCall(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part + 1, degrees)); 19699566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsToRewrite)); 1970252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 1971cb87ef4cSFlorian Wechsung 19729566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 19739566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 19749566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 19759566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 1976252a1336SBarry Smith if (usematpartitioning) { 1977252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part)); 1978252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 1979252a1336SBarry Smith } else PetscCall(PetscFree(part)); 19805dc86ac1SFlorian Wechsung if (viewer) { 19819566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 19829566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 19837d197802SFlorian Wechsung } 19848b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 19859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 1986b458e8f1SJose E. Roman PetscFunctionReturn(0); 1987240408d3SFlorian Wechsung #else 19885f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 198941525646SFlorian Wechsung #endif 1990cb87ef4cSFlorian Wechsung } 1991