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) */ 61*b68380d8SVaclav 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 68*b68380d8SVaclav 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) */ 83*b68380d8SVaclav 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) { 88*b68380d8SVaclav Hapla vAdj[off++] = DMPlex_GlobalID(cellNum[point-cStart]); 895a107427SMatthew G. Knepley } 905a107427SMatthew G. Knepley } 915f80ce2aSJacob Faibussowitsch PetscCheck(off == vOffsets[v+1],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %D should be %D", 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)); 172*b68380d8SVaclav 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)); 175*b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]-pStart]); 1769566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 177*b68380d8SVaclav 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)); 190*b68380d8SVaclav 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)); 193*b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]-pStart]); 1949566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 195*b68380d8SVaclav 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) */ 210*b68380d8SVaclav Hapla if (nroots > 0) {if (cellNum[p-pStart] < 0) continue;} 2118f4e72b9SMatthew G. Knepley /* Add remote cells */ 2128f4e72b9SMatthew G. Knepley if (remoteCells) { 213*b68380d8SVaclav 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)); 249*b68380d8SVaclav 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++) { 263*b68380d8SVaclav 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)); 348bbbc8e51SStefano Zampini if (globalNumbering) { 3499566063dSJacob Faibussowitsch PetscCall(ISDuplicate(cis, globalNumbering)); 350bbbc8e51SStefano Zampini } 351bbbc8e51SStefano Zampini 352bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 3539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fis, &m)); 3549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 356bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 357bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 358bbbc8e51SStefano Zampini 359bbbc8e51SStefano Zampini if (p < 0) { 360bbbc8e51SStefano Zampini idxs[i] = -(p+1); 361bbbc8e51SStefano Zampini } else { 362bbbc8e51SStefano Zampini idxs[i] = p; 363bbbc8e51SStefano Zampini floc += 1; 364bbbc8e51SStefano Zampini } 365bbbc8e51SStefano Zampini } 3669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 3679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis)); 369bbbc8e51SStefano Zampini 3709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cis, &m)); 3719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 3729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 3739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs2)); 374bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 375bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 376bbbc8e51SStefano Zampini 377bbbc8e51SStefano Zampini if (p < 0) { 378bbbc8e51SStefano Zampini idxs[i] = -(p+1); 379bbbc8e51SStefano Zampini } else { 380bbbc8e51SStefano Zampini idxs[i] = p; 381bbbc8e51SStefano Zampini idxs2[cloc++] = p; 382bbbc8e51SStefano Zampini } 383bbbc8e51SStefano Zampini } 3849566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 3859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 3869566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis)); 3879566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own)); 388bbbc8e51SStefano Zampini 389bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 3909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &conn)); 3919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(conn, floc, cloc, M, N)); 3929566063dSJacob Faibussowitsch PetscCall(MatSetType(conn, MATMPIAIJ)); 3939566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, NULL, &lm)); 3949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 3959566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL)); 396bbbc8e51SStefano Zampini 397bbbc8e51SStefano Zampini /* Assemble matrix */ 3989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 400bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 401bbbc8e51SStefano Zampini const PetscInt *cone; 402bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 403bbbc8e51SStefano Zampini 404bbbc8e51SStefano Zampini col = cols[c-cStart]; 4059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 4069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 407bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 408bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 409bbbc8e51SStefano Zampini const PetscInt *children; 410bbbc8e51SStefano Zampini PetscInt numChildren, ch; 411bbbc8e51SStefano Zampini 412bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 4139566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 414bbbc8e51SStefano Zampini 415bbbc8e51SStefano Zampini /* non-conforming meshes */ 4169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children)); 417bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 418bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 419bbbc8e51SStefano Zampini 420bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 421bbbc8e51SStefano Zampini row = rows[child-fStart]; 4229566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 423bbbc8e51SStefano Zampini } 424bbbc8e51SStefano Zampini } 425bbbc8e51SStefano Zampini } 4269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 4279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 4289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 4309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY)); 4319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY)); 432bbbc8e51SStefano Zampini 433bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 4349566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR)); 4359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 436bbbc8e51SStefano Zampini 437bbbc8e51SStefano Zampini /* extract local part of the CSR */ 4389566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn)); 4399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CSR)); 4409566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4415f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 442bbbc8e51SStefano Zampini 443bbbc8e51SStefano Zampini /* get back requested output */ 444bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 445bbbc8e51SStefano Zampini if (offsets) { 4469566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m+1, &idxs)); 447bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 448bbbc8e51SStefano Zampini *offsets = idxs; 449bbbc8e51SStefano Zampini } 450bbbc8e51SStefano Zampini if (adjacency) { 4519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ii[m] - m, &idxs)); 4529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis_own, &rows)); 453bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 454bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 455bbbc8e51SStefano Zampini 456bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 457bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 458bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 459bbbc8e51SStefano Zampini } 460bbbc8e51SStefano Zampini } 4615f80ce2aSJacob Faibussowitsch PetscCheck(c == ii[m] - m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 4629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis_own, &rows)); 463bbbc8e51SStefano Zampini *adjacency = idxs; 464bbbc8e51SStefano Zampini } 465bbbc8e51SStefano Zampini 466bbbc8e51SStefano Zampini /* cleanup */ 4679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis_own)); 4689566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4695f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 4709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 471bbbc8e51SStefano Zampini PetscFunctionReturn(0); 472bbbc8e51SStefano Zampini } 473bbbc8e51SStefano Zampini 474bbbc8e51SStefano Zampini /*@C 475bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 476bbbc8e51SStefano Zampini 477bbbc8e51SStefano Zampini Input Parameters: 478bbbc8e51SStefano Zampini + dm - The mesh DM dm 479bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 480bbbc8e51SStefano Zampini 481d8d19677SJose E. Roman Output Parameters: 482bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 483bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 484bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 485bbbc8e51SStefano 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. 486bbbc8e51SStefano Zampini 487bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 488bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 489bbbc8e51SStefano Zampini 4905a107427SMatthew G. Knepley Options Database Keys: 4915a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4925a107427SMatthew G. Knepley 493bbbc8e51SStefano Zampini Level: developer 494bbbc8e51SStefano Zampini 495bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 496bbbc8e51SStefano Zampini @*/ 497bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 498bbbc8e51SStefano Zampini { 4995a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH; 500bbbc8e51SStefano Zampini 501bbbc8e51SStefano Zampini PetscFunctionBegin; 5029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *) &alg, NULL)); 5035a107427SMatthew G. Knepley switch (alg) { 5045a107427SMatthew G. Knepley case DM_PLEX_CSR_MAT: 5059566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5065a107427SMatthew G. Knepley case DM_PLEX_CSR_GRAPH: 5079566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5085a107427SMatthew G. Knepley case DM_PLEX_CSR_OVERLAP: 5099566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 510bbbc8e51SStefano Zampini } 511bbbc8e51SStefano Zampini PetscFunctionReturn(0); 512bbbc8e51SStefano Zampini } 513bbbc8e51SStefano Zampini 514d5577e40SMatthew G. Knepley /*@C 515d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 516d5577e40SMatthew G. Knepley 517fe2efc57SMark Collective on DM 518d5577e40SMatthew G. Knepley 5194165533cSJose E. Roman Input Parameters: 520d5577e40SMatthew G. Knepley + dm - The DMPlex 521d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 522d5577e40SMatthew G. Knepley 5234165533cSJose E. Roman Output Parameters: 524d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 525d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 526d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 527d5577e40SMatthew G. Knepley 528d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 529d5577e40SMatthew G. Knepley 530d5577e40SMatthew G. Knepley Level: advanced 531d5577e40SMatthew G. Knepley 532d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 533d5577e40SMatthew G. Knepley @*/ 53470034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 53570034214SMatthew G. Knepley { 53670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 53770034214SMatthew G. Knepley PetscInt numFaceCases = 0; 53870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 53970034214SMatthew G. Knepley PetscInt *off, *adj; 54070034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 54170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 54270034214SMatthew G. Knepley 54370034214SMatthew G. Knepley PetscFunctionBegin; 54470034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 5459566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 54670034214SMatthew G. Knepley cellDim = dim - cellHeight; 5479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5489566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 54970034214SMatthew G. Knepley if (cEnd - cStart == 0) { 55070034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 55170034214SMatthew G. Knepley if (offsets) *offsets = NULL; 55270034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 55370034214SMatthew G. Knepley PetscFunctionReturn(0); 55470034214SMatthew G. Knepley } 55570034214SMatthew G. Knepley numCells = cEnd - cStart; 55670034214SMatthew G. Knepley faceDepth = depth - cellHeight; 55770034214SMatthew G. Knepley if (dim == depth) { 55870034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 55970034214SMatthew G. Knepley 5609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells+1, &off)); 56170034214SMatthew G. Knepley /* Count neighboring cells */ 5629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd)); 56370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 56470034214SMatthew G. Knepley const PetscInt *support; 56570034214SMatthew G. Knepley PetscInt supportSize; 5669566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5679566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 56870034214SMatthew G. Knepley if (supportSize == 2) { 5699ffc88e4SToby Isaac PetscInt numChildren; 5709ffc88e4SToby Isaac 5719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5729ffc88e4SToby Isaac if (!numChildren) { 57370034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 57470034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 57570034214SMatthew G. Knepley } 57670034214SMatthew G. Knepley } 5779ffc88e4SToby Isaac } 57870034214SMatthew G. Knepley /* Prefix sum */ 57970034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 58070034214SMatthew G. Knepley if (adjacency) { 58170034214SMatthew G. Knepley PetscInt *tmp; 58270034214SMatthew G. Knepley 5839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 5849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells+1, &tmp)); 5859566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(tmp, off, numCells+1)); 58670034214SMatthew G. Knepley /* Get neighboring cells */ 58770034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 58870034214SMatthew G. Knepley const PetscInt *support; 58970034214SMatthew G. Knepley PetscInt supportSize; 5909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 59270034214SMatthew G. Knepley if (supportSize == 2) { 5939ffc88e4SToby Isaac PetscInt numChildren; 5949ffc88e4SToby Isaac 5959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5969ffc88e4SToby Isaac if (!numChildren) { 59770034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 59870034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 59970034214SMatthew G. Knepley } 60070034214SMatthew G. Knepley } 6019ffc88e4SToby Isaac } 6025f80ce2aSJacob Faibussowitsch for (c = 0; c < cEnd-cStart; ++c) PetscAssert(tmp[c] == off[c+1],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 6039566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 60470034214SMatthew G. Knepley } 60570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 60670034214SMatthew G. Knepley if (offsets) *offsets = off; 60770034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 60870034214SMatthew G. Knepley PetscFunctionReturn(0); 60970034214SMatthew G. Knepley } 61070034214SMatthew G. Knepley /* Setup face recognition */ 61170034214SMatthew G. Knepley if (faceDepth == 1) { 61270034214SMatthew 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 */ 61370034214SMatthew G. Knepley 61470034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 61570034214SMatthew G. Knepley PetscInt corners; 61670034214SMatthew G. Knepley 6179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &corners)); 61870034214SMatthew G. Knepley if (!cornersSeen[corners]) { 61970034214SMatthew G. Knepley PetscInt nFV; 62070034214SMatthew G. Knepley 6215f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 62270034214SMatthew G. Knepley cornersSeen[corners] = 1; 62370034214SMatthew G. Knepley 6249566063dSJacob Faibussowitsch PetscCall(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV)); 62570034214SMatthew G. Knepley 62670034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 62770034214SMatthew G. Knepley } 62870034214SMatthew G. Knepley } 62970034214SMatthew G. Knepley } 6309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells+1, &off)); 63170034214SMatthew G. Knepley /* Count neighboring cells */ 63270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 63370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 63470034214SMatthew G. Knepley 6359566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 63670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 63770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 63870034214SMatthew G. Knepley PetscInt cellPair[2]; 63970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 64070034214SMatthew G. Knepley PetscInt meetSize = 0; 64170034214SMatthew G. Knepley const PetscInt *meet = NULL; 64270034214SMatthew G. Knepley 64370034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 64470034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 64570034214SMatthew G. Knepley if (!found) { 6469566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 64770034214SMatthew G. Knepley if (meetSize) { 64870034214SMatthew G. Knepley PetscInt f; 64970034214SMatthew G. Knepley 65070034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 65170034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 65270034214SMatthew G. Knepley found = PETSC_TRUE; 65370034214SMatthew G. Knepley break; 65470034214SMatthew G. Knepley } 65570034214SMatthew G. Knepley } 65670034214SMatthew G. Knepley } 6579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 65870034214SMatthew G. Knepley } 65970034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 66070034214SMatthew G. Knepley } 66170034214SMatthew G. Knepley } 66270034214SMatthew G. Knepley /* Prefix sum */ 66370034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 66470034214SMatthew G. Knepley 66570034214SMatthew G. Knepley if (adjacency) { 6669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 66770034214SMatthew G. Knepley /* Get neighboring cells */ 66870034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 66970034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 67070034214SMatthew G. Knepley PetscInt cellOffset = 0; 67170034214SMatthew G. Knepley 6729566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 67370034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 67470034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 67570034214SMatthew G. Knepley PetscInt cellPair[2]; 67670034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 67770034214SMatthew G. Knepley PetscInt meetSize = 0; 67870034214SMatthew G. Knepley const PetscInt *meet = NULL; 67970034214SMatthew G. Knepley 68070034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 68170034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 68270034214SMatthew G. Knepley if (!found) { 6839566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 68470034214SMatthew G. Knepley if (meetSize) { 68570034214SMatthew G. Knepley PetscInt f; 68670034214SMatthew G. Knepley 68770034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 68870034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 68970034214SMatthew G. Knepley found = PETSC_TRUE; 69070034214SMatthew G. Knepley break; 69170034214SMatthew G. Knepley } 69270034214SMatthew G. Knepley } 69370034214SMatthew G. Knepley } 6949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 69570034214SMatthew G. Knepley } 69670034214SMatthew G. Knepley if (found) { 69770034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 69870034214SMatthew G. Knepley ++cellOffset; 69970034214SMatthew G. Knepley } 70070034214SMatthew G. Knepley } 70170034214SMatthew G. Knepley } 70270034214SMatthew G. Knepley } 7039566063dSJacob Faibussowitsch PetscCall(PetscFree(neighborCells)); 70470034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 70570034214SMatthew G. Knepley if (offsets) *offsets = off; 70670034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 70770034214SMatthew G. Knepley PetscFunctionReturn(0); 70870034214SMatthew G. Knepley } 70970034214SMatthew G. Knepley 71077623264SMatthew G. Knepley /*@ 7113c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 71277623264SMatthew G. Knepley 713fe2efc57SMark Collective on PetscPartitioner 71477623264SMatthew G. Knepley 71577623264SMatthew G. Knepley Input Parameters: 71677623264SMatthew G. Knepley + part - The PetscPartitioner 7173c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 718f8987ae8SMichael Lange - dm - The mesh DM 71977623264SMatthew G. Knepley 72077623264SMatthew G. Knepley Output Parameters: 72177623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 722f8987ae8SMichael Lange - partition - The list of points by partition 72377623264SMatthew G. Knepley 7243c41b853SStefano Zampini Notes: 7253c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 7263c41b853SStefano Zampini by the section in the transitive closure of the point. 72777623264SMatthew G. Knepley 72877623264SMatthew G. Knepley Level: developer 72977623264SMatthew G. Knepley 7303c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition() 7314b15ede2SMatthew G. Knepley @*/ 7323c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 73377623264SMatthew G. Knepley { 73477623264SMatthew G. Knepley PetscMPIInt size; 7353c41b853SStefano Zampini PetscBool isplex; 7363c41b853SStefano Zampini PetscSection vertSection = NULL; 73777623264SMatthew G. Knepley 73877623264SMatthew G. Knepley PetscFunctionBegin; 73977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 74077623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7413c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 74277623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 74377623264SMatthew G. Knepley PetscValidPointer(partition, 5); 7449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex)); 7455f80ce2aSJacob Faibussowitsch PetscCheck(isplex,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 7469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) part), &size)); 74777623264SMatthew G. Knepley if (size == 1) { 74877623264SMatthew G. Knepley PetscInt *points; 74977623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 75077623264SMatthew G. Knepley 7519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 7529566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(partSection)); 7539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(partSection, 0, size)); 7549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(partSection, 0, cEnd-cStart)); 7559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(partSection)); 7569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd-cStart, &points)); 75777623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 7589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition)); 75977623264SMatthew G. Knepley PetscFunctionReturn(0); 76077623264SMatthew G. Knepley } 76177623264SMatthew G. Knepley if (part->height == 0) { 762074d466cSStefano Zampini PetscInt numVertices = 0; 76377623264SMatthew G. Knepley PetscInt *start = NULL; 76477623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7653fa7752dSToby Isaac IS globalNumbering; 76677623264SMatthew G. Knepley 767074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 7689566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering)); 76913911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 770074d466cSStefano Zampini const PetscInt *idxs; 771074d466cSStefano Zampini PetscInt p, pStart, pEnd; 772074d466cSStefano Zampini 7739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering)); 7759566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &idxs)); 776074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 7779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &idxs)); 778074d466cSStefano Zampini } 7793c41b853SStefano Zampini if (part->usevwgt) { 7803c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7813c41b853SStefano Zampini IS clPoints = NULL; 7823c41b853SStefano Zampini const PetscInt *gid,*clIdx; 7833c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7840358368aSMatthew G. Knepley 7853c41b853SStefano 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) */ 7863c41b853SStefano Zampini /* We do this only if the local section has been set */ 7873c41b853SStefano Zampini if (section) { 7889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL)); 7893c41b853SStefano Zampini if (!clSection) { 7909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateClosureIndex(dm,NULL)); 7913c41b853SStefano Zampini } 7929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints)); 7939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(clPoints,&clIdx)); 7943c41b853SStefano Zampini } 7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7969566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &vertSection)); 7979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(vertSection, 0, numVertices)); 7983c41b853SStefano Zampini if (globalNumbering) { 7999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering,&gid)); 8003c41b853SStefano Zampini } else gid = NULL; 8013c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 8023c41b853SStefano Zampini PetscInt dof = 1; 8030358368aSMatthew G. Knepley 8043c41b853SStefano Zampini /* skip cells in the overlap */ 8053c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 8063c41b853SStefano Zampini 8073c41b853SStefano Zampini if (section) { 8083c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8093c41b853SStefano Zampini 8103c41b853SStefano Zampini dof = 0; 8119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(clSection, p, &clSize)); 8129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(clSection, p, &clOff)); 8133c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 8143c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8153c41b853SStefano Zampini 8169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, clPoint, &clDof)); 8173c41b853SStefano Zampini dof += clDof; 8180358368aSMatthew G. Knepley } 8190358368aSMatthew G. Knepley } 8205f80ce2aSJacob Faibussowitsch PetscCheck(dof,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p); 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(vertSection, v, dof)); 8223c41b853SStefano Zampini v++; 8233c41b853SStefano Zampini } 8243c41b853SStefano Zampini if (globalNumbering) { 8259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering,&gid)); 8263c41b853SStefano Zampini } 8273c41b853SStefano Zampini if (clPoints) { 8289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(clPoints,&clIdx)); 8293c41b853SStefano Zampini } 8309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(vertSection)); 8313c41b853SStefano Zampini } 8329566063dSJacob Faibussowitsch PetscCall(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition)); 8339566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 8349566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 8353fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8363fa7752dSToby Isaac const PetscInt *globalNum; 8373fa7752dSToby Isaac const PetscInt *partIdx; 8383fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8393fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8403fa7752dSToby Isaac IS newPartition; 8413fa7752dSToby Isaac 8429566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*partition,&localSize)); 8439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize,&adjusted)); 8449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering,&globalNum)); 8459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*partition,&partIdx)); 8469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize,&map)); 8479566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 8483fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8493fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8503fa7752dSToby Isaac } 8513fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 8523fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 8533fa7752dSToby Isaac } 8549566063dSJacob Faibussowitsch PetscCall(PetscFree(map)); 8559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*partition,&partIdx)); 8569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering,&globalNum)); 8579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition)); 8589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalNumbering)); 8599566063dSJacob Faibussowitsch PetscCall(ISDestroy(partition)); 8603fa7752dSToby Isaac *partition = newPartition; 8613fa7752dSToby Isaac } 86298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 8639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&vertSection)); 86477623264SMatthew G. Knepley PetscFunctionReturn(0); 86577623264SMatthew G. Knepley } 86677623264SMatthew G. Knepley 8675680f57bSMatthew G. Knepley /*@ 8685680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8695680f57bSMatthew G. Knepley 8705680f57bSMatthew G. Knepley Not collective 8715680f57bSMatthew G. Knepley 8725680f57bSMatthew G. Knepley Input Parameter: 8735680f57bSMatthew G. Knepley . dm - The DM 8745680f57bSMatthew G. Knepley 8755680f57bSMatthew G. Knepley Output Parameter: 8765680f57bSMatthew G. Knepley . part - The PetscPartitioner 8775680f57bSMatthew G. Knepley 8785680f57bSMatthew G. Knepley Level: developer 8795680f57bSMatthew G. Knepley 88098599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 88198599a47SLawrence Mitchell 8823c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate() 8835680f57bSMatthew G. Knepley @*/ 8845680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 8855680f57bSMatthew G. Knepley { 8865680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 8875680f57bSMatthew G. Knepley 8885680f57bSMatthew G. Knepley PetscFunctionBegin; 8895680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8905680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 8915680f57bSMatthew G. Knepley *part = mesh->partitioner; 8925680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8935680f57bSMatthew G. Knepley } 8945680f57bSMatthew G. Knepley 89571bb2955SLawrence Mitchell /*@ 89671bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 89771bb2955SLawrence Mitchell 898fe2efc57SMark logically collective on DM 89971bb2955SLawrence Mitchell 90071bb2955SLawrence Mitchell Input Parameters: 90171bb2955SLawrence Mitchell + dm - The DM 90271bb2955SLawrence Mitchell - part - The partitioner 90371bb2955SLawrence Mitchell 90471bb2955SLawrence Mitchell Level: developer 90571bb2955SLawrence Mitchell 90671bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 90771bb2955SLawrence Mitchell 90871bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 90971bb2955SLawrence Mitchell @*/ 91071bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 91171bb2955SLawrence Mitchell { 91271bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 91371bb2955SLawrence Mitchell 91471bb2955SLawrence Mitchell PetscFunctionBegin; 91571bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91671bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 9179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)part)); 9189566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 91971bb2955SLawrence Mitchell mesh->partitioner = part; 92071bb2955SLawrence Mitchell PetscFunctionReturn(0); 92171bb2955SLawrence Mitchell } 92271bb2955SLawrence Mitchell 9238e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 9248e330a33SStefano Zampini { 9258e330a33SStefano Zampini const PetscInt *cone; 9268e330a33SStefano Zampini PetscInt coneSize, c; 9278e330a33SStefano Zampini PetscBool missing; 9288e330a33SStefano Zampini 9298e330a33SStefano Zampini PetscFunctionBeginHot; 9309566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, point, &missing)); 9318e330a33SStefano Zampini if (missing) { 9329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 9348e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9359566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, cone[c])); 9368e330a33SStefano Zampini } 9378e330a33SStefano Zampini } 9388e330a33SStefano Zampini PetscFunctionReturn(0); 9398e330a33SStefano Zampini } 9408e330a33SStefano Zampini 9418e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 942270bba0cSToby Isaac { 943270bba0cSToby Isaac PetscFunctionBegin; 9446a5a2ffdSToby Isaac if (up) { 9456a5a2ffdSToby Isaac PetscInt parent; 9466a5a2ffdSToby Isaac 9479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,point,&parent,NULL)); 9486a5a2ffdSToby Isaac if (parent != point) { 9496a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9506a5a2ffdSToby Isaac 9519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 952270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 953270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 954270bba0cSToby Isaac 9559566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9569566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE)); 957270bba0cSToby Isaac } 9589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 9596a5a2ffdSToby Isaac } 9606a5a2ffdSToby Isaac } 9616a5a2ffdSToby Isaac if (down) { 9626a5a2ffdSToby Isaac PetscInt numChildren; 9636a5a2ffdSToby Isaac const PetscInt *children; 9646a5a2ffdSToby Isaac 9659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,point,&numChildren,&children)); 9666a5a2ffdSToby Isaac if (numChildren) { 9676a5a2ffdSToby Isaac PetscInt i; 9686a5a2ffdSToby Isaac 9696a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9706a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9716a5a2ffdSToby Isaac 9729566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9739566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE)); 9746a5a2ffdSToby Isaac } 9756a5a2ffdSToby Isaac } 9766a5a2ffdSToby Isaac } 977270bba0cSToby Isaac PetscFunctionReturn(0); 978270bba0cSToby Isaac } 979270bba0cSToby Isaac 9808e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 9818e330a33SStefano Zampini { 9828e330a33SStefano Zampini PetscInt parent; 983825f8a23SLisandro Dalcin 9848e330a33SStefano Zampini PetscFunctionBeginHot; 9859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent,NULL)); 9868e330a33SStefano Zampini if (point != parent) { 9878e330a33SStefano Zampini const PetscInt *cone; 9888e330a33SStefano Zampini PetscInt coneSize, c; 9898e330a33SStefano Zampini 9909566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, parent)); 9919566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, parent)); 9929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, parent, &cone)); 9939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 9948e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9958e330a33SStefano Zampini const PetscInt cp = cone[c]; 9968e330a33SStefano Zampini 9979566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, cp)); 9988e330a33SStefano Zampini } 9998e330a33SStefano Zampini } 10008e330a33SStefano Zampini PetscFunctionReturn(0); 10018e330a33SStefano Zampini } 10028e330a33SStefano Zampini 10038e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 10048e330a33SStefano Zampini { 10058e330a33SStefano Zampini PetscInt i, numChildren; 10068e330a33SStefano Zampini const PetscInt *children; 10078e330a33SStefano Zampini 10088e330a33SStefano Zampini PetscFunctionBeginHot; 10099566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 10108e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 10119566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, children[i])); 10128e330a33SStefano Zampini } 10138e330a33SStefano Zampini PetscFunctionReturn(0); 10148e330a33SStefano Zampini } 10158e330a33SStefano Zampini 10168e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 10178e330a33SStefano Zampini { 10188e330a33SStefano Zampini const PetscInt *cone; 10198e330a33SStefano Zampini PetscInt coneSize, c; 10208e330a33SStefano Zampini 10218e330a33SStefano Zampini PetscFunctionBeginHot; 10229566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 10239566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, point)); 10249566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Down_Private(dm, ht, point)); 10259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 10269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 10278e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 10289566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Private(dm, ht, cone[c])); 10298e330a33SStefano Zampini } 10308e330a33SStefano Zampini PetscFunctionReturn(0); 10318e330a33SStefano Zampini } 10328e330a33SStefano Zampini 10338e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 1034825f8a23SLisandro Dalcin { 1035825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10368e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10378e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 103827104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1039825f8a23SLisandro Dalcin 1040825f8a23SLisandro Dalcin PetscFunctionBegin; 10419566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 10429566063dSJacob Faibussowitsch PetscCall(PetscHSetIResize(ht, numPoints*16)); 10438e330a33SStefano Zampini if (!hasTree) { 10448e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10459566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, points[p])); 10468e330a33SStefano Zampini } 10478e330a33SStefano Zampini } else { 10488e330a33SStefano Zampini #if 1 10498e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10509566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Private(dm, ht, points[p])); 10518e330a33SStefano Zampini } 10528e330a33SStefano Zampini #else 10538e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1054825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 10559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 1056825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 10579566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closure[c])); 10589566063dSJacob Faibussowitsch if (hasTree) PetscCall(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE)); 1059825f8a23SLisandro Dalcin } 1060825f8a23SLisandro Dalcin } 10619566063dSJacob Faibussowitsch if (closure) PetscCall(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure)); 10628e330a33SStefano Zampini #endif 10638e330a33SStefano Zampini } 10649566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nelems)); 10659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nelems, &elems)); 10669566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &off, elems)); 10679566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 10689566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nelems, elems)); 10699566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS)); 1070825f8a23SLisandro Dalcin PetscFunctionReturn(0); 1071825f8a23SLisandro Dalcin } 1072825f8a23SLisandro Dalcin 10735abbe4feSMichael Lange /*@ 10745abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10755abbe4feSMichael Lange 10765abbe4feSMichael Lange Input Parameters: 10775abbe4feSMichael Lange + dm - The DM 1078a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 10795abbe4feSMichael Lange 10805abbe4feSMichael Lange Level: developer 10815abbe4feSMichael Lange 108230b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 10835abbe4feSMichael Lange @*/ 10845abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 10859ffc88e4SToby Isaac { 1086825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 10875abbe4feSMichael Lange const PetscInt *ranks, *points; 1088825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 10899ffc88e4SToby Isaac 10909ffc88e4SToby Isaac PetscFunctionBegin; 10919566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 10929566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 10939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 10945abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10955abbe4feSMichael Lange const PetscInt rank = ranks[r]; 10969566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 10979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 10989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 10999566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS)); 11009566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 11019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11029566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, rank, closureIS)); 11039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&closureIS)); 11049ffc88e4SToby Isaac } 11059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11079ffc88e4SToby Isaac PetscFunctionReturn(0); 11089ffc88e4SToby Isaac } 11099ffc88e4SToby Isaac 111024d039d7SMichael Lange /*@ 111124d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 111224d039d7SMichael Lange 111324d039d7SMichael Lange Input Parameters: 111424d039d7SMichael Lange + dm - The DM 1115a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 111624d039d7SMichael Lange 111724d039d7SMichael Lange Level: developer 111824d039d7SMichael Lange 11192d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 112024d039d7SMichael Lange @*/ 112124d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 112270034214SMatthew G. Knepley { 112324d039d7SMichael Lange IS rankIS, pointIS; 112424d039d7SMichael Lange const PetscInt *ranks, *points; 112524d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 112624d039d7SMichael Lange PetscInt *adj = NULL; 112770034214SMatthew G. Knepley 112870034214SMatthew G. Knepley PetscFunctionBegin; 11299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 11309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 113224d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 113324d039d7SMichael Lange const PetscInt rank = ranks[r]; 113470034214SMatthew G. Knepley 11359566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 11369566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 11379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 113870034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 113924d039d7SMichael Lange adjSize = PETSC_DETERMINE; 11409566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj)); 11419566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(label, adj[a], rank)); 114270034214SMatthew G. Knepley } 11439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 11449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 114570034214SMatthew G. Knepley } 11469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11489566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 114924d039d7SMichael Lange PetscFunctionReturn(0); 115070034214SMatthew G. Knepley } 115170034214SMatthew G. Knepley 1152be200f8dSMichael Lange /*@ 1153be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1154be200f8dSMichael Lange 1155be200f8dSMichael Lange Input Parameters: 1156be200f8dSMichael Lange + dm - The DM 1157a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1158be200f8dSMichael Lange 1159be200f8dSMichael Lange Level: developer 1160be200f8dSMichael Lange 1161be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1162be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1163be200f8dSMichael Lange 11642d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 1165be200f8dSMichael Lange @*/ 1166be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1167be200f8dSMichael Lange { 1168be200f8dSMichael Lange MPI_Comm comm; 1169be200f8dSMichael Lange PetscMPIInt rank; 1170be200f8dSMichael Lange PetscSF sfPoint; 11715d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1172be200f8dSMichael Lange IS rankIS, pointIS; 1173be200f8dSMichael Lange const PetscInt *ranks; 1174be200f8dSMichael Lange PetscInt numRanks, r; 1175be200f8dSMichael Lange 1176be200f8dSMichael Lange PetscFunctionBegin; 11779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 11789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11799566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 11805d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 11819566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 11829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &rankIS)); 11839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11849566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 11855d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 11865d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 11875d04f6ebSMichael Lange if (remoteRank == rank) continue; 11889566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS)); 11899566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 11909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11915d04f6ebSMichael Lange } 11929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11949566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 1195be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 11969566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 11979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &rankIS)); 11989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 1200be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1201be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1202be200f8dSMichael Lange if (remoteRank == rank) continue; 12039566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS)); 12049566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 12059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 1206be200f8dSMichael Lange } 12079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 12089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 12099566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 1210be200f8dSMichael Lange PetscFunctionReturn(0); 1211be200f8dSMichael Lange } 1212be200f8dSMichael Lange 12131fd9873aSMichael Lange /*@ 12141fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 12151fd9873aSMichael Lange 12161fd9873aSMichael Lange Input Parameters: 12171fd9873aSMichael Lange + dm - The DM 1218a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots 1219fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 12201fd9873aSMichael Lange 12211fd9873aSMichael Lange Output Parameter: 1222a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots 12231fd9873aSMichael Lange 12241fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 12251fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 12261fd9873aSMichael Lange 12271fd9873aSMichael Lange Level: developer 12281fd9873aSMichael Lange 12292d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 12301fd9873aSMichael Lange @*/ 12311fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 12321fd9873aSMichael Lange { 12331fd9873aSMichael Lange MPI_Comm comm; 1234874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1235874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12361fd9873aSMichael Lange PetscSF sfPoint; 1237874ddda9SLisandro Dalcin PetscSection rootSection; 12381fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12391fd9873aSMichael Lange const PetscSFNode *remote; 12401fd9873aSMichael Lange const PetscInt *local, *neighbors; 12411fd9873aSMichael Lange IS valueIS; 1242874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12431fd9873aSMichael Lange 12441fd9873aSMichael Lange PetscFunctionBegin; 12459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0)); 12469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 12479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 12499566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 12501fd9873aSMichael Lange 12511fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 12529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 12539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, 0, size)); 12549566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(rootLabel, &valueIS)); 12559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numNeighbors)); 12569566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &neighbors)); 12571fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12589566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints)); 12599566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(rootSection, neighbors[n], numPoints)); 12601fd9873aSMichael Lange } 12619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 12629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &rootSize)); 12639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rootSize, &rootPoints)); 12649566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 12651fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12661fd9873aSMichael Lange IS pointIS; 12671fd9873aSMichael Lange const PetscInt *points; 12681fd9873aSMichael Lange 12699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 12709566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS)); 12719566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 12729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 12731fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 12749566063dSJacob Faibussowitsch if (local) PetscCall(PetscFindInt(points[p], nleaves, local, &l)); 1275f8987ae8SMichael Lange else {l = -1;} 12761fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 12771fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 12781fd9873aSMichael Lange } 12799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 12809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 12811fd9873aSMichael Lange } 1282874ddda9SLisandro Dalcin 1283874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1284874ddda9SLisandro Dalcin if (!processSF) { 1285874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1286874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1287874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1288874ddda9SLisandro Dalcin 12899566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls)); 1290874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 12919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, neighbors[n], &dof)); 12929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1293874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 1294874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1295874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1296874ddda9SLisandro Dalcin #endif 1297874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 1298874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 1299874ddda9SLisandro Dalcin } 13009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm)); 1301874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 1302874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 13039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm)); 1304874ddda9SLisandro Dalcin if (!mpiOverflow) { 13059566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using Alltoallv for mesh distribution\n")); 1306874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 13079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafSize, &leafPoints)); 13089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm)); 1309874ddda9SLisandro Dalcin } 13109566063dSJacob Faibussowitsch PetscCall(PetscFree4(scounts, sdispls, rcounts, rdispls)); 1311874ddda9SLisandro Dalcin } 1312874ddda9SLisandro Dalcin 1313874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1314874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1315874ddda9SLisandro Dalcin PetscSF procSF; 1316874ddda9SLisandro Dalcin PetscSection leafSection; 1317874ddda9SLisandro Dalcin 1318874ddda9SLisandro Dalcin if (processSF) { 13199566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using processSF for mesh distribution\n")); 13209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)processSF)); 1321874ddda9SLisandro Dalcin procSF = processSF; 1322874ddda9SLisandro Dalcin } else { 13239566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n")); 13249566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&procSF)); 13259566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL)); 1326874ddda9SLisandro Dalcin } 1327874ddda9SLisandro Dalcin 13289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection)); 13299566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints)); 13309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSection, &leafSize)); 13319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 13329566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&procSF)); 1333874ddda9SLisandro Dalcin } 1334874ddda9SLisandro Dalcin 1335874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 13369566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank)); 13371fd9873aSMichael Lange } 1338874ddda9SLisandro Dalcin 13399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &neighbors)); 13409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 13419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 13429566063dSJacob Faibussowitsch PetscCall(PetscFree(rootPoints)); 13439566063dSJacob Faibussowitsch PetscCall(PetscFree(leafPoints)); 13449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0)); 13451fd9873aSMichael Lange PetscFunctionReturn(0); 13461fd9873aSMichael Lange } 13471fd9873aSMichael Lange 1348aa3148a8SMichael Lange /*@ 1349aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1350aa3148a8SMichael Lange 1351aa3148a8SMichael Lange Input Parameters: 1352aa3148a8SMichael Lange + dm - The DM 1353a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1354aa3148a8SMichael Lange 1355aa3148a8SMichael Lange Output Parameter: 1356fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1357aa3148a8SMichael Lange 1358aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1359aa3148a8SMichael Lange 1360aa3148a8SMichael Lange Level: developer 1361aa3148a8SMichael Lange 136230b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 1363aa3148a8SMichael Lange @*/ 1364aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1365aa3148a8SMichael Lange { 13666e203dd9SStefano Zampini PetscMPIInt rank; 13676e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1368aa3148a8SMichael Lange PetscSFNode *remotePoints; 13696e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13706e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1371aa3148a8SMichael Lange 1372aa3148a8SMichael Lange PetscFunctionBegin; 13739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 13749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 1375aa3148a8SMichael Lange 13769566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &neighborsIS)); 13776e203dd9SStefano Zampini #if 0 13786e203dd9SStefano Zampini { 13796e203dd9SStefano Zampini IS is; 13809566063dSJacob Faibussowitsch PetscCall(ISDuplicate(neighborsIS, &is)); 13819566063dSJacob Faibussowitsch PetscCall(ISSort(is)); 13829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 13836e203dd9SStefano Zampini neighborsIS = is; 13846e203dd9SStefano Zampini } 13856e203dd9SStefano Zampini #endif 13869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neighborsIS, &nNeighbors)); 13879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(neighborsIS, &neighbors)); 13886e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 13899566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, neighbors[n], &numPoints)); 1390aa3148a8SMichael Lange numRemote += numPoints; 1391aa3148a8SMichael Lange } 13929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRemote, &remotePoints)); 139343f7d02bSMichael Lange /* Put owned points first */ 13949566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, rank, &numPoints)); 139543f7d02bSMichael Lange if (numPoints > 0) { 13969566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &remoteRootIS)); 13979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 139843f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 139943f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 140043f7d02bSMichael Lange remotePoints[idx].rank = rank; 140143f7d02bSMichael Lange idx++; 140243f7d02bSMichael Lange } 14039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 140543f7d02bSMichael Lange } 140643f7d02bSMichael Lange /* Now add remote points */ 14076e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 14086e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 14096e203dd9SStefano Zampini 14109566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, nn, &numPoints)); 14116e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 14129566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, nn, &remoteRootIS)); 14139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 1414aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1415aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 14166e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1417aa3148a8SMichael Lange idx++; 1418aa3148a8SMichael Lange } 14199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 1421aa3148a8SMichael Lange } 14229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject) dm), sf)); 14239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14249566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 14259566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sf)); 14269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 14279566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 142870034214SMatthew G. Knepley PetscFunctionReturn(0); 142970034214SMatthew G. Knepley } 1430cb87ef4cSFlorian Wechsung 1431abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1432abe9303eSLisandro Dalcin #include <parmetis.h> 1433abe9303eSLisandro Dalcin #endif 1434abe9303eSLisandro Dalcin 14356a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14366a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14376a3739e5SFlorian Wechsung * them out in that case. */ 14386a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 14397a82c785SFlorian Wechsung /*@C 14407f57c1a4SFlorian Wechsung 14417f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 14427f57c1a4SFlorian Wechsung 14437f57c1a4SFlorian Wechsung Input parameters: 14447f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1445fe2efc57SMark . n - The number of points. 1446fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1447fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1448fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 14497f57c1a4SFlorian Wechsung 14507f57c1a4SFlorian Wechsung Level: developer 14517f57c1a4SFlorian Wechsung 14527f57c1a4SFlorian Wechsung @*/ 14537f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 14547f57c1a4SFlorian Wechsung { 14555f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14567f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14577f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14587f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14597f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14607f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14617f57c1a4SFlorian Wechsung PetscSF sf; 14627f57c1a4SFlorian Wechsung MPI_Comm comm; 14635a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14647f57c1a4SFlorian Wechsung 14657f57c1a4SFlorian Wechsung PetscFunctionBegin; 14669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 14679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14707f57c1a4SFlorian Wechsung 14719566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 14729566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 14739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isLeaf)); 14747f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14757f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 14767f57c1a4SFlorian Wechsung } 14777f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 14787f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 14797f57c1a4SFlorian Wechsung } 14807f57c1a4SFlorian Wechsung 14819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart+1, &cumSumDegrees)); 14827f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 14837f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 14847f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 14857f57c1a4SFlorian Wechsung } 14867f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 14877f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 14887f57c1a4SFlorian Wechsung 14899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &locationsOfLeafs)); 14909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &rankOnLeafs)); 14917f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14927f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 14937f57c1a4SFlorian Wechsung } 14949566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14959566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 14969566063dSJacob Faibussowitsch PetscCall(PetscFree(rankOnLeafs)); 14977f57c1a4SFlorian Wechsung 14987f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 14999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs)); 15009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &points)); 15017f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15027f57c1a4SFlorian Wechsung points[i] = pStart+i; 15037f57c1a4SFlorian Wechsung } 15049566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15059566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15069566063dSJacob Faibussowitsch PetscCall(PetscFree(points)); 15077f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 15089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &newOwners)); 15099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &newNumbers)); 15107f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15117f57c1a4SFlorian Wechsung newOwners[i] = -1; 15127f57c1a4SFlorian Wechsung newNumbers[i] = -1; 15137f57c1a4SFlorian Wechsung } 15147f57c1a4SFlorian Wechsung { 15157f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 15167f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 15177f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 15187f57c1a4SFlorian Wechsung newNumber = -1; 15197f57c1a4SFlorian Wechsung oldOwner = rank; 15207f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 15217f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 15227f57c1a4SFlorian Wechsung newNumber = oldNumber; 15237f57c1a4SFlorian Wechsung } else { 15247f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 15257f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 15267f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 15277f57c1a4SFlorian Wechsung break; 15287f57c1a4SFlorian Wechsung } 15297f57c1a4SFlorian Wechsung } 15307f57c1a4SFlorian Wechsung } 15315f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 15327f57c1a4SFlorian Wechsung 15337f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 15347f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 15357f57c1a4SFlorian Wechsung } 15367f57c1a4SFlorian Wechsung } 15379566063dSJacob Faibussowitsch PetscCall(PetscFree(cumSumDegrees)); 15389566063dSJacob Faibussowitsch PetscCall(PetscFree(locationsOfLeafs)); 15399566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteLocalPointOfLeafs)); 15407f57c1a4SFlorian Wechsung 15419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 15429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 15439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 15449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 15457f57c1a4SFlorian Wechsung 15467f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15477f57c1a4SFlorian Wechsung leafCounter=0; 15487f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15497f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15507f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15517f57c1a4SFlorian Wechsung leafCounter++; 15527f57c1a4SFlorian Wechsung } 15537f57c1a4SFlorian Wechsung } else { 15547f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15557f57c1a4SFlorian Wechsung leafCounter++; 15567f57c1a4SFlorian Wechsung } 15577f57c1a4SFlorian Wechsung } 15587f57c1a4SFlorian Wechsung } 15597f57c1a4SFlorian Wechsung 15607f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 15619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafsNew)); 15629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafLocationsNew)); 15637f57c1a4SFlorian Wechsung 15647f57c1a4SFlorian Wechsung leafCounter = 0; 15657f57c1a4SFlorian Wechsung counter = 0; 15667f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15677f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15687f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15697f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15707f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15717f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15727f57c1a4SFlorian Wechsung leafCounter++; 15737f57c1a4SFlorian Wechsung } 15747f57c1a4SFlorian Wechsung } else { 15757f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15767f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15777f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15787f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 15797f57c1a4SFlorian Wechsung leafCounter++; 15807f57c1a4SFlorian Wechsung } 15817f57c1a4SFlorian Wechsung } 15827f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15837f57c1a4SFlorian Wechsung counter++; 15847f57c1a4SFlorian Wechsung } 15857f57c1a4SFlorian Wechsung } 15867f57c1a4SFlorian Wechsung 15879566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER)); 15889566063dSJacob Faibussowitsch PetscCall(PetscFree(newOwners)); 15899566063dSJacob Faibussowitsch PetscCall(PetscFree(newNumbers)); 15909566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 15917f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 15927f57c1a4SFlorian Wechsung } 15937f57c1a4SFlorian Wechsung 1594125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1595125d2a8fSFlorian Wechsung { 15965f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum; 15975a30b08bSFlorian Wechsung PetscMPIInt rank, size; 15985f80ce2aSJacob Faibussowitsch 1599125d2a8fSFlorian Wechsung PetscFunctionBegin; 16009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 16019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16029566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &distribution)); 16035f80ce2aSJacob Faibussowitsch for (PetscInt i=0; i<n; i++) { 1604125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 1605125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 1606125d2a8fSFlorian Wechsung } 16079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm)); 1608125d2a8fSFlorian Wechsung min = distribution[0]; 1609125d2a8fSFlorian Wechsung max = distribution[0]; 1610125d2a8fSFlorian Wechsung sum = distribution[0]; 16115f80ce2aSJacob Faibussowitsch for (PetscInt i=1; i<size; i++) { 1612125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 1613125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 1614125d2a8fSFlorian Wechsung sum += distribution[i]; 1615125d2a8fSFlorian Wechsung } 16169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum)); 16179566063dSJacob Faibussowitsch PetscCall(PetscFree(distribution)); 1618125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1619125d2a8fSFlorian Wechsung } 1620125d2a8fSFlorian Wechsung 16216a3739e5SFlorian Wechsung #endif 16226a3739e5SFlorian Wechsung 1623cb87ef4cSFlorian Wechsung /*@ 16245dc86ac1SFlorian 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. 1625cb87ef4cSFlorian Wechsung 1626cb87ef4cSFlorian Wechsung Input parameters: 1627ed44d270SFlorian Wechsung + dm - The DMPlex object. 1628fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1629fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1630fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1631cb87ef4cSFlorian Wechsung 16328b879b41SFlorian Wechsung Output parameters: 1633fe2efc57SMark . success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 16348b879b41SFlorian Wechsung 163590ea27d8SSatish Balay Level: intermediate 1636cb87ef4cSFlorian Wechsung 1637cb87ef4cSFlorian Wechsung @*/ 1638cb87ef4cSFlorian Wechsung 16398b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1640cb87ef4cSFlorian Wechsung { 164141525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1642cb87ef4cSFlorian Wechsung PetscSF sf; 16430faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16447f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16457f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16467f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1647cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1648cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1649cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16507f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16515dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1652cb87ef4cSFlorian Wechsung PetscInt offset, counter; 16537f57c1a4SFlorian Wechsung PetscInt lenadjncy; 1654cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 1655cb87ef4cSFlorian Wechsung PetscInt lenxadj; 1656cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 1657cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1658cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1659cb87ef4cSFlorian Wechsung real_t *ubvec; 1660cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1661cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1662cb87ef4cSFlorian Wechsung MPI_Comm comm; 16634baf1206SFlorian Wechsung Mat A, Apre; 166412617df9SFlorian Wechsung const char *prefix = NULL; 16657d197802SFlorian Wechsung PetscViewer viewer; 16667d197802SFlorian Wechsung PetscViewerFormat format; 16675a30b08bSFlorian Wechsung PetscLayout layout; 166812617df9SFlorian Wechsung 166912617df9SFlorian Wechsung PetscFunctionBegin; 16708b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 16719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject) dm, &comm)); 16729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 16747f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 16757f57c1a4SFlorian Wechsung 16769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 167741525646SFlorian Wechsung 16789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL)); 16795dc86ac1SFlorian Wechsung if (viewer) { 16809566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,format)); 16817d197802SFlorian Wechsung } 16827d197802SFlorian Wechsung 1683ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 16849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd)); 16859566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &toBalance)); 1687cf818975SFlorian Wechsung 1688cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 16895a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 1690cb87ef4cSFlorian Wechsung } 1691cb87ef4cSFlorian Wechsung 1692cf818975SFlorian Wechsung /* There are three types of points: 1693cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1694cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1695cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1696cf818975SFlorian Wechsung */ 16979566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 16989566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 16999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isLeaf)); 17009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned)); 17019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &isExclusivelyOwned)); 1702cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1703cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1704cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1705cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1706cb87ef4cSFlorian Wechsung } 1707cf818975SFlorian Wechsung 1708cf818975SFlorian Wechsung /* start by marking all the leafs */ 1709cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 1710cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 1711cb87ef4cSFlorian Wechsung } 1712cb87ef4cSFlorian Wechsung 1713cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1714cf818975SFlorian Wechsung * not by calculating its degree */ 17159566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, °rees)); 17169566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, °rees)); 1717cf818975SFlorian Wechsung 1718cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1719cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1720cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1721cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17227f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1723cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1724cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1725cb87ef4cSFlorian Wechsung } else { 1726cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1727cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1728cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1729cb87ef4cSFlorian Wechsung } 1730cb87ef4cSFlorian Wechsung } 1731cb87ef4cSFlorian Wechsung } 1732cb87ef4cSFlorian Wechsung } 1733cb87ef4cSFlorian Wechsung 1734cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 1735cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1736cf818975SFlorian Wechsung * point. */ 1737cb87ef4cSFlorian Wechsung 17389566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout)); 17399566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned)); 17409566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 17419566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &cumSumVertices)); 17425dc86ac1SFlorian Wechsung 17439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices)); 17445a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 1745cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1746cb87ef4cSFlorian Wechsung counter = 0; 1747cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1748cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17497f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1750cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1751cb87ef4cSFlorian Wechsung counter++; 1752cb87ef4cSFlorian Wechsung } 1753cb87ef4cSFlorian Wechsung } 1754cb87ef4cSFlorian Wechsung } 1755cb87ef4cSFlorian Wechsung 1756cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 17579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd-pStart, &leafGlobalNumbers)); 17589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 17599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 1760cb87ef4cSFlorian Wechsung 17610faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 1762cb87ef4cSFlorian Wechsung 17639566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Apre)); 17649566063dSJacob Faibussowitsch PetscCall(MatSetType(Apre, MATPREALLOCATOR)); 17659566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size])); 17669566063dSJacob Faibussowitsch PetscCall(MatSetUp(Apre)); 17678c9a1619SFlorian Wechsung 17688c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17698c9a1619SFlorian Wechsung if (toBalance[i]) { 17700faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17710faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17720faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17730faf6628SFlorian Wechsung else continue; 17749566063dSJacob Faibussowitsch PetscCall(MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES)); 17759566063dSJacob Faibussowitsch PetscCall(MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES)); 17764baf1206SFlorian Wechsung } 17774baf1206SFlorian Wechsung } 17784baf1206SFlorian Wechsung 17799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY)); 17809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY)); 17814baf1206SFlorian Wechsung 17829566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 17839566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPIAIJ)); 17849566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size])); 17859566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(Apre, PETSC_FALSE, A)); 17869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Apre)); 17874baf1206SFlorian Wechsung 17884baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17894baf1206SFlorian Wechsung if (toBalance[i]) { 17900faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17910faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17920faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17930faf6628SFlorian Wechsung else continue; 17949566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, idx, jdx, 1, INSERT_VALUES)); 17959566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, jdx, idx, 1, INSERT_VALUES)); 17960941debbSFlorian Wechsung } 17970941debbSFlorian Wechsung } 17988c9a1619SFlorian Wechsung 17999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 18009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 18019566063dSJacob Faibussowitsch PetscCall(PetscFree(leafGlobalNumbers)); 18029566063dSJacob Faibussowitsch PetscCall(PetscFree(globalNumbersOfLocalOwnedVertices)); 18034baf1206SFlorian Wechsung 180441525646SFlorian Wechsung nparts = size; 180541525646SFlorian Wechsung wgtflag = 2; 180641525646SFlorian Wechsung numflag = 0; 180741525646SFlorian Wechsung ncon = 2; 180841525646SFlorian Wechsung real_t *tpwgts; 18099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * nparts, &tpwgts)); 181041525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 181141525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 181241525646SFlorian Wechsung } 181341525646SFlorian Wechsung 18149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon, &ubvec)); 181541525646SFlorian Wechsung ubvec[0] = 1.01; 18165a30b08bSFlorian Wechsung ubvec[1] = 1.01; 18178c9a1619SFlorian Wechsung lenadjncy = 0; 18188c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18198c9a1619SFlorian Wechsung PetscInt temp=0; 18209566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL)); 18218c9a1619SFlorian Wechsung lenadjncy += temp; 18229566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL)); 18238c9a1619SFlorian Wechsung } 18249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lenadjncy, &adjncy)); 18257407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 18269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lenxadj, &xadj)); 18270941debbSFlorian Wechsung xadj[0] = 0; 18288c9a1619SFlorian Wechsung counter = 0; 18298c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18302953a68cSFlorian Wechsung PetscInt temp=0; 18312953a68cSFlorian Wechsung const PetscInt *cols; 18329566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL)); 18339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&adjncy[counter], cols, temp)); 18348c9a1619SFlorian Wechsung counter += temp; 18350941debbSFlorian Wechsung xadj[i+1] = counter; 18369566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL)); 18378c9a1619SFlorian Wechsung } 18388c9a1619SFlorian Wechsung 18399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part)); 18409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt)); 184141525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 184241525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 184341525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 184441525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 184541525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 184641525646SFlorian Wechsung } 18478c9a1619SFlorian Wechsung 18485dc86ac1SFlorian Wechsung if (viewer) { 18499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth)); 18509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size])); 185112617df9SFlorian Wechsung } 185241525646SFlorian Wechsung if (parallel) { 18539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(4, &options)); 18545a30b08bSFlorian Wechsung options[0] = 1; 18555a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 18565a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18575a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 18589566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n")); 18598c9a1619SFlorian Wechsung if (useInitialGuess) { 18609566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n")); 18618c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 18625dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 18635f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18648c9a1619SFlorian Wechsung PetscStackPop; 18658c9a1619SFlorian Wechsung } else { 18668c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 18675dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 18688c9a1619SFlorian Wechsung PetscStackPop; 18695f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18708c9a1619SFlorian Wechsung } 18719566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 187241525646SFlorian Wechsung } else { 18739566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n")); 187441525646SFlorian Wechsung Mat As; 187541525646SFlorian Wechsung PetscInt numRows; 187641525646SFlorian Wechsung PetscInt *partGlobal; 18779566063dSJacob Faibussowitsch PetscCall(MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As)); 1878cb87ef4cSFlorian Wechsung 187941525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 18809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &numExclusivelyOwnedAll)); 188141525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 18829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm)); 1883cb87ef4cSFlorian Wechsung 18849566063dSJacob Faibussowitsch PetscCall(MatGetSize(As, &numRows, NULL)); 18859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &partGlobal)); 1886dd400576SPatrick Sanan if (rank == 0) { 188741525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 188841525646SFlorian Wechsung lenadjncy = 0; 188941525646SFlorian Wechsung 189041525646SFlorian Wechsung for (i=0; i<numRows; i++) { 189141525646SFlorian Wechsung PetscInt temp=0; 18929566063dSJacob Faibussowitsch PetscCall(MatGetRow(As, i, &temp, NULL, NULL)); 189341525646SFlorian Wechsung lenadjncy += temp; 18949566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(As, i, &temp, NULL, NULL)); 189541525646SFlorian Wechsung } 18969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lenadjncy, &adjncy_g)); 189741525646SFlorian Wechsung lenxadj = 1 + numRows; 18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lenxadj, &xadj_g)); 189941525646SFlorian Wechsung xadj_g[0] = 0; 190041525646SFlorian Wechsung counter = 0; 190141525646SFlorian Wechsung for (i=0; i<numRows; i++) { 19022953a68cSFlorian Wechsung PetscInt temp=0; 19032953a68cSFlorian Wechsung const PetscInt *cols; 19049566063dSJacob Faibussowitsch PetscCall(MatGetRow(As, i, &temp, &cols, NULL)); 19059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&adjncy_g[counter], cols, temp)); 190641525646SFlorian Wechsung counter += temp; 190741525646SFlorian Wechsung xadj_g[i+1] = counter; 19089566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(As, i, &temp, &cols, NULL)); 190941525646SFlorian Wechsung } 19109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2*numRows, &vtxwgt_g)); 191141525646SFlorian Wechsung for (i=0; i<size; i++) { 191241525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 191341525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 191441525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 191541525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 191641525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 191741525646SFlorian Wechsung } 191841525646SFlorian Wechsung } 19199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(64, &options)); 192041525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 19215f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 192241525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 192341525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 192406b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 192541525646SFlorian Wechsung PetscStackPop; 19265f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 19279566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 19289566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj_g)); 19299566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_g)); 19309566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt_g)); 193141525646SFlorian Wechsung } 19329566063dSJacob Faibussowitsch PetscCall(PetscFree(numExclusivelyOwnedAll)); 193341525646SFlorian Wechsung 19345dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 19355dc86ac1SFlorian Wechsung { 193681a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 19379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &counts)); 19389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size+1, &mpiCumSumVertices)); 19395dc86ac1SFlorian Wechsung for (i=0; i<size; i++) { 19409566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]))); 194141525646SFlorian Wechsung } 194281a13b52SFlorian Wechsung for (i=0; i<=size; i++) { 19439566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]))); 194481a13b52SFlorian Wechsung } 19459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm)); 19469566063dSJacob Faibussowitsch PetscCall(PetscFree(counts)); 19479566063dSJacob Faibussowitsch PetscCall(PetscFree(mpiCumSumVertices)); 19485dc86ac1SFlorian Wechsung } 19495dc86ac1SFlorian Wechsung 19509566063dSJacob Faibussowitsch PetscCall(PetscFree(partGlobal)); 19519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&As)); 195241525646SFlorian Wechsung } 1953cb87ef4cSFlorian Wechsung 19549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 19559566063dSJacob Faibussowitsch PetscCall(PetscFree(ubvec)); 19569566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts)); 1957cb87ef4cSFlorian Wechsung 1958cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1959cb87ef4cSFlorian Wechsung 19609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &firstVertices)); 19619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &renumbering)); 1962cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 19639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm)); 1964cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 1965cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 1966cb87ef4cSFlorian Wechsung } 1967cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 1968cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 1969cb87ef4cSFlorian Wechsung } 1970cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1971cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 19729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm)); 1973cb87ef4cSFlorian Wechsung 19749566063dSJacob Faibussowitsch PetscCall(PetscFree(firstVertices)); 19759566063dSJacob Faibussowitsch PetscCall(PetscFree(renumbering)); 19767f57c1a4SFlorian Wechsung 1977cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 19789566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 19799566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 19809566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 19819566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt)); 19829566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 19839566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 19849566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 19859566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 19869566063dSJacob Faibussowitsch PetscCall(PetscFree(part)); 19877f57c1a4SFlorian Wechsung if (viewer) { 19889566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 19899566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 19907f57c1a4SFlorian Wechsung } 19919566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 19928b879b41SFlorian Wechsung PetscFunctionReturn(0); 1993cb87ef4cSFlorian Wechsung } 1994cb87ef4cSFlorian Wechsung 19957407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 19965dc86ac1SFlorian Wechsung if (viewer) { 19979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth)); 19989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Initial. ")); 19999566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer)); 20009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Rebalanced. ")); 20019566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 20027407ba93SFlorian Wechsung } 20037407ba93SFlorian Wechsung 2004cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 200541525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 2006cb87ef4cSFlorian Wechsung PetscInt loc = 0; 20079566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc)); 20087407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 2009cb87ef4cSFlorian Wechsung if (loc<0) { 201041525646SFlorian Wechsung part[i] = rank; 2011cb87ef4cSFlorian Wechsung } 2012cb87ef4cSFlorian Wechsung } 2013cb87ef4cSFlorian Wechsung 20147407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 20155dc86ac1SFlorian Wechsung if (viewer) { 20169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "After. ")); 20179566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 20187407ba93SFlorian Wechsung } 20197407ba93SFlorian Wechsung 20209566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 20219566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 20229566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 20239566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt)); 2024cb87ef4cSFlorian Wechsung 20257f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 2026cf818975SFlorian Wechsung { 20277f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 20289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite)); 20297f57c1a4SFlorian Wechsung counter = 0; 2030cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2031cb87ef4cSFlorian Wechsung if (toBalance[i]) { 2032cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 20337f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 2034cb87ef4cSFlorian Wechsung counter++; 2035cb87ef4cSFlorian Wechsung } 2036cb87ef4cSFlorian Wechsung } 2037cb87ef4cSFlorian Wechsung } 20389566063dSJacob Faibussowitsch PetscCall(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees)); 20399566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsToRewrite)); 2040cf818975SFlorian Wechsung } 2041cb87ef4cSFlorian Wechsung 20429566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 20439566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 20449566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 20459566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 20469566063dSJacob Faibussowitsch PetscCall(PetscFree(part)); 20475dc86ac1SFlorian Wechsung if (viewer) { 20489566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 20499566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 20507d197802SFlorian Wechsung } 20518b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 20529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 2053b458e8f1SJose E. Roman PetscFunctionReturn(0); 2054240408d3SFlorian Wechsung #else 20555f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 205641525646SFlorian Wechsung #endif 2057cb87ef4cSFlorian Wechsung } 2058