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 79fbee547SJacob Faibussowitsch static inline PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 80134a67bSLisandro Dalcin 95a107427SMatthew G. Knepley static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 105a107427SMatthew G. Knepley { 115a107427SMatthew G. Knepley DM ovdm; 125a107427SMatthew G. Knepley PetscSF sfPoint; 135a107427SMatthew G. Knepley IS cellNumbering; 145a107427SMatthew G. Knepley const PetscInt *cellNum; 155a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL; 165a107427SMatthew G. Knepley PetscBool useCone, useClosure; 175a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v; 185a107427SMatthew G. Knepley PetscMPIInt rank, size; 195a107427SMatthew G. Knepley 205a107427SMatthew G. Knepley PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size)); 239566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 255a107427SMatthew G. Knepley if (dim != depth) { 265a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 285a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 299566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 305a107427SMatthew G. Knepley /* Different behavior for empty graphs */ 315a107427SMatthew G. Knepley if (!*numVertices) { 329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 335a107427SMatthew G. Knepley (*offsets)[0] = 0; 345a107427SMatthew G. Knepley } 355a107427SMatthew G. Knepley /* Broken in parallel */ 365f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 375a107427SMatthew G. Knepley PetscFunctionReturn(0); 385a107427SMatthew G. Knepley } 395a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */ 409566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 419566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 425a107427SMatthew G. Knepley /* Need overlap >= 1 */ 439566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 445a107427SMatthew G. Knepley if (size && overlap < 1) { 459566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(dm, 1, NULL, &ovdm)); 465a107427SMatthew G. Knepley } else { 479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm)); 485a107427SMatthew G. Knepley ovdm = dm; 495a107427SMatthew G. Knepley } 509566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(ovdm, &sfPoint)); 519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd)); 529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering)); 535a107427SMatthew G. Knepley if (globalNumbering) { 549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) cellNumbering)); 555a107427SMatthew G. Knepley *globalNumbering = cellNumbering; 565a107427SMatthew G. Knepley } 579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 585a107427SMatthew G. Knepley /* Determine sizes */ 595a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) { 605a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 61b68380d8SVaclav Hapla if (cellNum[c-cStart] < 0) continue; 625a107427SMatthew G. Knepley (*numVertices)++; 635a107427SMatthew G. Knepley } 649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(*numVertices+1, &vOffsets)); 655a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 665a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0; 675a107427SMatthew G. Knepley 68b68380d8SVaclav Hapla if (cellNum[c-cStart] < 0) continue; 699566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 705a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 715a107427SMatthew G. Knepley const PetscInt point = adj[a]; 725a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize; 735a107427SMatthew G. Knepley } 745a107427SMatthew G. Knepley vOffsets[v+1] = vOffsets[v] + vsize; 755a107427SMatthew G. Knepley ++v; 765a107427SMatthew G. Knepley } 775a107427SMatthew G. Knepley /* Determine adjacency */ 789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vOffsets[*numVertices], &vAdj)); 795a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 805a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v]; 815a107427SMatthew G. Knepley 825a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 83b68380d8SVaclav Hapla if (cellNum[c-cStart] < 0) continue; 849566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 855a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 865a107427SMatthew G. Knepley const PetscInt point = adj[a]; 875a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) { 88b68380d8SVaclav Hapla vAdj[off++] = DMPlex_GlobalID(cellNum[point-cStart]); 895a107427SMatthew G. Knepley } 905a107427SMatthew G. Knepley } 9163a3b9bcSJacob Faibussowitsch PetscCheck(off == vOffsets[v+1],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %" PetscInt_FMT " should be %" PetscInt_FMT, off, vOffsets[v+1]); 925a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */ 939566063dSJacob Faibussowitsch PetscCall(PetscSortInt(off-vOffsets[v], &vAdj[vOffsets[v]])); 945a107427SMatthew G. Knepley ++v; 955a107427SMatthew G. Knepley } 969566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 999566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 1009566063dSJacob Faibussowitsch PetscCall(DMDestroy(&ovdm)); 1015a107427SMatthew G. Knepley if (offsets) {*offsets = vOffsets;} 1029566063dSJacob Faibussowitsch else PetscCall(PetscFree(vOffsets)); 1035a107427SMatthew G. Knepley if (adjacency) {*adjacency = vAdj;} 1049566063dSJacob Faibussowitsch else PetscCall(PetscFree(vAdj)); 1055a107427SMatthew G. Knepley PetscFunctionReturn(0); 1065a107427SMatthew G. Knepley } 1075a107427SMatthew G. Knepley 108bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 109532c4e7dSMichael Lange { 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) */ 210b68380d8SVaclav Hapla if (nroots > 0) {if (cellNum[p-pStart] < 0) continue;} 2118f4e72b9SMatthew G. Knepley /* Add remote cells */ 2128f4e72b9SMatthew G. Knepley if (remoteCells) { 213b68380d8SVaclav Hapla const PetscInt gp = DMPlex_GlobalID(cellNum[p-pStart]); 2140134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 2150134a67bSLisandro Dalcin const PetscInt *cone, *children; 2160134a67bSLisandro Dalcin 2179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 2189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 2198f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 2200134a67bSLisandro Dalcin const PetscInt point = cone[c]; 2210134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 2228f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 2239566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2249566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2250134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 2260134a67bSLisandro Dalcin } 2270134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 2289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 2290134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 2300134a67bSLisandro Dalcin const PetscInt child = children[i]; 2310134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 2320134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 2339566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2349566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2350134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 2360134a67bSLisandro Dalcin } 2378f4e72b9SMatthew G. Knepley } 2388f4e72b9SMatthew G. Knepley } 2398f4e72b9SMatthew G. Knepley } 2408f4e72b9SMatthew G. Knepley /* Add local cells */ 241532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 2429566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 243532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 244532c4e7dSMichael Lange const PetscInt point = adj[a]; 245532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 246532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 2479566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2489566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 249b68380d8SVaclav Hapla *pBuf = DMPlex_GlobalID(cellNum[point-pStart]); 250532c4e7dSMichael Lange } 251532c4e7dSMichael Lange } 2528cfe4c1fSMichael Lange (*numVertices)++; 253532c4e7dSMichael Lange } 2549566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2559566063dSJacob Faibussowitsch PetscCall(PetscFree2(adjCells, remoteCells)); 2569566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2574e468a93SLisandro Dalcin 258532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 2599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices+1, &vOffsets)); 26243f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 263b68380d8SVaclav Hapla if (nroots > 0) {if (cellNum[p-pStart] < 0) continue;} 2649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 26543f7d02bSMichael Lange } 266532c4e7dSMichael Lange vOffsets[*numVertices] = size; 2679566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2684e468a93SLisandro Dalcin 2694e468a93SLisandro Dalcin if (nroots >= 0) { 2704e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 2719566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(section)); 2729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, 0, *numVertices)); 2734e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2744e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2754e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 2769566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&numEdges, &graph[start])); 2779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numEdges)); 2789566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, numEdges, &edges)); 2799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(edges, &graph[start], numEdges)); 2804e468a93SLisandro Dalcin } 2819566063dSJacob Faibussowitsch PetscCall(PetscFree(vOffsets)); 2829566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2834e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices+1, &vOffsets)); 2874e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 2889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 2894e468a93SLisandro Dalcin } 2904e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2919566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2924e468a93SLisandro Dalcin } else { 2934e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2944e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2954e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2969566063dSJacob Faibussowitsch PetscCall(PetscSortInt(end-start, &graph[start])); 2974e468a93SLisandro Dalcin } 2984e468a93SLisandro Dalcin } 2994e468a93SLisandro Dalcin 3004e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 301389e55d8SMichael Lange if (adjacency) *adjacency = graph; 3024e468a93SLisandro Dalcin 303532c4e7dSMichael Lange /* Cleanup */ 3049566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 3059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 3069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 3079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 308532c4e7dSMichael Lange PetscFunctionReturn(0); 309532c4e7dSMichael Lange } 310532c4e7dSMichael Lange 311bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 312bbbc8e51SStefano Zampini { 313bbbc8e51SStefano Zampini Mat conn, CSR; 314bbbc8e51SStefano Zampini IS fis, cis, cis_own; 315bbbc8e51SStefano Zampini PetscSF sfPoint; 316bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 317bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 31883c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 319bbbc8e51SStefano Zampini PetscMPIInt rank; 320bbbc8e51SStefano Zampini PetscBool flg; 321bbbc8e51SStefano Zampini 322bbbc8e51SStefano Zampini PetscFunctionBegin; 3239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 3249566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 326bbbc8e51SStefano Zampini if (dim != depth) { 327bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 3289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 329bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 3309566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 331bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 332bbbc8e51SStefano Zampini if (!*numVertices) { 3339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 334bbbc8e51SStefano Zampini (*offsets)[0] = 0; 335bbbc8e51SStefano Zampini } 336bbbc8e51SStefano Zampini /* Broken in parallel */ 3375f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 338bbbc8e51SStefano Zampini PetscFunctionReturn(0); 339bbbc8e51SStefano Zampini } 340bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 341bbbc8e51SStefano Zampini 342bbbc8e51SStefano Zampini /* numbering */ 3439566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 3449566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 3459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd)); 3469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis)); 3479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis)); 3481baa6e33SBarry Smith if (globalNumbering) PetscCall(ISDuplicate(cis, globalNumbering)); 349bbbc8e51SStefano Zampini 350bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 3519566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fis, &m)); 3529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 354bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 355bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 356bbbc8e51SStefano Zampini 357bbbc8e51SStefano Zampini if (p < 0) { 358bbbc8e51SStefano Zampini idxs[i] = -(p+1); 359bbbc8e51SStefano Zampini } else { 360bbbc8e51SStefano Zampini idxs[i] = p; 361bbbc8e51SStefano Zampini floc += 1; 362bbbc8e51SStefano Zampini } 363bbbc8e51SStefano Zampini } 3649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 3659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis)); 367bbbc8e51SStefano Zampini 3689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cis, &m)); 3699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 3709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 3719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs2)); 372bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 373bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 374bbbc8e51SStefano Zampini 375bbbc8e51SStefano Zampini if (p < 0) { 376bbbc8e51SStefano Zampini idxs[i] = -(p+1); 377bbbc8e51SStefano Zampini } else { 378bbbc8e51SStefano Zampini idxs[i] = p; 379bbbc8e51SStefano Zampini idxs2[cloc++] = p; 380bbbc8e51SStefano Zampini } 381bbbc8e51SStefano Zampini } 3829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 3839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 3849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis)); 3859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own)); 386bbbc8e51SStefano Zampini 387bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 3889566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &conn)); 3899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(conn, floc, cloc, M, N)); 3909566063dSJacob Faibussowitsch PetscCall(MatSetType(conn, MATMPIAIJ)); 3919566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, NULL, &lm)); 3929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 3939566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL)); 394bbbc8e51SStefano Zampini 395bbbc8e51SStefano Zampini /* Assemble matrix */ 3969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 398bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 399bbbc8e51SStefano Zampini const PetscInt *cone; 400bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 401bbbc8e51SStefano Zampini 402bbbc8e51SStefano Zampini col = cols[c-cStart]; 4039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 4049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 405bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 406bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 407bbbc8e51SStefano Zampini const PetscInt *children; 408bbbc8e51SStefano Zampini PetscInt numChildren, ch; 409bbbc8e51SStefano Zampini 410bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 4119566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 412bbbc8e51SStefano Zampini 413bbbc8e51SStefano Zampini /* non-conforming meshes */ 4149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children)); 415bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 416bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 417bbbc8e51SStefano Zampini 418bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 419bbbc8e51SStefano Zampini row = rows[child-fStart]; 4209566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 421bbbc8e51SStefano Zampini } 422bbbc8e51SStefano Zampini } 423bbbc8e51SStefano Zampini } 4249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 4259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 4269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 4289566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY)); 4299566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY)); 430bbbc8e51SStefano Zampini 431bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 4329566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR)); 4339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 434bbbc8e51SStefano Zampini 435bbbc8e51SStefano Zampini /* extract local part of the CSR */ 4369566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn)); 4379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CSR)); 4389566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4395f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 440bbbc8e51SStefano Zampini 441bbbc8e51SStefano Zampini /* get back requested output */ 442bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 443bbbc8e51SStefano Zampini if (offsets) { 4449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m+1, &idxs)); 445bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 446bbbc8e51SStefano Zampini *offsets = idxs; 447bbbc8e51SStefano Zampini } 448bbbc8e51SStefano Zampini if (adjacency) { 4499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ii[m] - m, &idxs)); 4509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis_own, &rows)); 451bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 452bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 453bbbc8e51SStefano Zampini 454bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 455bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 456bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 457bbbc8e51SStefano Zampini } 458bbbc8e51SStefano Zampini } 45963a3b9bcSJacob Faibussowitsch PetscCheck(c == ii[m] - m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,c,ii[m]-m); 4609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis_own, &rows)); 461bbbc8e51SStefano Zampini *adjacency = idxs; 462bbbc8e51SStefano Zampini } 463bbbc8e51SStefano Zampini 464bbbc8e51SStefano Zampini /* cleanup */ 4659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis_own)); 4669566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4675f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 4689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 469bbbc8e51SStefano Zampini PetscFunctionReturn(0); 470bbbc8e51SStefano Zampini } 471bbbc8e51SStefano Zampini 472bbbc8e51SStefano Zampini /*@C 473bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 474bbbc8e51SStefano Zampini 475bbbc8e51SStefano Zampini Input Parameters: 476bbbc8e51SStefano Zampini + dm - The mesh DM dm 477bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 478bbbc8e51SStefano Zampini 479d8d19677SJose E. Roman Output Parameters: 480bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 481bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 482bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 483bbbc8e51SStefano 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. 484bbbc8e51SStefano Zampini 485bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 486bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 487bbbc8e51SStefano Zampini 4885a107427SMatthew G. Knepley Options Database Keys: 4895a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4905a107427SMatthew G. Knepley 491bbbc8e51SStefano Zampini Level: developer 492bbbc8e51SStefano Zampini 493db781477SPatrick Sanan .seealso: `PetscPartitionerGetType()`, `PetscPartitionerCreate()`, `DMSetAdjacency()` 494bbbc8e51SStefano Zampini @*/ 495bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 496bbbc8e51SStefano Zampini { 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) { 5025a107427SMatthew G. Knepley case DM_PLEX_CSR_MAT: 5039566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5045a107427SMatthew G. Knepley case DM_PLEX_CSR_GRAPH: 5059566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5065a107427SMatthew G. Knepley case DM_PLEX_CSR_OVERLAP: 5079566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 508bbbc8e51SStefano Zampini } 509bbbc8e51SStefano Zampini PetscFunctionReturn(0); 510bbbc8e51SStefano Zampini } 511bbbc8e51SStefano Zampini 512d5577e40SMatthew G. Knepley /*@C 513d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 514d5577e40SMatthew G. Knepley 515fe2efc57SMark Collective on DM 516d5577e40SMatthew G. Knepley 5174165533cSJose E. Roman Input Parameters: 518d5577e40SMatthew G. Knepley + dm - The DMPlex 519d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 520d5577e40SMatthew G. Knepley 5214165533cSJose E. Roman Output Parameters: 522d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 523d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 524d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 525d5577e40SMatthew G. Knepley 526d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 527d5577e40SMatthew G. Knepley 528d5577e40SMatthew G. Knepley Level: advanced 529d5577e40SMatthew G. Knepley 530db781477SPatrick Sanan .seealso: `DMPlexCreate()` 531d5577e40SMatthew G. Knepley @*/ 53270034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 53370034214SMatthew G. Knepley { 53470034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 53570034214SMatthew G. Knepley PetscInt numFaceCases = 0; 53670034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 53770034214SMatthew G. Knepley PetscInt *off, *adj; 53870034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 53970034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 54070034214SMatthew G. Knepley 54170034214SMatthew G. Knepley PetscFunctionBegin; 54270034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 5439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 54470034214SMatthew G. Knepley cellDim = dim - cellHeight; 5459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5469566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 54770034214SMatthew G. Knepley if (cEnd - cStart == 0) { 54870034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 54970034214SMatthew G. Knepley if (offsets) *offsets = NULL; 55070034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 55170034214SMatthew G. Knepley PetscFunctionReturn(0); 55270034214SMatthew G. Knepley } 55370034214SMatthew G. Knepley numCells = cEnd - cStart; 55470034214SMatthew G. Knepley faceDepth = depth - cellHeight; 55570034214SMatthew G. Knepley if (dim == depth) { 55670034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 55770034214SMatthew G. Knepley 5589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells+1, &off)); 55970034214SMatthew G. Knepley /* Count neighboring cells */ 5609566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd)); 56170034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 56270034214SMatthew G. Knepley const PetscInt *support; 56370034214SMatthew G. Knepley PetscInt supportSize; 5649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 56670034214SMatthew G. Knepley if (supportSize == 2) { 5679ffc88e4SToby Isaac PetscInt numChildren; 5689ffc88e4SToby Isaac 5699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5709ffc88e4SToby Isaac if (!numChildren) { 57170034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 57270034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 57370034214SMatthew G. Knepley } 57470034214SMatthew G. Knepley } 5759ffc88e4SToby Isaac } 57670034214SMatthew G. Knepley /* Prefix sum */ 57770034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 57870034214SMatthew G. Knepley if (adjacency) { 57970034214SMatthew G. Knepley PetscInt *tmp; 58070034214SMatthew G. Knepley 5819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 5829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells+1, &tmp)); 5839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(tmp, off, numCells+1)); 58470034214SMatthew G. Knepley /* Get neighboring cells */ 58570034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 58670034214SMatthew G. Knepley const PetscInt *support; 58770034214SMatthew G. Knepley PetscInt supportSize; 5889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 59070034214SMatthew G. Knepley if (supportSize == 2) { 5919ffc88e4SToby Isaac PetscInt numChildren; 5929ffc88e4SToby Isaac 5939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5949ffc88e4SToby Isaac if (!numChildren) { 59570034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 59670034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 59770034214SMatthew G. Knepley } 59870034214SMatthew G. Knepley } 5999ffc88e4SToby Isaac } 60063a3b9bcSJacob 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); 6019566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 60270034214SMatthew G. Knepley } 60370034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 60470034214SMatthew G. Knepley if (offsets) *offsets = off; 60570034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 60670034214SMatthew G. Knepley PetscFunctionReturn(0); 60770034214SMatthew G. Knepley } 60870034214SMatthew G. Knepley /* Setup face recognition */ 60970034214SMatthew G. Knepley if (faceDepth == 1) { 61070034214SMatthew 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 */ 61170034214SMatthew G. Knepley 61270034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 61370034214SMatthew G. Knepley PetscInt corners; 61470034214SMatthew G. Knepley 6159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &corners)); 61670034214SMatthew G. Knepley if (!cornersSeen[corners]) { 61770034214SMatthew G. Knepley PetscInt nFV; 61870034214SMatthew G. Knepley 6195f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 62070034214SMatthew G. Knepley cornersSeen[corners] = 1; 62170034214SMatthew G. Knepley 6229566063dSJacob Faibussowitsch PetscCall(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV)); 62370034214SMatthew G. Knepley 62470034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 62570034214SMatthew G. Knepley } 62670034214SMatthew G. Knepley } 62770034214SMatthew G. Knepley } 6289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells+1, &off)); 62970034214SMatthew G. Knepley /* Count neighboring cells */ 63070034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 63170034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 63270034214SMatthew G. Knepley 6339566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 63470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 63570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 63670034214SMatthew G. Knepley PetscInt cellPair[2]; 63770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 63870034214SMatthew G. Knepley PetscInt meetSize = 0; 63970034214SMatthew G. Knepley const PetscInt *meet = NULL; 64070034214SMatthew G. Knepley 64170034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 64270034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 64370034214SMatthew G. Knepley if (!found) { 6449566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 64570034214SMatthew G. Knepley if (meetSize) { 64670034214SMatthew G. Knepley PetscInt f; 64770034214SMatthew G. Knepley 64870034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 64970034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 65070034214SMatthew G. Knepley found = PETSC_TRUE; 65170034214SMatthew G. Knepley break; 65270034214SMatthew G. Knepley } 65370034214SMatthew G. Knepley } 65470034214SMatthew G. Knepley } 6559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 65670034214SMatthew G. Knepley } 65770034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 65870034214SMatthew G. Knepley } 65970034214SMatthew G. Knepley } 66070034214SMatthew G. Knepley /* Prefix sum */ 66170034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 66270034214SMatthew G. Knepley 66370034214SMatthew G. Knepley if (adjacency) { 6649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 66570034214SMatthew G. Knepley /* Get neighboring cells */ 66670034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 66770034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 66870034214SMatthew G. Knepley PetscInt cellOffset = 0; 66970034214SMatthew G. Knepley 6709566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 67170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 67270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 67370034214SMatthew G. Knepley PetscInt cellPair[2]; 67470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 67570034214SMatthew G. Knepley PetscInt meetSize = 0; 67670034214SMatthew G. Knepley const PetscInt *meet = NULL; 67770034214SMatthew G. Knepley 67870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 67970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 68070034214SMatthew G. Knepley if (!found) { 6819566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 68270034214SMatthew G. Knepley if (meetSize) { 68370034214SMatthew G. Knepley PetscInt f; 68470034214SMatthew G. Knepley 68570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 68670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 68770034214SMatthew G. Knepley found = PETSC_TRUE; 68870034214SMatthew G. Knepley break; 68970034214SMatthew G. Knepley } 69070034214SMatthew G. Knepley } 69170034214SMatthew G. Knepley } 6929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 69370034214SMatthew G. Knepley } 69470034214SMatthew G. Knepley if (found) { 69570034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 69670034214SMatthew G. Knepley ++cellOffset; 69770034214SMatthew G. Knepley } 69870034214SMatthew G. Knepley } 69970034214SMatthew G. Knepley } 70070034214SMatthew G. Knepley } 7019566063dSJacob Faibussowitsch PetscCall(PetscFree(neighborCells)); 70270034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 70370034214SMatthew G. Knepley if (offsets) *offsets = off; 70470034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 70570034214SMatthew G. Knepley PetscFunctionReturn(0); 70670034214SMatthew G. Knepley } 70770034214SMatthew G. Knepley 70877623264SMatthew G. Knepley /*@ 7093c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 71077623264SMatthew G. Knepley 711fe2efc57SMark Collective on PetscPartitioner 71277623264SMatthew G. Knepley 71377623264SMatthew G. Knepley Input Parameters: 71477623264SMatthew G. Knepley + part - The PetscPartitioner 7153c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 716f8987ae8SMichael Lange - dm - The mesh DM 71777623264SMatthew G. Knepley 71877623264SMatthew G. Knepley Output Parameters: 71977623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 720f8987ae8SMichael Lange - partition - The list of points by partition 72177623264SMatthew G. Knepley 7223c41b853SStefano Zampini Notes: 7233c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 7243c41b853SStefano Zampini by the section in the transitive closure of the point. 72577623264SMatthew G. Knepley 72677623264SMatthew G. Knepley Level: developer 72777623264SMatthew G. Knepley 728db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `PetscPartitionerCreate()`, `PetscSectionCreate()`, `PetscSectionSetChart()`, `PetscPartitionerPartition()` 7294b15ede2SMatthew G. Knepley @*/ 7303c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 73177623264SMatthew G. Knepley { 73277623264SMatthew G. Knepley PetscMPIInt size; 7333c41b853SStefano Zampini PetscBool isplex; 7343c41b853SStefano Zampini PetscSection vertSection = NULL; 73577623264SMatthew G. Knepley 73677623264SMatthew G. Knepley PetscFunctionBegin; 73777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 73877623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7393c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 74077623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 74177623264SMatthew G. Knepley PetscValidPointer(partition, 5); 7429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex)); 7435f80ce2aSJacob Faibussowitsch PetscCheck(isplex,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 7449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) part), &size)); 74577623264SMatthew G. Knepley if (size == 1) { 74677623264SMatthew G. Knepley PetscInt *points; 74777623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 74877623264SMatthew G. Knepley 7499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 7509566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(partSection)); 7519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(partSection, 0, size)); 7529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(partSection, 0, cEnd-cStart)); 7539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(partSection)); 7549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd-cStart, &points)); 75577623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 7569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition)); 75777623264SMatthew G. Knepley PetscFunctionReturn(0); 75877623264SMatthew G. Knepley } 75977623264SMatthew G. Knepley if (part->height == 0) { 760074d466cSStefano Zampini PetscInt numVertices = 0; 76177623264SMatthew G. Knepley PetscInt *start = NULL; 76277623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7633fa7752dSToby Isaac IS globalNumbering; 76477623264SMatthew G. Knepley 765074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 7669566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering)); 76713911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 768074d466cSStefano Zampini const PetscInt *idxs; 769074d466cSStefano Zampini PetscInt p, pStart, pEnd; 770074d466cSStefano Zampini 7719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering)); 7739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &idxs)); 774074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 7759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &idxs)); 776074d466cSStefano Zampini } 7773c41b853SStefano Zampini if (part->usevwgt) { 7783c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7793c41b853SStefano Zampini IS clPoints = NULL; 7803c41b853SStefano Zampini const PetscInt *gid,*clIdx; 7813c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7820358368aSMatthew G. Knepley 7833c41b853SStefano 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) */ 7843c41b853SStefano Zampini /* We do this only if the local section has been set */ 7853c41b853SStefano Zampini if (section) { 7869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL)); 7873c41b853SStefano Zampini if (!clSection) { 7889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateClosureIndex(dm,NULL)); 7893c41b853SStefano Zampini } 7909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints)); 7919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(clPoints,&clIdx)); 7923c41b853SStefano Zampini } 7939566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &vertSection)); 7959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(vertSection, 0, numVertices)); 7963c41b853SStefano Zampini if (globalNumbering) { 7979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering,&gid)); 7983c41b853SStefano Zampini } else gid = NULL; 7993c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 8003c41b853SStefano Zampini PetscInt dof = 1; 8010358368aSMatthew G. Knepley 8023c41b853SStefano Zampini /* skip cells in the overlap */ 8033c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 8043c41b853SStefano Zampini 8053c41b853SStefano Zampini if (section) { 8063c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8073c41b853SStefano Zampini 8083c41b853SStefano Zampini dof = 0; 8099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(clSection, p, &clSize)); 8109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(clSection, p, &clOff)); 8113c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 8123c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8133c41b853SStefano Zampini 8149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, clPoint, &clDof)); 8153c41b853SStefano Zampini dof += clDof; 8160358368aSMatthew G. Knepley } 8170358368aSMatthew G. Knepley } 81863a3b9bcSJacob Faibussowitsch PetscCheck(dof,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %" PetscInt_FMT " in the local section should be positive",p); 8199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(vertSection, v, dof)); 8203c41b853SStefano Zampini v++; 8213c41b853SStefano Zampini } 8223c41b853SStefano Zampini if (globalNumbering) { 8239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering,&gid)); 8243c41b853SStefano Zampini } 8253c41b853SStefano Zampini if (clPoints) { 8269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(clPoints,&clIdx)); 8273c41b853SStefano Zampini } 8289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(vertSection)); 8293c41b853SStefano Zampini } 8309566063dSJacob Faibussowitsch PetscCall(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition)); 8319566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 8329566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 8333fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8343fa7752dSToby Isaac const PetscInt *globalNum; 8353fa7752dSToby Isaac const PetscInt *partIdx; 8363fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8373fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8383fa7752dSToby Isaac IS newPartition; 8393fa7752dSToby Isaac 8409566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*partition,&localSize)); 8419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize,&adjusted)); 8429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering,&globalNum)); 8439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*partition,&partIdx)); 8449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize,&map)); 8459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 8463fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8473fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8483fa7752dSToby Isaac } 8493fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 8503fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 8513fa7752dSToby Isaac } 8529566063dSJacob Faibussowitsch PetscCall(PetscFree(map)); 8539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*partition,&partIdx)); 8549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering,&globalNum)); 8559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition)); 8569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalNumbering)); 8579566063dSJacob Faibussowitsch PetscCall(ISDestroy(partition)); 8583fa7752dSToby Isaac *partition = newPartition; 8593fa7752dSToby Isaac } 86063a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %" PetscInt_FMT " for points to partition", part->height); 8619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&vertSection)); 86277623264SMatthew G. Knepley PetscFunctionReturn(0); 86377623264SMatthew G. Knepley } 86477623264SMatthew G. Knepley 8655680f57bSMatthew G. Knepley /*@ 8665680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8675680f57bSMatthew G. Knepley 8685680f57bSMatthew G. Knepley Not collective 8695680f57bSMatthew G. Knepley 8705680f57bSMatthew G. Knepley Input Parameter: 8715680f57bSMatthew G. Knepley . dm - The DM 8725680f57bSMatthew G. Knepley 8735680f57bSMatthew G. Knepley Output Parameter: 8745680f57bSMatthew G. Knepley . part - The PetscPartitioner 8755680f57bSMatthew G. Knepley 8765680f57bSMatthew G. Knepley Level: developer 8775680f57bSMatthew G. Knepley 87898599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 87998599a47SLawrence Mitchell 880db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `DMPlexSetPartitioner()`, `PetscPartitionerDMPlexPartition()`, `PetscPartitionerCreate()` 8815680f57bSMatthew G. Knepley @*/ 8825680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 8835680f57bSMatthew G. Knepley { 8845680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 8855680f57bSMatthew G. Knepley 8865680f57bSMatthew G. Knepley PetscFunctionBegin; 8875680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8885680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 8895680f57bSMatthew G. Knepley *part = mesh->partitioner; 8905680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8915680f57bSMatthew G. Knepley } 8925680f57bSMatthew G. Knepley 89371bb2955SLawrence Mitchell /*@ 89471bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 89571bb2955SLawrence Mitchell 896fe2efc57SMark logically collective on DM 89771bb2955SLawrence Mitchell 89871bb2955SLawrence Mitchell Input Parameters: 89971bb2955SLawrence Mitchell + dm - The DM 90071bb2955SLawrence Mitchell - part - The partitioner 90171bb2955SLawrence Mitchell 90271bb2955SLawrence Mitchell Level: developer 90371bb2955SLawrence Mitchell 90471bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 90571bb2955SLawrence Mitchell 906db781477SPatrick Sanan .seealso `DMPlexDistribute()`, `DMPlexGetPartitioner()`, `PetscPartitionerCreate()` 90771bb2955SLawrence Mitchell @*/ 90871bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 90971bb2955SLawrence Mitchell { 91071bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 91171bb2955SLawrence Mitchell 91271bb2955SLawrence Mitchell PetscFunctionBegin; 91371bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91471bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 9159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)part)); 9169566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 91771bb2955SLawrence Mitchell mesh->partitioner = part; 91871bb2955SLawrence Mitchell PetscFunctionReturn(0); 91971bb2955SLawrence Mitchell } 92071bb2955SLawrence Mitchell 9218e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 9228e330a33SStefano Zampini { 9238e330a33SStefano Zampini const PetscInt *cone; 9248e330a33SStefano Zampini PetscInt coneSize, c; 9258e330a33SStefano Zampini PetscBool missing; 9268e330a33SStefano Zampini 9278e330a33SStefano Zampini PetscFunctionBeginHot; 9289566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, point, &missing)); 9298e330a33SStefano Zampini if (missing) { 9309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 9328e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9339566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, cone[c])); 9348e330a33SStefano Zampini } 9358e330a33SStefano Zampini } 9368e330a33SStefano Zampini PetscFunctionReturn(0); 9378e330a33SStefano Zampini } 9388e330a33SStefano Zampini 9398e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 940270bba0cSToby Isaac { 941270bba0cSToby Isaac PetscFunctionBegin; 9426a5a2ffdSToby Isaac if (up) { 9436a5a2ffdSToby Isaac PetscInt parent; 9446a5a2ffdSToby Isaac 9459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,point,&parent,NULL)); 9466a5a2ffdSToby Isaac if (parent != point) { 9476a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9486a5a2ffdSToby Isaac 9499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 950270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 951270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 952270bba0cSToby Isaac 9539566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9549566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE)); 955270bba0cSToby Isaac } 9569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 9576a5a2ffdSToby Isaac } 9586a5a2ffdSToby Isaac } 9596a5a2ffdSToby Isaac if (down) { 9606a5a2ffdSToby Isaac PetscInt numChildren; 9616a5a2ffdSToby Isaac const PetscInt *children; 9626a5a2ffdSToby Isaac 9639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,point,&numChildren,&children)); 9646a5a2ffdSToby Isaac if (numChildren) { 9656a5a2ffdSToby Isaac PetscInt i; 9666a5a2ffdSToby Isaac 9676a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9686a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9696a5a2ffdSToby Isaac 9709566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9719566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE)); 9726a5a2ffdSToby Isaac } 9736a5a2ffdSToby Isaac } 9746a5a2ffdSToby Isaac } 975270bba0cSToby Isaac PetscFunctionReturn(0); 976270bba0cSToby Isaac } 977270bba0cSToby Isaac 9788e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 9798e330a33SStefano Zampini { 9808e330a33SStefano Zampini PetscInt parent; 981825f8a23SLisandro Dalcin 9828e330a33SStefano Zampini PetscFunctionBeginHot; 9839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent,NULL)); 9848e330a33SStefano Zampini if (point != parent) { 9858e330a33SStefano Zampini const PetscInt *cone; 9868e330a33SStefano Zampini PetscInt coneSize, c; 9878e330a33SStefano Zampini 9889566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, parent)); 9899566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, parent)); 9909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, parent, &cone)); 9919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 9928e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9938e330a33SStefano Zampini const PetscInt cp = cone[c]; 9948e330a33SStefano Zampini 9959566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, cp)); 9968e330a33SStefano Zampini } 9978e330a33SStefano Zampini } 9988e330a33SStefano Zampini PetscFunctionReturn(0); 9998e330a33SStefano Zampini } 10008e330a33SStefano Zampini 10018e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 10028e330a33SStefano Zampini { 10038e330a33SStefano Zampini PetscInt i, numChildren; 10048e330a33SStefano Zampini const PetscInt *children; 10058e330a33SStefano Zampini 10068e330a33SStefano Zampini PetscFunctionBeginHot; 10079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 10088e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 10099566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, children[i])); 10108e330a33SStefano Zampini } 10118e330a33SStefano Zampini PetscFunctionReturn(0); 10128e330a33SStefano Zampini } 10138e330a33SStefano Zampini 10148e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 10158e330a33SStefano Zampini { 10168e330a33SStefano Zampini const PetscInt *cone; 10178e330a33SStefano Zampini PetscInt coneSize, c; 10188e330a33SStefano Zampini 10198e330a33SStefano Zampini PetscFunctionBeginHot; 10209566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 10219566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, point)); 10229566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Down_Private(dm, ht, point)); 10239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 10249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 10258e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 10269566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Private(dm, ht, cone[c])); 10278e330a33SStefano Zampini } 10288e330a33SStefano Zampini PetscFunctionReturn(0); 10298e330a33SStefano Zampini } 10308e330a33SStefano Zampini 10318e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 1032825f8a23SLisandro Dalcin { 1033825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10348e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10358e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 103627104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1037825f8a23SLisandro Dalcin 1038825f8a23SLisandro Dalcin PetscFunctionBegin; 10399566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 10409566063dSJacob Faibussowitsch PetscCall(PetscHSetIResize(ht, numPoints*16)); 10418e330a33SStefano Zampini if (!hasTree) { 10428e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10439566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, points[p])); 10448e330a33SStefano Zampini } 10458e330a33SStefano Zampini } else { 10468e330a33SStefano Zampini #if 1 10478e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10489566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Private(dm, ht, points[p])); 10498e330a33SStefano Zampini } 10508e330a33SStefano Zampini #else 10518e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1052825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 10539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 1054825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 10559566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closure[c])); 10569566063dSJacob Faibussowitsch if (hasTree) PetscCall(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE)); 1057825f8a23SLisandro Dalcin } 1058825f8a23SLisandro Dalcin } 10599566063dSJacob Faibussowitsch if (closure) PetscCall(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure)); 10608e330a33SStefano Zampini #endif 10618e330a33SStefano Zampini } 10629566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nelems)); 10639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nelems, &elems)); 10649566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &off, elems)); 10659566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 10669566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nelems, elems)); 10679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS)); 1068825f8a23SLisandro Dalcin PetscFunctionReturn(0); 1069825f8a23SLisandro Dalcin } 1070825f8a23SLisandro Dalcin 10715abbe4feSMichael Lange /*@ 10725abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10735abbe4feSMichael Lange 10745abbe4feSMichael Lange Input Parameters: 10755abbe4feSMichael Lange + dm - The DM 1076a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 10775abbe4feSMichael Lange 10785abbe4feSMichael Lange Level: developer 10795abbe4feSMichael Lange 1080db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 10815abbe4feSMichael Lange @*/ 10825abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 10839ffc88e4SToby Isaac { 1084825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 10855abbe4feSMichael Lange const PetscInt *ranks, *points; 1086825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 10879ffc88e4SToby Isaac 10889ffc88e4SToby Isaac PetscFunctionBegin; 10899566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 10909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 10919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 10925abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10935abbe4feSMichael Lange const PetscInt rank = ranks[r]; 10949566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 10959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 10969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 10979566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS)); 10989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 10999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11009566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, rank, closureIS)); 11019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&closureIS)); 11029ffc88e4SToby Isaac } 11039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11059ffc88e4SToby Isaac PetscFunctionReturn(0); 11069ffc88e4SToby Isaac } 11079ffc88e4SToby Isaac 110824d039d7SMichael Lange /*@ 110924d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 111024d039d7SMichael Lange 111124d039d7SMichael Lange Input Parameters: 111224d039d7SMichael Lange + dm - The DM 1113a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 111424d039d7SMichael Lange 111524d039d7SMichael Lange Level: developer 111624d039d7SMichael Lange 1117db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 111824d039d7SMichael Lange @*/ 111924d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 112070034214SMatthew G. Knepley { 112124d039d7SMichael Lange IS rankIS, pointIS; 112224d039d7SMichael Lange const PetscInt *ranks, *points; 112324d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 112424d039d7SMichael Lange PetscInt *adj = NULL; 112570034214SMatthew G. Knepley 112670034214SMatthew G. Knepley PetscFunctionBegin; 11279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 11289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 113024d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 113124d039d7SMichael Lange const PetscInt rank = ranks[r]; 113270034214SMatthew G. Knepley 11339566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 11349566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 11359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 113670034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 113724d039d7SMichael Lange adjSize = PETSC_DETERMINE; 11389566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj)); 11399566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(label, adj[a], rank)); 114070034214SMatthew G. Knepley } 11419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 11429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 114370034214SMatthew G. Knepley } 11449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11469566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 114724d039d7SMichael Lange PetscFunctionReturn(0); 114870034214SMatthew G. Knepley } 114970034214SMatthew G. Knepley 1150be200f8dSMichael Lange /*@ 1151be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1152be200f8dSMichael Lange 1153be200f8dSMichael Lange Input Parameters: 1154be200f8dSMichael Lange + dm - The DM 1155a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1156be200f8dSMichael Lange 1157be200f8dSMichael Lange Level: developer 1158be200f8dSMichael Lange 1159be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1160be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1161be200f8dSMichael Lange 1162db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1163be200f8dSMichael Lange @*/ 1164be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1165be200f8dSMichael Lange { 1166be200f8dSMichael Lange MPI_Comm comm; 1167be200f8dSMichael Lange PetscMPIInt rank; 1168be200f8dSMichael Lange PetscSF sfPoint; 11695d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1170be200f8dSMichael Lange IS rankIS, pointIS; 1171be200f8dSMichael Lange const PetscInt *ranks; 1172be200f8dSMichael Lange PetscInt numRanks, r; 1173be200f8dSMichael Lange 1174be200f8dSMichael Lange PetscFunctionBegin; 11759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 11769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11779566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 11785d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 11799566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 11809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &rankIS)); 11819566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 11835d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 11845d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 11855d04f6ebSMichael Lange if (remoteRank == rank) continue; 11869566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS)); 11879566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 11889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11895d04f6ebSMichael Lange } 11909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11929566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 1193be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 11949566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 11959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &rankIS)); 11969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 1198be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1199be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1200be200f8dSMichael Lange if (remoteRank == rank) continue; 12019566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS)); 12029566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 12039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 1204be200f8dSMichael Lange } 12059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 12069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 12079566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 1208be200f8dSMichael Lange PetscFunctionReturn(0); 1209be200f8dSMichael Lange } 1210be200f8dSMichael Lange 12111fd9873aSMichael Lange /*@ 12121fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 12131fd9873aSMichael Lange 12141fd9873aSMichael Lange Input Parameters: 12151fd9873aSMichael Lange + dm - The DM 1216a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots 1217fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 12181fd9873aSMichael Lange 12191fd9873aSMichael Lange Output Parameter: 1220a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots 12211fd9873aSMichael Lange 12221fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 12231fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 12241fd9873aSMichael Lange 12251fd9873aSMichael Lange Level: developer 12261fd9873aSMichael Lange 1227db781477SPatrick Sanan .seealso: `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 12281fd9873aSMichael Lange @*/ 12291fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 12301fd9873aSMichael Lange { 12311fd9873aSMichael Lange MPI_Comm comm; 1232874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1233874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12341fd9873aSMichael Lange PetscSF sfPoint; 1235874ddda9SLisandro Dalcin PetscSection rootSection; 12361fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12371fd9873aSMichael Lange const PetscSFNode *remote; 12381fd9873aSMichael Lange const PetscInt *local, *neighbors; 12391fd9873aSMichael Lange IS valueIS; 1240874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12411fd9873aSMichael Lange 12421fd9873aSMichael Lange PetscFunctionBegin; 12439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0)); 12449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 12459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 12479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 12481fd9873aSMichael Lange 12491fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 12509566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 12519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, 0, size)); 12529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(rootLabel, &valueIS)); 12539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numNeighbors)); 12549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &neighbors)); 12551fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12569566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints)); 12579566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(rootSection, neighbors[n], numPoints)); 12581fd9873aSMichael Lange } 12599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 12609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &rootSize)); 12619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rootSize, &rootPoints)); 12629566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 12631fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12641fd9873aSMichael Lange IS pointIS; 12651fd9873aSMichael Lange const PetscInt *points; 12661fd9873aSMichael Lange 12679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 12689566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS)); 12699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 12709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 12711fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 12729566063dSJacob Faibussowitsch if (local) PetscCall(PetscFindInt(points[p], nleaves, local, &l)); 1273f8987ae8SMichael Lange else {l = -1;} 12741fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 12751fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 12761fd9873aSMichael Lange } 12779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 12789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 12791fd9873aSMichael Lange } 1280874ddda9SLisandro Dalcin 1281874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1282874ddda9SLisandro Dalcin if (!processSF) { 1283874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1284874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1285874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1286874ddda9SLisandro Dalcin 12879566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls)); 1288874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 12899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, neighbors[n], &dof)); 12909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1291874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 1292874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1293874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1294874ddda9SLisandro Dalcin #endif 1295874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 1296874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 1297874ddda9SLisandro Dalcin } 12989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm)); 1299874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 1300874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 13019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm)); 1302874ddda9SLisandro Dalcin if (!mpiOverflow) { 13039566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using Alltoallv for mesh distribution\n")); 1304874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 13059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafSize, &leafPoints)); 13069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm)); 1307874ddda9SLisandro Dalcin } 13089566063dSJacob Faibussowitsch PetscCall(PetscFree4(scounts, sdispls, rcounts, rdispls)); 1309874ddda9SLisandro Dalcin } 1310874ddda9SLisandro Dalcin 1311874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1312874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1313874ddda9SLisandro Dalcin PetscSF procSF; 1314874ddda9SLisandro Dalcin PetscSection leafSection; 1315874ddda9SLisandro Dalcin 1316874ddda9SLisandro Dalcin if (processSF) { 13179566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using processSF for mesh distribution\n")); 13189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)processSF)); 1319874ddda9SLisandro Dalcin procSF = processSF; 1320874ddda9SLisandro Dalcin } else { 13219566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n")); 13229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&procSF)); 13239566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL)); 1324874ddda9SLisandro Dalcin } 1325874ddda9SLisandro Dalcin 13269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection)); 13279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints)); 13289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSection, &leafSize)); 13299566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 13309566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&procSF)); 1331874ddda9SLisandro Dalcin } 1332874ddda9SLisandro Dalcin 1333874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 13349566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank)); 13351fd9873aSMichael Lange } 1336874ddda9SLisandro Dalcin 13379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &neighbors)); 13389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 13399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 13409566063dSJacob Faibussowitsch PetscCall(PetscFree(rootPoints)); 13419566063dSJacob Faibussowitsch PetscCall(PetscFree(leafPoints)); 13429566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0)); 13431fd9873aSMichael Lange PetscFunctionReturn(0); 13441fd9873aSMichael Lange } 13451fd9873aSMichael Lange 1346aa3148a8SMichael Lange /*@ 1347aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1348aa3148a8SMichael Lange 1349aa3148a8SMichael Lange Input Parameters: 1350aa3148a8SMichael Lange + dm - The DM 1351a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1352aa3148a8SMichael Lange 1353aa3148a8SMichael Lange Output Parameter: 1354fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1355aa3148a8SMichael Lange 1356aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1357aa3148a8SMichael Lange 1358aa3148a8SMichael Lange Level: developer 1359aa3148a8SMichael Lange 1360db781477SPatrick Sanan .seealso: `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1361aa3148a8SMichael Lange @*/ 1362aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1363aa3148a8SMichael Lange { 13646e203dd9SStefano Zampini PetscMPIInt rank; 13656e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1366aa3148a8SMichael Lange PetscSFNode *remotePoints; 13676e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13686e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1369aa3148a8SMichael Lange 1370aa3148a8SMichael Lange PetscFunctionBegin; 13719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 13729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 1373aa3148a8SMichael Lange 13749566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &neighborsIS)); 13756e203dd9SStefano Zampini #if 0 13766e203dd9SStefano Zampini { 13776e203dd9SStefano Zampini IS is; 13789566063dSJacob Faibussowitsch PetscCall(ISDuplicate(neighborsIS, &is)); 13799566063dSJacob Faibussowitsch PetscCall(ISSort(is)); 13809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 13816e203dd9SStefano Zampini neighborsIS = is; 13826e203dd9SStefano Zampini } 13836e203dd9SStefano Zampini #endif 13849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neighborsIS, &nNeighbors)); 13859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(neighborsIS, &neighbors)); 13866e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 13879566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, neighbors[n], &numPoints)); 1388aa3148a8SMichael Lange numRemote += numPoints; 1389aa3148a8SMichael Lange } 13909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRemote, &remotePoints)); 139143f7d02bSMichael Lange /* Put owned points first */ 13929566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, rank, &numPoints)); 139343f7d02bSMichael Lange if (numPoints > 0) { 13949566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &remoteRootIS)); 13959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 139643f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 139743f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 139843f7d02bSMichael Lange remotePoints[idx].rank = rank; 139943f7d02bSMichael Lange idx++; 140043f7d02bSMichael Lange } 14019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 140343f7d02bSMichael Lange } 140443f7d02bSMichael Lange /* Now add remote points */ 14056e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 14066e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 14076e203dd9SStefano Zampini 14089566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, nn, &numPoints)); 14096e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 14109566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, nn, &remoteRootIS)); 14119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 1412aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1413aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 14146e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1415aa3148a8SMichael Lange idx++; 1416aa3148a8SMichael Lange } 14179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 1419aa3148a8SMichael Lange } 14209566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject) dm), sf)); 14219566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sf)); 14249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 14259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 142670034214SMatthew G. Knepley PetscFunctionReturn(0); 142770034214SMatthew G. Knepley } 1428cb87ef4cSFlorian Wechsung 1429abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1430abe9303eSLisandro Dalcin #include <parmetis.h> 1431abe9303eSLisandro Dalcin #endif 1432abe9303eSLisandro Dalcin 14336a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14346a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14356a3739e5SFlorian Wechsung * them out in that case. */ 14366a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 14377a82c785SFlorian Wechsung /*@C 14387f57c1a4SFlorian Wechsung 14397f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 14407f57c1a4SFlorian Wechsung 14417f57c1a4SFlorian Wechsung Input parameters: 14427f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1443fe2efc57SMark . n - The number of points. 1444fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1445fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1446fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 14477f57c1a4SFlorian Wechsung 14487f57c1a4SFlorian Wechsung Level: developer 14497f57c1a4SFlorian Wechsung 14507f57c1a4SFlorian Wechsung @*/ 14517f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 14527f57c1a4SFlorian Wechsung { 14535f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14547f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14557f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14567f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14577f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14587f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14597f57c1a4SFlorian Wechsung PetscSF sf; 14607f57c1a4SFlorian Wechsung MPI_Comm comm; 14615a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14627f57c1a4SFlorian Wechsung 14637f57c1a4SFlorian Wechsung PetscFunctionBegin; 14649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 14659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14687f57c1a4SFlorian Wechsung 14699566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 14709566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 14719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isLeaf)); 14727f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14737f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 14747f57c1a4SFlorian Wechsung } 14757f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 14767f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 14777f57c1a4SFlorian Wechsung } 14787f57c1a4SFlorian Wechsung 14799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart+1, &cumSumDegrees)); 14807f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 14817f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 14827f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 14837f57c1a4SFlorian Wechsung } 14847f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 14857f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 14867f57c1a4SFlorian Wechsung 14879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &locationsOfLeafs)); 14889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &rankOnLeafs)); 14897f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14907f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 14917f57c1a4SFlorian Wechsung } 14929566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14939566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14949566063dSJacob Faibussowitsch PetscCall(PetscFree(rankOnLeafs)); 14957f57c1a4SFlorian Wechsung 14967f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 14979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs)); 14989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &points)); 14997f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15007f57c1a4SFlorian Wechsung points[i] = pStart+i; 15017f57c1a4SFlorian Wechsung } 15029566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15039566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15049566063dSJacob Faibussowitsch PetscCall(PetscFree(points)); 15057f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 15069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &newOwners)); 15079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &newNumbers)); 15087f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15097f57c1a4SFlorian Wechsung newOwners[i] = -1; 15107f57c1a4SFlorian Wechsung newNumbers[i] = -1; 15117f57c1a4SFlorian Wechsung } 15127f57c1a4SFlorian Wechsung { 15137f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 15147f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 15157f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 15167f57c1a4SFlorian Wechsung newNumber = -1; 15177f57c1a4SFlorian Wechsung oldOwner = rank; 15187f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 15197f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 15207f57c1a4SFlorian Wechsung newNumber = oldNumber; 15217f57c1a4SFlorian Wechsung } else { 15227f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 15237f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 15247f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 15257f57c1a4SFlorian Wechsung break; 15267f57c1a4SFlorian Wechsung } 15277f57c1a4SFlorian Wechsung } 15287f57c1a4SFlorian Wechsung } 15295f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 15307f57c1a4SFlorian Wechsung 15317f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 15327f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 15337f57c1a4SFlorian Wechsung } 15347f57c1a4SFlorian Wechsung } 15359566063dSJacob Faibussowitsch PetscCall(PetscFree(cumSumDegrees)); 15369566063dSJacob Faibussowitsch PetscCall(PetscFree(locationsOfLeafs)); 15379566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteLocalPointOfLeafs)); 15387f57c1a4SFlorian Wechsung 15399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 15409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 15419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 15429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 15437f57c1a4SFlorian Wechsung 15447f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15457f57c1a4SFlorian Wechsung leafCounter=0; 15467f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15477f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15487f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15497f57c1a4SFlorian Wechsung leafCounter++; 15507f57c1a4SFlorian Wechsung } 15517f57c1a4SFlorian Wechsung } else { 15527f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15537f57c1a4SFlorian Wechsung leafCounter++; 15547f57c1a4SFlorian Wechsung } 15557f57c1a4SFlorian Wechsung } 15567f57c1a4SFlorian Wechsung } 15577f57c1a4SFlorian Wechsung 15587f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 15599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafsNew)); 15609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafLocationsNew)); 15617f57c1a4SFlorian Wechsung 15627f57c1a4SFlorian Wechsung leafCounter = 0; 15637f57c1a4SFlorian Wechsung counter = 0; 15647f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15657f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15667f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15677f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15687f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15697f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15707f57c1a4SFlorian Wechsung leafCounter++; 15717f57c1a4SFlorian Wechsung } 15727f57c1a4SFlorian Wechsung } else { 15737f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15747f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15757f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15767f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 15777f57c1a4SFlorian Wechsung leafCounter++; 15787f57c1a4SFlorian Wechsung } 15797f57c1a4SFlorian Wechsung } 15807f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15817f57c1a4SFlorian Wechsung counter++; 15827f57c1a4SFlorian Wechsung } 15837f57c1a4SFlorian Wechsung } 15847f57c1a4SFlorian Wechsung 15859566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER)); 15869566063dSJacob Faibussowitsch PetscCall(PetscFree(newOwners)); 15879566063dSJacob Faibussowitsch PetscCall(PetscFree(newNumbers)); 15889566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 15897f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 15907f57c1a4SFlorian Wechsung } 15917f57c1a4SFlorian Wechsung 1592125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1593125d2a8fSFlorian Wechsung { 15945f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum; 15955a30b08bSFlorian Wechsung PetscMPIInt rank, size; 15965f80ce2aSJacob Faibussowitsch 1597125d2a8fSFlorian Wechsung PetscFunctionBegin; 15989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16009566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &distribution)); 16015f80ce2aSJacob Faibussowitsch for (PetscInt i=0; i<n; i++) { 1602125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 1603125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 1604125d2a8fSFlorian Wechsung } 16059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm)); 1606125d2a8fSFlorian Wechsung min = distribution[0]; 1607125d2a8fSFlorian Wechsung max = distribution[0]; 1608125d2a8fSFlorian Wechsung sum = distribution[0]; 16095f80ce2aSJacob Faibussowitsch for (PetscInt i=1; i<size; i++) { 1610125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 1611125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 1612125d2a8fSFlorian Wechsung sum += distribution[i]; 1613125d2a8fSFlorian Wechsung } 161463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Min: %" PetscInt_FMT ", Avg: %" PetscInt_FMT ", Max: %" PetscInt_FMT ", Balance: %f\n", min, sum/size, max, (max*1.*size)/sum)); 16159566063dSJacob Faibussowitsch PetscCall(PetscFree(distribution)); 1616125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1617125d2a8fSFlorian Wechsung } 1618125d2a8fSFlorian Wechsung 16196a3739e5SFlorian Wechsung #endif 16206a3739e5SFlorian Wechsung 1621cb87ef4cSFlorian Wechsung /*@ 16225dc86ac1SFlorian 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. 1623cb87ef4cSFlorian Wechsung 1624cb87ef4cSFlorian Wechsung Input parameters: 1625ed44d270SFlorian Wechsung + dm - The DMPlex object. 1626fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1627fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1628fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1629cb87ef4cSFlorian Wechsung 16308b879b41SFlorian Wechsung Output parameters: 1631252a1336SBarry Smith . success - whether the graph partitioning was successful or not, optional. Unsuccessful simply means no change to the partitioning 1632252a1336SBarry Smith 1633252a1336SBarry Smith Options Database: 1634252a1336SBarry Smith + -dm_plex_rebalance_shared_points_parmetis - Use ParMetis instead of Metis for the partitioner 1635252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_initial_guess - Use current partition to bootstrap ParMetis partition 1636252a1336SBarry 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_ 1637252a1336SBarry Smith - -dm_plex_rebalance_shared_points_monitor - Monitor the shared points rebalance process 1638252a1336SBarry Smith 1639252a1336SBarry Smith Developer Notes: 1640252a1336SBarry Smith This should use MatPartitioning to allow the use of any partitioner and not be hardwired to use ParMetis 16418b879b41SFlorian Wechsung 164290ea27d8SSatish Balay Level: intermediate 1643cb87ef4cSFlorian Wechsung @*/ 16448b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1645cb87ef4cSFlorian Wechsung { 164641525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1647cb87ef4cSFlorian Wechsung PetscSF sf; 16480faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16497f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16507f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16517f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1652cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1653cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1654cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16557f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16565dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1657cb87ef4cSFlorian Wechsung PetscInt offset, counter; 1658252a1336SBarry Smith PetscInt *vtxwgt; 1659252a1336SBarry Smith const PetscInt *xadj, *adjncy; 1660cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1661cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1662cb87ef4cSFlorian Wechsung real_t *ubvec; 1663cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1664cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1665cb87ef4cSFlorian Wechsung MPI_Comm comm; 1666252a1336SBarry Smith Mat A; 16677d197802SFlorian Wechsung PetscViewer viewer; 16687d197802SFlorian Wechsung PetscViewerFormat format; 16695a30b08bSFlorian Wechsung PetscLayout layout; 1670252a1336SBarry Smith real_t *tpwgts; 1671252a1336SBarry Smith PetscMPIInt *counts, *mpiCumSumVertices; 1672252a1336SBarry Smith PetscInt *pointsToRewrite; 1673252a1336SBarry Smith PetscInt numRows; 1674252a1336SBarry Smith PetscBool done,usematpartitioning = PETSC_FALSE; 1675252a1336SBarry Smith IS ispart = NULL; 1676252a1336SBarry Smith MatPartitioning mp; 1677252a1336SBarry Smith const char *prefix; 167812617df9SFlorian Wechsung 167912617df9SFlorian Wechsung PetscFunctionBegin; 16809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 16819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1682252a1336SBarry Smith if (size==1) { 1683252a1336SBarry Smith if (success) *success = PETSC_TRUE; 1684252a1336SBarry Smith PetscFunctionReturn(0); 1685252a1336SBarry Smith } 1686252a1336SBarry Smith if (success) *success = PETSC_FALSE; 1687252a1336SBarry Smith PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1688252a1336SBarry Smith 1689252a1336SBarry Smith parallel = PETSC_FALSE; 1690252a1336SBarry Smith useInitialGuess = PETSC_FALSE; 1691252a1336SBarry Smith PetscObjectOptionsBegin((PetscObject)dm); 1692252a1336SBarry Smith PetscCall(PetscOptionsName("-dm_plex_rebalance_shared_points_parmetis","Use ParMetis instead of Metis for the partitioner","DMPlexRebalanceSharedPoints",¶llel)); 1693252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_initial_guess","Use current partition to bootstrap ParMetis partition","DMPlexRebalanceSharedPoints",useInitialGuess,&useInitialGuess,NULL)); 1694252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_mat_partitioning","Use the MatPartitioning object to partition","DMPlexRebalanceSharedPoints",usematpartitioning,&usematpartitioning,NULL)); 1695252a1336SBarry Smith PetscCall(PetscOptionsViewer("-dm_plex_rebalance_shared_points_monitor","Monitor the shared points rebalance process","DMPlexRebalanceSharedPoints",&viewer,&format,NULL)); 1696252a1336SBarry Smith PetscOptionsEnd(); 1697252a1336SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer,format)); 16987f57c1a4SFlorian Wechsung 16999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 170041525646SFlorian Wechsung 1701252a1336SBarry Smith PetscCall(DMGetOptionsPrefix(dm,&prefix)); 17029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL)); 17031baa6e33SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer,format)); 17047d197802SFlorian Wechsung 1705ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 17069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd)); 17079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &toBalance)); 1709cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1710252a1336SBarry Smith toBalance[i] = (PetscBool)(i>=eBegin && i<eEnd); 1711cb87ef4cSFlorian Wechsung } 1712cb87ef4cSFlorian Wechsung 1713cf818975SFlorian Wechsung /* There are three types of points: 1714cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1715cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1716cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1717cf818975SFlorian Wechsung */ 17189566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 17199566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 17209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isLeaf)); 17219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned)); 17229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isExclusivelyOwned)); 1723cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1724cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1725cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1726cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1727cb87ef4cSFlorian Wechsung } 1728cf818975SFlorian Wechsung 1729252a1336SBarry Smith /* mark all the leafs */ 1730cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 1731cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 1732cb87ef4cSFlorian Wechsung } 1733cb87ef4cSFlorian Wechsung 1734cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1735cf818975SFlorian Wechsung * not by calculating its degree */ 17369566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, °rees)); 17379566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, °rees)); 1738cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1739cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1740cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1741cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17427f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1743cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1744cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1745cb87ef4cSFlorian Wechsung } else { 1746cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1747cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1748cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1749cb87ef4cSFlorian Wechsung } 1750cb87ef4cSFlorian Wechsung } 1751cb87ef4cSFlorian Wechsung } 1752cb87ef4cSFlorian Wechsung } 1753cb87ef4cSFlorian Wechsung 1754252a1336SBarry Smith /* Build a graph with one vertex per core representing the 1755cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1756cf818975SFlorian Wechsung * point. */ 17579566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout)); 17589566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned)); 17599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 17609566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &cumSumVertices)); 17619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices)); 17625a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 1763cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1764cb87ef4cSFlorian Wechsung counter = 0; 1765cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1766cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17677f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1768cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1769cb87ef4cSFlorian Wechsung counter++; 1770cb87ef4cSFlorian Wechsung } 1771cb87ef4cSFlorian Wechsung } 1772cb87ef4cSFlorian Wechsung } 1773cb87ef4cSFlorian Wechsung 1774cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 17759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &leafGlobalNumbers)); 17769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 17779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 1778cb87ef4cSFlorian Wechsung 1779252a1336SBarry Smith /* Build the graph for partitioning */ 1780252a1336SBarry Smith numRows = 1+numNonExclusivelyOwned; 1781252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 17829566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 1783252a1336SBarry Smith PetscCall(MatSetType(A, MATMPIADJ)); 1784252a1336SBarry Smith PetscCall(MatSetSizes(A, numRows, numRows, cumSumVertices[size], cumSumVertices[size])); 1785252a1336SBarry Smith idx = cumSumVertices[rank]; 17864baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17874baf1206SFlorian Wechsung if (toBalance[i]) { 17880faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17890faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17900faf6628SFlorian Wechsung else continue; 17919566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, idx, jdx, 1, INSERT_VALUES)); 17929566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, jdx, idx, 1, INSERT_VALUES)); 17930941debbSFlorian Wechsung } 17940941debbSFlorian Wechsung } 1795252a1336SBarry Smith PetscCall(PetscFree(globalNumbersOfLocalOwnedVertices)); 1796252a1336SBarry Smith PetscCall(PetscFree(leafGlobalNumbers)); 17979566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17989566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 1799252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 18004baf1206SFlorian Wechsung 180141525646SFlorian Wechsung nparts = size; 1802252a1336SBarry Smith ncon = 1; 18039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * nparts, &tpwgts)); 180441525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 180541525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 180641525646SFlorian Wechsung } 18079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon, &ubvec)); 1808252a1336SBarry Smith ubvec[0] = 1.05; 1809252a1336SBarry Smith ubvec[1] = 1.05; 18108c9a1619SFlorian Wechsung 18119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt)); 1812252a1336SBarry Smith if (ncon == 2) { 181341525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 1814252a1336SBarry Smith vtxwgt[1] = 1; 181541525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 181641525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 1817252a1336SBarry Smith vtxwgt[ncon*(i+1)+1] = 0; 1818252a1336SBarry Smith } 1819252a1336SBarry Smith } else { 1820252a1336SBarry Smith PetscInt base,ms; 1821252a1336SBarry Smith PetscCallMPI(MPI_Allreduce(&numExclusivelyOwned,&base,1,MPIU_INT,MPIU_MAX,PetscObjectComm((PetscObject)dm))); 1822252a1336SBarry Smith PetscCall(MatGetSize(A,&ms,NULL)); 1823252a1336SBarry Smith ms -= size; 1824252a1336SBarry Smith base = PetscMax(base,ms); 1825252a1336SBarry Smith vtxwgt[0] = base + numExclusivelyOwned; 1826252a1336SBarry Smith for (i=0; i<numNonExclusivelyOwned; i++) { 1827252a1336SBarry Smith vtxwgt[i + 1] = 1; 1828252a1336SBarry Smith } 182941525646SFlorian Wechsung } 18308c9a1619SFlorian Wechsung 18315dc86ac1SFlorian Wechsung if (viewer) { 183263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %" PetscInt_FMT " on interface of mesh distribution.\n", entityDepth)); 183363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %" PetscInt_FMT "\n", cumSumVertices[size])); 183412617df9SFlorian Wechsung } 1835252a1336SBarry Smith /* TODO: Drop the parallel/sequential choice here and just use MatPartioner for much more flexibility */ 1836252a1336SBarry Smith if (usematpartitioning) { 1837252a1336SBarry Smith const char *prefix; 1838252a1336SBarry Smith 1839252a1336SBarry Smith PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)dm),&mp)); 1840252a1336SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mp,"dm_plex_rebalance_shared_points_")); 1841252a1336SBarry Smith PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 1842252a1336SBarry Smith PetscCall(PetscObjectPrependOptionsPrefix((PetscObject)mp,prefix)); 1843252a1336SBarry Smith PetscCall(MatPartitioningSetAdjacency(mp,A)); 1844252a1336SBarry Smith PetscCall(MatPartitioningSetNumberVertexWeights(mp,ncon)); 1845252a1336SBarry Smith PetscCall(MatPartitioningSetVertexWeights(mp,vtxwgt)); 1846252a1336SBarry Smith PetscCall(MatPartitioningSetFromOptions(mp)); 1847252a1336SBarry Smith PetscCall(MatPartitioningApply(mp,&ispart)); 1848252a1336SBarry Smith PetscCall(ISGetIndices(ispart,(const PetscInt **)&part)); 1849252a1336SBarry Smith } else if (parallel) { 1850252a1336SBarry Smith if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n")); 1851252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part)); 1852252a1336SBarry Smith PetscCall(MatGetRowIJ(A,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows,&xadj,&adjncy,&done)); 1853252a1336SBarry Smith PetscCheck(done,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Could not get adjacency information"); 18549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(4, &options)); 18555a30b08bSFlorian Wechsung options[0] = 1; 18565a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 1857252a1336SBarry Smith if (viewer) options[1] = 1; 18585a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18595a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 1860252a1336SBarry Smith wgtflag = 2; 1861252a1336SBarry Smith numflag = 0; 18628c9a1619SFlorian Wechsung if (useInitialGuess) { 1863252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "THIS DOES NOT WORK! I don't know why. Using current distribution of points as initial guess.\n")); 1864252a1336SBarry Smith for (i=0; i<numRows; i++) part[i] = rank; 18659566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n")); 1866*792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_RefineKway"); 1867252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition,0,0,0,0)); 1868252a1336SBarry 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); 1869252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition,0,0,0,0)); 18708c9a1619SFlorian Wechsung PetscStackPop; 1871252a1336SBarry Smith PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18728c9a1619SFlorian Wechsung } else { 1873*792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_PartKway"); 1874252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition,0,0,0,0)); 1875252a1336SBarry 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); 1876252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition,0,0,0,0)); 18778c9a1619SFlorian Wechsung PetscStackPop; 18785f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18798c9a1619SFlorian Wechsung } 1880252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows,&xadj,&adjncy,&done)); 18819566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 188241525646SFlorian Wechsung } else { 18839566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n")); 188441525646SFlorian Wechsung Mat As; 188541525646SFlorian Wechsung PetscInt *partGlobal; 188641525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 1887252a1336SBarry Smith 1888252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part)); 1889252a1336SBarry Smith PetscCall(MatGetSize(A, &numRows, NULL)); 1890252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1891252a1336SBarry Smith PetscCall(MatMPIAdjToSeqRankZero(A, &As)); 1892252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1893252a1336SBarry Smith 18949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &numExclusivelyOwnedAll)); 189541525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 18969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm)); 1897cb87ef4cSFlorian Wechsung 18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &partGlobal)); 1899252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition,0,0,0,0)); 1900dd400576SPatrick Sanan if (rank == 0) { 1901252a1336SBarry Smith PetscInt *vtxwgt_g, numRows_g; 190241525646SFlorian Wechsung 1903252a1336SBarry Smith PetscCall(MatGetRowIJ(As,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows_g,&xadj,&adjncy,&done)); 1904252a1336SBarry Smith PetscCall(PetscMalloc1(2*numRows_g, &vtxwgt_g)); 190541525646SFlorian Wechsung for (i=0; i<size; i++) { 190641525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 190741525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 190841525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 190941525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 191041525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 191141525646SFlorian Wechsung } 191241525646SFlorian Wechsung } 1913252a1336SBarry Smith 19149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(64, &options)); 191541525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 19165f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 191741525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 1918*792fecdfSBarry Smith PetscStackPushExternal("METIS_PartGraphKway"); 1919252a1336SBarry Smith ierr = METIS_PartGraphKway(&numRows_g, &ncon, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 192041525646SFlorian Wechsung PetscStackPop; 19215f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 19229566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 19239566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt_g)); 1924252a1336SBarry Smith PetscCall(MatRestoreRowIJ(As,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows_g,&xadj,&adjncy,&done)); 1925252a1336SBarry Smith PetscCall(MatDestroy(&As)); 192641525646SFlorian Wechsung } 1927252a1336SBarry Smith PetscCall(PetscBarrier((PetscObject)dm)); 1928252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition,0,0,0,0)); 19299566063dSJacob Faibussowitsch PetscCall(PetscFree(numExclusivelyOwnedAll)); 193041525646SFlorian Wechsung 1931252a1336SBarry Smith /* scatter the partitioning information to ranks */ 1932252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalScatterPart,0,0,0,0)); 19339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &counts)); 19349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size+1, &mpiCumSumVertices)); 19355dc86ac1SFlorian Wechsung for (i=0; i<size; i++) { 19369566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]))); 193741525646SFlorian Wechsung } 193881a13b52SFlorian Wechsung for (i=0; i<=size; i++) { 19399566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]))); 194081a13b52SFlorian Wechsung } 19419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm)); 19429566063dSJacob Faibussowitsch PetscCall(PetscFree(counts)); 19439566063dSJacob Faibussowitsch PetscCall(PetscFree(mpiCumSumVertices)); 19449566063dSJacob Faibussowitsch PetscCall(PetscFree(partGlobal)); 1945252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalScatterPart,0,0,0,0)); 194641525646SFlorian Wechsung } 19479566063dSJacob Faibussowitsch PetscCall(PetscFree(ubvec)); 19489566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts)); 1949cb87ef4cSFlorian Wechsung 1950252a1336SBarry Smith /* Rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1951252a1336SBarry Smith PetscCall(PetscMalloc2(size, &firstVertices,size, &renumbering)); 1952cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 19539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm)); 1954cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 1955cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 1956cb87ef4cSFlorian Wechsung } 1957cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 1958cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 1959cb87ef4cSFlorian Wechsung } 1960252a1336SBarry Smith PetscCall(PetscFree2(firstVertices,renumbering)); 1961252a1336SBarry Smith 1962cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1963cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 19649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm)); 1965cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 1966252a1336SBarry Smith PetscCheck(failedGlobal <= 0,comm,PETSC_ERR_LIB,"Metis/Parmetis returned a bad partion"); 19679566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt)); 19689566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 19699566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 19709566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 19719566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 1972252a1336SBarry Smith if (usematpartitioning) { 1973252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart,(const PetscInt **)&part)); 1974252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 1975252a1336SBarry Smith } else PetscCall(PetscFree(part)); 19767f57c1a4SFlorian Wechsung if (viewer) { 19779566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 19789566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 19797f57c1a4SFlorian Wechsung } 19809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 19818b879b41SFlorian Wechsung PetscFunctionReturn(0); 1982cb87ef4cSFlorian Wechsung } 1983cb87ef4cSFlorian Wechsung 1984252a1336SBarry Smith /* Check how well we did distributing points*/ 19855dc86ac1SFlorian Wechsung if (viewer) { 1986252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Number of owned entities of depth %" PetscInt_FMT ".\n", entityDepth)); 1987252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Initial ")); 19889566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer)); 1989252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Rebalanced ")); 19909566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 19917407ba93SFlorian Wechsung } 19927407ba93SFlorian Wechsung 1993252a1336SBarry Smith /* Check that every vertex is owned by a process that it is actually connected to. */ 1994252a1336SBarry Smith PetscCall(MatGetRowIJ(A,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 199541525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 1996cb87ef4cSFlorian Wechsung PetscInt loc = 0; 19979566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc)); 19987407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 1999cb87ef4cSFlorian Wechsung if (loc<0) { 200041525646SFlorian Wechsung part[i] = rank; 2001cb87ef4cSFlorian Wechsung } 2002cb87ef4cSFlorian Wechsung } 2003252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,&numRows,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done)); 2004252a1336SBarry Smith PetscCall(MatDestroy(&A)); 2005cb87ef4cSFlorian Wechsung 2006252a1336SBarry Smith /* See how significant the influences of the previous fixing up step was.*/ 20075dc86ac1SFlorian Wechsung if (viewer) { 2008252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "After fix ")); 20099566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 20107407ba93SFlorian Wechsung } 2011252a1336SBarry Smith if (!usematpartitioning) PetscCall(PetscFree(vtxwgt)); 2012252a1336SBarry Smith else PetscCall(MatPartitioningDestroy(&mp)); 20137407ba93SFlorian Wechsung 20149566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 2015cb87ef4cSFlorian Wechsung 2016252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 2017252a1336SBarry Smith /* Rewrite the SF to reflect the new ownership. */ 20189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite)); 20197f57c1a4SFlorian Wechsung counter = 0; 2020cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2021cb87ef4cSFlorian Wechsung if (toBalance[i]) { 2022cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 20237f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 2024cb87ef4cSFlorian Wechsung counter++; 2025cb87ef4cSFlorian Wechsung } 2026cb87ef4cSFlorian Wechsung } 2027cb87ef4cSFlorian Wechsung } 20289566063dSJacob Faibussowitsch PetscCall(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees)); 20299566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsToRewrite)); 2030252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 2031cb87ef4cSFlorian Wechsung 20329566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 20339566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 20349566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 20359566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 2036252a1336SBarry Smith if (usematpartitioning) { 2037252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart,(const PetscInt **)&part)); 2038252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 2039252a1336SBarry Smith } else PetscCall(PetscFree(part)); 20405dc86ac1SFlorian Wechsung if (viewer) { 20419566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 20429566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 20437d197802SFlorian Wechsung } 20448b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 20459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 2046b458e8f1SJose E. Roman PetscFunctionReturn(0); 2047240408d3SFlorian Wechsung #else 20485f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 204941525646SFlorian Wechsung #endif 2050cb87ef4cSFlorian Wechsung } 2051