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 7d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlex_GlobalID(PetscInt point) 8d71ae5a4SJacob Faibussowitsch { 99371c9d4SSatish Balay return point >= 0 ? point : -(point + 1); 109371c9d4SSatish Balay } 110134a67bSLisandro Dalcin 12d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 13d71ae5a4SJacob Faibussowitsch { 145a107427SMatthew G. Knepley DM ovdm; 155a107427SMatthew G. Knepley PetscSF sfPoint; 165a107427SMatthew G. Knepley IS cellNumbering; 175a107427SMatthew G. Knepley const PetscInt *cellNum; 185a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL; 195a107427SMatthew G. Knepley PetscBool useCone, useClosure; 205a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v; 215a107427SMatthew G. Knepley PetscMPIInt rank, size; 225a107427SMatthew G. Knepley 235a107427SMatthew G. Knepley PetscFunctionBegin; 249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 269566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 285a107427SMatthew G. Knepley if (dim != depth) { 295a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 315a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 329566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 335a107427SMatthew G. Knepley /* Different behavior for empty graphs */ 345a107427SMatthew G. Knepley if (!*numVertices) { 359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 365a107427SMatthew G. Knepley (*offsets)[0] = 0; 375a107427SMatthew G. Knepley } 385a107427SMatthew G. Knepley /* Broken in parallel */ 395f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 415a107427SMatthew G. Knepley } 425a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */ 439566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 449566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 455a107427SMatthew G. Knepley /* Need overlap >= 1 */ 469566063dSJacob Faibussowitsch PetscCall(DMPlexGetOverlap(dm, &overlap)); 475a107427SMatthew G. Knepley if (size && overlap < 1) { 489566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(dm, 1, NULL, &ovdm)); 495a107427SMatthew G. Knepley } else { 509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 515a107427SMatthew G. Knepley ovdm = dm; 525a107427SMatthew G. Knepley } 539566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(ovdm, &sfPoint)); 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd)); 559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering)); 565a107427SMatthew G. Knepley if (globalNumbering) { 579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 585a107427SMatthew G. Knepley *globalNumbering = cellNumbering; 595a107427SMatthew G. Knepley } 609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 615a107427SMatthew G. Knepley /* Determine sizes */ 625a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) { 635a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 64b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 655a107427SMatthew G. Knepley (*numVertices)++; 665a107427SMatthew G. Knepley } 679566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(*numVertices + 1, &vOffsets)); 685a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 695a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0; 705a107427SMatthew G. Knepley 71b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 729566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 735a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 745a107427SMatthew G. Knepley const PetscInt point = adj[a]; 755a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize; 765a107427SMatthew G. Knepley } 775a107427SMatthew G. Knepley vOffsets[v + 1] = vOffsets[v] + vsize; 785a107427SMatthew G. Knepley ++v; 795a107427SMatthew G. Knepley } 805a107427SMatthew G. Knepley /* Determine adjacency */ 819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vOffsets[*numVertices], &vAdj)); 825a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 835a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v]; 845a107427SMatthew G. Knepley 855a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 86b68380d8SVaclav Hapla if (cellNum[c - cStart] < 0) continue; 879566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 885a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 895a107427SMatthew G. Knepley const PetscInt point = adj[a]; 90ad540459SPierre Jolivet if (point != c && cStart <= point && point < cEnd) vAdj[off++] = DMPlex_GlobalID(cellNum[point - cStart]); 915a107427SMatthew G. Knepley } 9263a3b9bcSJacob Faibussowitsch PetscCheck(off == vOffsets[v + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %" PetscInt_FMT " should be %" PetscInt_FMT, off, vOffsets[v + 1]); 935a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */ 949566063dSJacob Faibussowitsch PetscCall(PetscSortInt(off - vOffsets[v], &vAdj[vOffsets[v]])); 955a107427SMatthew G. Knepley ++v; 965a107427SMatthew G. Knepley } 979566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 1009566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 1019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&ovdm)); 1029371c9d4SSatish Balay if (offsets) { 1039371c9d4SSatish Balay *offsets = vOffsets; 1049371c9d4SSatish Balay } else PetscCall(PetscFree(vOffsets)); 1059371c9d4SSatish Balay if (adjacency) { 1069371c9d4SSatish Balay *adjacency = vAdj; 1079371c9d4SSatish Balay } else PetscCall(PetscFree(vAdj)); 1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1095a107427SMatthew G. Knepley } 1105a107427SMatthew G. Knepley 111d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 112d71ae5a4SJacob Faibussowitsch { 113ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 114389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 1158cfe4c1fSMichael Lange IS cellNumbering; 1168cfe4c1fSMichael Lange const PetscInt *cellNum; 117532c4e7dSMichael Lange PetscBool useCone, useClosure; 118532c4e7dSMichael Lange PetscSection section; 119532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 1208cfe4c1fSMichael Lange PetscSF sfPoint; 1218f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 1228f4e72b9SMatthew G. Knepley const PetscInt *local; 1238f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 124532c4e7dSMichael Lange PetscMPIInt rank; 125532c4e7dSMichael Lange 126532c4e7dSMichael Lange PetscFunctionBegin; 1279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 130ffbd6163SMatthew G. Knepley if (dim != depth) { 131ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 1329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 133ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 1349566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 135ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 136ffbd6163SMatthew G. Knepley if (!*numVertices) { 1379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 138ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 139ffbd6163SMatthew G. Knepley } 140ffbd6163SMatthew G. Knepley /* Broken in parallel */ 1415f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 1423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143ffbd6163SMatthew G. Knepley } 1449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1459566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &pStart, &pEnd)); 146532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 1479566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 1489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 1499566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 150532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 1519566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 1529566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 1539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering)); 1543fa7752dSToby Isaac if (globalNumbering) { 1559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 1563fa7752dSToby Isaac *globalNumbering = cellNumbering; 1573fa7752dSToby Isaac } 1589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 1598f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 1608f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 1618f4e72b9SMatthew G. Knepley */ 1629566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL)); 1638f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1648f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1658f4e72b9SMatthew G. Knepley 1669566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nroots, &adjCells, nroots, &remoteCells)); 1679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd)); 1688f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1698f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1708f4e72b9SMatthew G. Knepley const PetscInt *support; 1718f4e72b9SMatthew G. Knepley PetscInt supportSize; 1728f4e72b9SMatthew G. Knepley 1739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 1749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 175b68380d8SVaclav Hapla if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1768f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 1779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p)); 178b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1] - pStart]); 1799566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 180b68380d8SVaclav Hapla if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1810134a67bSLisandro Dalcin } 1820134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1830134a67bSLisandro Dalcin if (supportSize > 2) { 1840134a67bSLisandro Dalcin PetscInt numChildren, i; 1850134a67bSLisandro Dalcin const PetscInt *children; 1860134a67bSLisandro Dalcin 1879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, &children)); 1880134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1890134a67bSLisandro Dalcin const PetscInt child = children[i]; 1900134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, child, &support)); 1929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, child, &supportSize)); 193b68380d8SVaclav Hapla if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1940134a67bSLisandro Dalcin else if (supportSize == 2) { 1959566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[0], nleaves, local, &p)); 196b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1] - pStart]); 1979566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[1], nleaves, local, &p)); 198b68380d8SVaclav Hapla if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0] - pStart]); 1990134a67bSLisandro Dalcin } 2000134a67bSLisandro Dalcin } 2010134a67bSLisandro Dalcin } 2028f4e72b9SMatthew G. Knepley } 2038f4e72b9SMatthew G. Knepley } 2048f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 2059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE)); 2069566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_REPLACE)); 2079566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 2089566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 2098f4e72b9SMatthew G. Knepley } 2108f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 2118cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 2128cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 2139371c9d4SSatish Balay if (nroots > 0) { 2149371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue; 2159371c9d4SSatish Balay } 2168f4e72b9SMatthew G. Knepley /* Add remote cells */ 2178f4e72b9SMatthew G. Knepley if (remoteCells) { 218b68380d8SVaclav Hapla const PetscInt gp = DMPlex_GlobalID(cellNum[p - pStart]); 2190134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 2200134a67bSLisandro Dalcin const PetscInt *cone, *children; 2210134a67bSLisandro Dalcin 2229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 2248f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 2250134a67bSLisandro Dalcin const PetscInt point = cone[c]; 2260134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 2278f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 2289566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2299566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2300134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 2310134a67bSLisandro Dalcin } 2320134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 2339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 2340134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 2350134a67bSLisandro Dalcin const PetscInt child = children[i]; 2360134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 2370134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 2389566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2399566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2400134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 2410134a67bSLisandro Dalcin } 2428f4e72b9SMatthew G. Knepley } 2438f4e72b9SMatthew G. Knepley } 2448f4e72b9SMatthew G. Knepley } 2458f4e72b9SMatthew G. Knepley /* Add local cells */ 246532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 2479566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 248532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 249532c4e7dSMichael Lange const PetscInt point = adj[a]; 250532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 251532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 2529566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 2539566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 254b68380d8SVaclav Hapla *pBuf = DMPlex_GlobalID(cellNum[point - pStart]); 255532c4e7dSMichael Lange } 256532c4e7dSMichael Lange } 2578cfe4c1fSMichael Lange (*numVertices)++; 258532c4e7dSMichael Lange } 2599566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2609566063dSJacob Faibussowitsch PetscCall(PetscFree2(adjCells, remoteCells)); 2619566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2624e468a93SLisandro Dalcin 263532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 2649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets)); 26743f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 2689371c9d4SSatish Balay if (nroots > 0) { 2699371c9d4SSatish Balay if (cellNum[p - pStart] < 0) continue; 2709371c9d4SSatish Balay } 271*f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &vOffsets[idx++])); 27243f7d02bSMichael Lange } 273532c4e7dSMichael Lange vOffsets[*numVertices] = size; 2749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2754e468a93SLisandro Dalcin 2764e468a93SLisandro Dalcin if (nroots >= 0) { 2774e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 2789566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(section)); 2799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, 0, *numVertices)); 2804e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2814e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1]; 2824e468a93SLisandro Dalcin PetscInt numEdges = end - start, *PETSC_RESTRICT edges; 2839566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&numEdges, &graph[start])); 2849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numEdges)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, numEdges, &edges)); 2869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(edges, &graph[start], numEdges)); 2874e468a93SLisandro Dalcin } 2889566063dSJacob Faibussowitsch PetscCall(PetscFree(vOffsets)); 2899566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 2904e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 2929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 2939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numVertices + 1, &vOffsets)); 294*f4f49eeaSPierre Jolivet for (idx = 0, p = 0; p < *numVertices; p++) PetscCall(PetscSectionGetOffset(section, p, &vOffsets[idx++])); 2954e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2969566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2974e468a93SLisandro Dalcin } else { 2984e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2994e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 3004e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p + 1]; 3019566063dSJacob Faibussowitsch PetscCall(PetscSortInt(end - start, &graph[start])); 3024e468a93SLisandro Dalcin } 3034e468a93SLisandro Dalcin } 3044e468a93SLisandro Dalcin 3054e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 306389e55d8SMichael Lange if (adjacency) *adjacency = graph; 3074e468a93SLisandro Dalcin 308532c4e7dSMichael Lange /* Cleanup */ 3099566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 3109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 3119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellNumbering, &cellNum)); 3129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellNumbering)); 3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 314532c4e7dSMichael Lange } 315532c4e7dSMichael Lange 316d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 317d71ae5a4SJacob Faibussowitsch { 318bbbc8e51SStefano Zampini Mat conn, CSR; 319bbbc8e51SStefano Zampini IS fis, cis, cis_own; 320bbbc8e51SStefano Zampini PetscSF sfPoint; 321bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 322bbbc8e51SStefano Zampini PetscInt *idxs, *idxs2; 32383c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 324bbbc8e51SStefano Zampini PetscMPIInt rank; 325bbbc8e51SStefano Zampini PetscBool flg; 326bbbc8e51SStefano Zampini 327bbbc8e51SStefano Zampini PetscFunctionBegin; 3289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3299566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 331bbbc8e51SStefano Zampini if (dim != depth) { 332bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 3339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 334bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 3359566063dSJacob Faibussowitsch if (globalNumbering) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 336bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 337bbbc8e51SStefano Zampini if (!*numVertices) { 3389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, offsets)); 339bbbc8e51SStefano Zampini (*offsets)[0] = 0; 340bbbc8e51SStefano Zampini } 341bbbc8e51SStefano Zampini /* Broken in parallel */ 3425f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 344bbbc8e51SStefano Zampini } 345bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 346bbbc8e51SStefano Zampini 347bbbc8e51SStefano Zampini /* numbering */ 3489566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 3499566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 3509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, height + 1, &fStart, &fEnd)); 3519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis)); 3529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis)); 3531baa6e33SBarry Smith if (globalNumbering) PetscCall(ISDuplicate(cis, globalNumbering)); 354bbbc8e51SStefano Zampini 355bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 3569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fis, &m)); 3579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 3589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 359bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 360bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 361bbbc8e51SStefano Zampini 362bbbc8e51SStefano Zampini if (p < 0) { 363bbbc8e51SStefano Zampini idxs[i] = -(p + 1); 364bbbc8e51SStefano Zampini } else { 365bbbc8e51SStefano Zampini idxs[i] = p; 366bbbc8e51SStefano Zampini floc += 1; 367bbbc8e51SStefano Zampini } 368bbbc8e51SStefano Zampini } 3699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 3709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 3719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis)); 372bbbc8e51SStefano Zampini 3739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cis, &m)); 3749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs)); 3769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idxs2)); 377bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 378bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 379bbbc8e51SStefano Zampini 380bbbc8e51SStefano Zampini if (p < 0) { 381bbbc8e51SStefano Zampini idxs[i] = -(p + 1); 382bbbc8e51SStefano Zampini } else { 383bbbc8e51SStefano Zampini idxs[i] = p; 384bbbc8e51SStefano Zampini idxs2[cloc++] = p; 385bbbc8e51SStefano Zampini } 386bbbc8e51SStefano Zampini } 3879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 3889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 3899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis)); 3909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own)); 391bbbc8e51SStefano Zampini 392bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 3939566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), &conn)); 3949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(conn, floc, cloc, M, N)); 3959566063dSJacob Faibussowitsch PetscCall(MatSetType(conn, MATMPIAIJ)); 3969566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, NULL, &lm)); 397712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 3989566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL)); 399bbbc8e51SStefano Zampini 400bbbc8e51SStefano Zampini /* Assemble matrix */ 4019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fis, &rows)); 4029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis, &cols)); 403bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 404bbbc8e51SStefano Zampini const PetscInt *cone; 405bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 406bbbc8e51SStefano Zampini 407bbbc8e51SStefano Zampini col = cols[c - cStart]; 4089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 4099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 410bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 411bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 412bbbc8e51SStefano Zampini const PetscInt *children; 413bbbc8e51SStefano Zampini PetscInt numChildren, ch; 414bbbc8e51SStefano Zampini 415bbbc8e51SStefano Zampini row = rows[cone[f] - fStart]; 4169566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 417bbbc8e51SStefano Zampini 418bbbc8e51SStefano Zampini /* non-conforming meshes */ 4199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children)); 420bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 421bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 422bbbc8e51SStefano Zampini 423bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 424bbbc8e51SStefano Zampini row = rows[child - fStart]; 4259566063dSJacob Faibussowitsch PetscCall(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 426bbbc8e51SStefano Zampini } 427bbbc8e51SStefano Zampini } 428bbbc8e51SStefano Zampini } 4299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fis, &rows)); 4309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis, &cols)); 4319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis)); 4339566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY)); 4349566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY)); 435bbbc8e51SStefano Zampini 436bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 4379566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR)); 4389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 439bbbc8e51SStefano Zampini 440bbbc8e51SStefano Zampini /* extract local part of the CSR */ 4419566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn)); 4429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CSR)); 4439566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4445f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 445bbbc8e51SStefano Zampini 446bbbc8e51SStefano Zampini /* get back requested output */ 447bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 448bbbc8e51SStefano Zampini if (offsets) { 4499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m + 1, &idxs)); 450bbbc8e51SStefano Zampini for (i = 1; i < m + 1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 451bbbc8e51SStefano Zampini *offsets = idxs; 452bbbc8e51SStefano Zampini } 453bbbc8e51SStefano Zampini if (adjacency) { 4549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ii[m] - m, &idxs)); 4559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cis_own, &rows)); 456bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 457bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 458bbbc8e51SStefano Zampini 459bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 460bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 461bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 462bbbc8e51SStefano Zampini } 463bbbc8e51SStefano Zampini } 46463a3b9bcSJacob Faibussowitsch PetscCheck(c == ii[m] - m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, c, ii[m] - m); 4659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cis_own, &rows)); 466bbbc8e51SStefano Zampini *adjacency = idxs; 467bbbc8e51SStefano Zampini } 468bbbc8e51SStefano Zampini 469bbbc8e51SStefano Zampini /* cleanup */ 4709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis_own)); 4719566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 4725f80ce2aSJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 4739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 4743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 475bbbc8e51SStefano Zampini } 476bbbc8e51SStefano Zampini 477bbbc8e51SStefano Zampini /*@C 478bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 479bbbc8e51SStefano Zampini 48020f4b53cSBarry Smith Collective 481a1cb98faSBarry Smith 482bbbc8e51SStefano Zampini Input Parameters: 483a1cb98faSBarry Smith + dm - The mesh `DM` 484bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 485bbbc8e51SStefano Zampini 486d8d19677SJose E. Roman Output Parameters: 487bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 488bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 489bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 490bbbc8e51SStefano Zampini - globalNumbering - A map from the local cell numbering to the global numbering used in "adjacency". Negative indicates that the cell is a duplicate from another process. 491bbbc8e51SStefano Zampini 49220f4b53cSBarry Smith Options Database Key: 4935a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4945a107427SMatthew G. Knepley 495bbbc8e51SStefano Zampini Level: developer 496bbbc8e51SStefano Zampini 497a1cb98faSBarry Smith Note: 498a1cb98faSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 499a1cb98faSBarry Smith representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 500a1cb98faSBarry Smith 5011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitionerGetType()`, `PetscPartitionerCreate()`, `DMSetAdjacency()` 502bbbc8e51SStefano Zampini @*/ 503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 504d71ae5a4SJacob Faibussowitsch { 5055a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH; 506bbbc8e51SStefano Zampini 507bbbc8e51SStefano Zampini PetscFunctionBegin; 5089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *)&alg, NULL)); 5095a107427SMatthew G. Knepley switch (alg) { 510d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_MAT: 511d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering)); 512d71ae5a4SJacob Faibussowitsch break; 513d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_GRAPH: 514d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering)); 515d71ae5a4SJacob Faibussowitsch break; 516d71ae5a4SJacob Faibussowitsch case DM_PLEX_CSR_OVERLAP: 517d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering)); 518d71ae5a4SJacob Faibussowitsch break; 519bbbc8e51SStefano Zampini } 5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 521bbbc8e51SStefano Zampini } 522bbbc8e51SStefano Zampini 523d5577e40SMatthew G. Knepley /*@C 524d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 525d5577e40SMatthew G. Knepley 52620f4b53cSBarry Smith Collective 527d5577e40SMatthew G. Knepley 5284165533cSJose E. Roman Input Parameters: 529a1cb98faSBarry Smith + dm - The `DMPLEX` 530d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 531d5577e40SMatthew G. Knepley 5324165533cSJose E. Roman Output Parameters: 533d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 534d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 535d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 536d5577e40SMatthew G. Knepley 537d5577e40SMatthew G. Knepley Level: advanced 538d5577e40SMatthew G. Knepley 539a1cb98faSBarry Smith Note: 540a1cb98faSBarry Smith This is suitable for input to a mesh partitioner like ParMetis. 541a1cb98faSBarry Smith 5421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()` 543d5577e40SMatthew G. Knepley @*/ 544d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 545d71ae5a4SJacob Faibussowitsch { 54670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 54770034214SMatthew G. Knepley PetscInt numFaceCases = 0; 54870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 54970034214SMatthew G. Knepley PetscInt *off, *adj; 55070034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 55170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 55270034214SMatthew G. Knepley 55370034214SMatthew G. Knepley PetscFunctionBegin; 55470034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 5559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 55670034214SMatthew G. Knepley cellDim = dim - cellHeight; 5579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 55970034214SMatthew G. Knepley if (cEnd - cStart == 0) { 56070034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 56170034214SMatthew G. Knepley if (offsets) *offsets = NULL; 56270034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 5633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56470034214SMatthew G. Knepley } 56570034214SMatthew G. Knepley numCells = cEnd - cStart; 56670034214SMatthew G. Knepley faceDepth = depth - cellHeight; 56770034214SMatthew G. Knepley if (dim == depth) { 56870034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 56970034214SMatthew G. Knepley 5709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off)); 57170034214SMatthew G. Knepley /* Count neighboring cells */ 5729566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight + 1, &fStart, &fEnd)); 57370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 57470034214SMatthew G. Knepley const PetscInt *support; 57570034214SMatthew G. Knepley PetscInt supportSize; 5769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 5779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 57870034214SMatthew G. Knepley if (supportSize == 2) { 5799ffc88e4SToby Isaac PetscInt numChildren; 5809ffc88e4SToby Isaac 5819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL)); 5829ffc88e4SToby Isaac if (!numChildren) { 58370034214SMatthew G. Knepley ++off[support[0] - cStart + 1]; 58470034214SMatthew G. Knepley ++off[support[1] - cStart + 1]; 58570034214SMatthew G. Knepley } 58670034214SMatthew G. Knepley } 5879ffc88e4SToby Isaac } 58870034214SMatthew G. Knepley /* Prefix sum */ 58970034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c - 1]; 59070034214SMatthew G. Knepley if (adjacency) { 59170034214SMatthew G. Knepley PetscInt *tmp; 59270034214SMatthew G. Knepley 5939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 5949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells + 1, &tmp)); 5959566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(tmp, off, numCells + 1)); 59670034214SMatthew G. Knepley /* Get neighboring cells */ 59770034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 59870034214SMatthew G. Knepley const PetscInt *support; 59970034214SMatthew G. Knepley PetscInt supportSize; 6009566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 6019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &support)); 60270034214SMatthew G. Knepley if (supportSize == 2) { 6039ffc88e4SToby Isaac PetscInt numChildren; 6049ffc88e4SToby Isaac 6059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, f, &numChildren, NULL)); 6069ffc88e4SToby Isaac if (!numChildren) { 60770034214SMatthew G. Knepley adj[tmp[support[0] - cStart]++] = support[1]; 60870034214SMatthew G. Knepley adj[tmp[support[1] - cStart]++] = support[0]; 60970034214SMatthew G. Knepley } 61070034214SMatthew G. Knepley } 6119ffc88e4SToby Isaac } 61263a3b9bcSJacob Faibussowitsch for (c = 0; c < cEnd - cStart; ++c) PetscAssert(tmp[c] == off[c + 1], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %" PetscInt_FMT " != %" PetscInt_FMT " for cell %" PetscInt_FMT, tmp[c], off[c], c + cStart); 6139566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 61470034214SMatthew G. Knepley } 61570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 61670034214SMatthew G. Knepley if (offsets) *offsets = off; 61770034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 6183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61970034214SMatthew G. Knepley } 62070034214SMatthew G. Knepley /* Setup face recognition */ 62170034214SMatthew G. Knepley if (faceDepth == 1) { 62270034214SMatthew G. Knepley PetscInt cornersSeen[30] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Could use PetscBT */ 62370034214SMatthew G. Knepley 62470034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 62570034214SMatthew G. Knepley PetscInt corners; 62670034214SMatthew G. Knepley 6279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &corners)); 62870034214SMatthew G. Knepley if (!cornersSeen[corners]) { 62970034214SMatthew G. Knepley PetscInt nFV; 63070034214SMatthew G. Knepley 6315f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 63270034214SMatthew G. Knepley cornersSeen[corners] = 1; 63370034214SMatthew G. Knepley 6349566063dSJacob Faibussowitsch PetscCall(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV)); 63570034214SMatthew G. Knepley 63670034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 63770034214SMatthew G. Knepley } 63870034214SMatthew G. Knepley } 63970034214SMatthew G. Knepley } 6409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells + 1, &off)); 64170034214SMatthew G. Knepley /* Count neighboring cells */ 64270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 64370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 64470034214SMatthew G. Knepley 6459566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 64670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 64770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 64870034214SMatthew G. Knepley PetscInt cellPair[2]; 64970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 65070034214SMatthew G. Knepley PetscInt meetSize = 0; 65170034214SMatthew G. Knepley const PetscInt *meet = NULL; 65270034214SMatthew G. Knepley 6539371c9d4SSatish Balay cellPair[0] = cell; 6549371c9d4SSatish Balay cellPair[1] = neighborCells[n]; 65570034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 65670034214SMatthew G. Knepley if (!found) { 6579566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 65870034214SMatthew G. Knepley if (meetSize) { 65970034214SMatthew G. Knepley PetscInt f; 66070034214SMatthew G. Knepley 66170034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 66270034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 66370034214SMatthew G. Knepley found = PETSC_TRUE; 66470034214SMatthew G. Knepley break; 66570034214SMatthew G. Knepley } 66670034214SMatthew G. Knepley } 66770034214SMatthew G. Knepley } 6689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 66970034214SMatthew G. Knepley } 67070034214SMatthew G. Knepley if (found) ++off[cell - cStart + 1]; 67170034214SMatthew G. Knepley } 67270034214SMatthew G. Knepley } 67370034214SMatthew G. Knepley /* Prefix sum */ 67470034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell - 1]; 67570034214SMatthew G. Knepley 67670034214SMatthew G. Knepley if (adjacency) { 6779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(off[numCells], &adj)); 67870034214SMatthew G. Knepley /* Get neighboring cells */ 67970034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 68070034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 68170034214SMatthew G. Knepley PetscInt cellOffset = 0; 68270034214SMatthew G. Knepley 6839566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 68470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 68570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 68670034214SMatthew G. Knepley PetscInt cellPair[2]; 68770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 68870034214SMatthew G. Knepley PetscInt meetSize = 0; 68970034214SMatthew G. Knepley const PetscInt *meet = NULL; 69070034214SMatthew G. Knepley 6919371c9d4SSatish Balay cellPair[0] = cell; 6929371c9d4SSatish Balay cellPair[1] = neighborCells[n]; 69370034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 69470034214SMatthew G. Knepley if (!found) { 6959566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 69670034214SMatthew G. Knepley if (meetSize) { 69770034214SMatthew G. Knepley PetscInt f; 69870034214SMatthew G. Knepley 69970034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 70070034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 70170034214SMatthew G. Knepley found = PETSC_TRUE; 70270034214SMatthew G. Knepley break; 70370034214SMatthew G. Knepley } 70470034214SMatthew G. Knepley } 70570034214SMatthew G. Knepley } 7069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 70770034214SMatthew G. Knepley } 70870034214SMatthew G. Knepley if (found) { 70970034214SMatthew G. Knepley adj[off[cell - cStart] + cellOffset] = neighborCells[n]; 71070034214SMatthew G. Knepley ++cellOffset; 71170034214SMatthew G. Knepley } 71270034214SMatthew G. Knepley } 71370034214SMatthew G. Knepley } 71470034214SMatthew G. Knepley } 7159566063dSJacob Faibussowitsch PetscCall(PetscFree(neighborCells)); 71670034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 71770034214SMatthew G. Knepley if (offsets) *offsets = off; 71870034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 7193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 72070034214SMatthew G. Knepley } 72170034214SMatthew G. Knepley 72277623264SMatthew G. Knepley /*@ 7233c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 72477623264SMatthew G. Knepley 72520f4b53cSBarry Smith Collective 72677623264SMatthew G. Knepley 72777623264SMatthew G. Knepley Input Parameters: 728a1cb98faSBarry Smith + part - The `PetscPartitioner` 72920f4b53cSBarry Smith . targetSection - The `PetscSection` describing the absolute weight of each partition (can be `NULL`) 730a1cb98faSBarry Smith - dm - The mesh `DM` 73177623264SMatthew G. Knepley 73277623264SMatthew G. Knepley Output Parameters: 733a1cb98faSBarry Smith + partSection - The `PetscSection` giving the division of points by partition 734f8987ae8SMichael Lange - partition - The list of points by partition 73577623264SMatthew G. Knepley 73677623264SMatthew G. Knepley Level: developer 73777623264SMatthew G. Knepley 738a1cb98faSBarry Smith Note: 739a1cb98faSBarry Smith If the `DM` has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 740a1cb98faSBarry Smith by the section in the transitive closure of the point. 741a1cb98faSBarry Smith 7421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`, `PetscSection`, `DMPlexDistribute()`, `PetscPartitionerCreate()`, `PetscSectionCreate()`, 743a1cb98faSBarry Smith `PetscSectionSetChart()`, `PetscPartitionerPartition()` 7444b15ede2SMatthew G. Knepley @*/ 745d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 746d71ae5a4SJacob Faibussowitsch { 74777623264SMatthew G. Knepley PetscMPIInt size; 7483c41b853SStefano Zampini PetscBool isplex; 7493c41b853SStefano Zampini PetscSection vertSection = NULL; 75077623264SMatthew G. Knepley 75177623264SMatthew G. Knepley PetscFunctionBegin; 75277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 75377623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7543c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 75577623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 7564f572ea9SToby Isaac PetscAssertPointer(partition, 5); 7579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isplex)); 7585f80ce2aSJacob Faibussowitsch PetscCheck(isplex, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not for type %s", ((PetscObject)dm)->type_name); 7599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)part), &size)); 76077623264SMatthew G. Knepley if (size == 1) { 76177623264SMatthew G. Knepley PetscInt *points; 76277623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 76377623264SMatthew G. Knepley 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 7659566063dSJacob Faibussowitsch PetscCall(PetscSectionReset(partSection)); 7669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(partSection, 0, size)); 7679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(partSection, 0, cEnd - cStart)); 7689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(partSection)); 7699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &points)); 77077623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 7719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), cEnd - cStart, points, PETSC_OWN_POINTER, partition)); 7723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77377623264SMatthew G. Knepley } 77477623264SMatthew G. Knepley if (part->height == 0) { 775074d466cSStefano Zampini PetscInt numVertices = 0; 77677623264SMatthew G. Knepley PetscInt *start = NULL; 77777623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7783fa7752dSToby Isaac IS globalNumbering; 77977623264SMatthew G. Knepley 780074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 7819566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering)); 78213911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 783074d466cSStefano Zampini const PetscInt *idxs; 784074d466cSStefano Zampini PetscInt p, pStart, pEnd; 785074d466cSStefano Zampini 7869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 7879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering)); 7889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &idxs)); 789074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 7909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &idxs)); 791074d466cSStefano Zampini } 7923c41b853SStefano Zampini if (part->usevwgt) { 7933c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7943c41b853SStefano Zampini IS clPoints = NULL; 7953c41b853SStefano Zampini const PetscInt *gid, *clIdx; 7963c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7970358368aSMatthew G. Knepley 7983c41b853SStefano Zampini /* dm->localSection encodes degrees of freedom per point, not per cell. We need to get the closure index to properly specify cell weights (aka dofs) */ 7993c41b853SStefano Zampini /* We do this only if the local section has been set */ 8003c41b853SStefano Zampini if (section) { 8019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL)); 80248a46eb9SPierre Jolivet if (!clSection) PetscCall(DMPlexCreateClosureIndex(dm, NULL)); 8039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints)); 8049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(clPoints, &clIdx)); 8053c41b853SStefano Zampini } 8069566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 8079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &vertSection)); 8089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(vertSection, 0, numVertices)); 8093c41b853SStefano Zampini if (globalNumbering) { 8109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &gid)); 8113c41b853SStefano Zampini } else gid = NULL; 8123c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 8133c41b853SStefano Zampini PetscInt dof = 1; 8140358368aSMatthew G. Knepley 8153c41b853SStefano Zampini /* skip cells in the overlap */ 8163c41b853SStefano Zampini if (gid && gid[p - pStart] < 0) continue; 8173c41b853SStefano Zampini 8183c41b853SStefano Zampini if (section) { 8193c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8203c41b853SStefano Zampini 8213c41b853SStefano Zampini dof = 0; 8229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(clSection, p, &clSize)); 8239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(clSection, p, &clOff)); 8243c41b853SStefano Zampini for (cl = 0; cl < clSize; cl += 2) { 8253c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8263c41b853SStefano Zampini 8279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, clPoint, &clDof)); 8283c41b853SStefano Zampini dof += clDof; 8290358368aSMatthew G. Knepley } 8300358368aSMatthew G. Knepley } 83163a3b9bcSJacob Faibussowitsch PetscCheck(dof, PETSC_COMM_SELF, PETSC_ERR_SUP, "Number of dofs for point %" PetscInt_FMT " in the local section should be positive", p); 8329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(vertSection, v, dof)); 8333c41b853SStefano Zampini v++; 8343c41b853SStefano Zampini } 83548a46eb9SPierre Jolivet if (globalNumbering) PetscCall(ISRestoreIndices(globalNumbering, &gid)); 83648a46eb9SPierre Jolivet if (clPoints) PetscCall(ISRestoreIndices(clPoints, &clIdx)); 8379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(vertSection)); 8383c41b853SStefano Zampini } 8399566063dSJacob Faibussowitsch PetscCall(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition)); 8409566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 8419566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 8423fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8433fa7752dSToby Isaac const PetscInt *globalNum; 8443fa7752dSToby Isaac const PetscInt *partIdx; 8453fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8463fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8473fa7752dSToby Isaac IS newPartition; 8483fa7752dSToby Isaac 8499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*partition, &localSize)); 8509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &adjusted)); 8519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalNumbering, &globalNum)); 8529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*partition, &partIdx)); 8539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(localSize, &map)); 8549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 8553fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8563fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8573fa7752dSToby Isaac } 858ad540459SPierre Jolivet for (i = 0; i < localSize; i++) adjusted[i] = map[partIdx[i]]; 8599566063dSJacob Faibussowitsch PetscCall(PetscFree(map)); 8609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*partition, &partIdx)); 8619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalNumbering, &globalNum)); 8629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, localSize, adjusted, PETSC_OWN_POINTER, &newPartition)); 8639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalNumbering)); 8649566063dSJacob Faibussowitsch PetscCall(ISDestroy(partition)); 8653fa7752dSToby Isaac *partition = newPartition; 8663fa7752dSToby Isaac } 86763a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %" PetscInt_FMT " for points to partition", part->height); 8689566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&vertSection)); 8693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 87077623264SMatthew G. Knepley } 87177623264SMatthew G. Knepley 8725680f57bSMatthew G. Knepley /*@ 8735680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8745680f57bSMatthew G. Knepley 87520f4b53cSBarry Smith Not Collective 8765680f57bSMatthew G. Knepley 8775680f57bSMatthew G. Knepley Input Parameter: 878a1cb98faSBarry Smith . dm - The `DM` 8795680f57bSMatthew G. Knepley 8805680f57bSMatthew G. Knepley Output Parameter: 881a1cb98faSBarry Smith . part - The `PetscPartitioner` 8825680f57bSMatthew G. Knepley 8835680f57bSMatthew G. Knepley Level: developer 8845680f57bSMatthew G. Knepley 885a1cb98faSBarry Smith Note: 886a1cb98faSBarry Smith This gets a borrowed reference, so the user should not destroy this `PetscPartitioner`. 88798599a47SLawrence Mitchell 8881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`, `PetscSection`, `DMPlexDistribute()`, `DMPlexSetPartitioner()`, `PetscPartitionerDMPlexPartition()`, `PetscPartitionerCreate()` 8895680f57bSMatthew G. Knepley @*/ 890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 891d71ae5a4SJacob Faibussowitsch { 8925680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 8935680f57bSMatthew G. Knepley 8945680f57bSMatthew G. Knepley PetscFunctionBegin; 8955680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8964f572ea9SToby Isaac PetscAssertPointer(part, 2); 8975680f57bSMatthew G. Knepley *part = mesh->partitioner; 8983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8995680f57bSMatthew G. Knepley } 9005680f57bSMatthew G. Knepley 90171bb2955SLawrence Mitchell /*@ 90271bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 90371bb2955SLawrence Mitchell 90420f4b53cSBarry Smith logically Collective 90571bb2955SLawrence Mitchell 90671bb2955SLawrence Mitchell Input Parameters: 907a1cb98faSBarry Smith + dm - The `DM` 90871bb2955SLawrence Mitchell - part - The partitioner 90971bb2955SLawrence Mitchell 91071bb2955SLawrence Mitchell Level: developer 91171bb2955SLawrence Mitchell 912a1cb98faSBarry Smith Note: 913a1cb98faSBarry Smith Any existing `PetscPartitioner` will be destroyed. 91471bb2955SLawrence Mitchell 9151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPartitioner`,`DMPlexDistribute()`, `DMPlexGetPartitioner()`, `PetscPartitionerCreate()` 91671bb2955SLawrence Mitchell @*/ 917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 918d71ae5a4SJacob Faibussowitsch { 91971bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 92071bb2955SLawrence Mitchell 92171bb2955SLawrence Mitchell PetscFunctionBegin; 92271bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92371bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 9249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)part)); 9259566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 92671bb2955SLawrence Mitchell mesh->partitioner = part; 9273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92871bb2955SLawrence Mitchell } 92971bb2955SLawrence Mitchell 930d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 931d71ae5a4SJacob Faibussowitsch { 9328e330a33SStefano Zampini const PetscInt *cone; 9338e330a33SStefano Zampini PetscInt coneSize, c; 9348e330a33SStefano Zampini PetscBool missing; 9358e330a33SStefano Zampini 9368e330a33SStefano Zampini PetscFunctionBeginHot; 9379566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, point, &missing)); 9388e330a33SStefano Zampini if (missing) { 9399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 94148a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosure_Private(dm, ht, cone[c])); 9428e330a33SStefano Zampini } 9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9448e330a33SStefano Zampini } 9458e330a33SStefano Zampini 946d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 947d71ae5a4SJacob Faibussowitsch { 948270bba0cSToby Isaac PetscFunctionBegin; 9496a5a2ffdSToby Isaac if (up) { 9506a5a2ffdSToby Isaac PetscInt parent; 9516a5a2ffdSToby Isaac 9529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 9536a5a2ffdSToby Isaac if (parent != point) { 9546a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9556a5a2ffdSToby Isaac 9569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 957270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 958270bba0cSToby Isaac PetscInt cpoint = closure[2 * i]; 959270bba0cSToby Isaac 9609566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9619566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_TRUE, PETSC_FALSE)); 962270bba0cSToby Isaac } 9639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure)); 9646a5a2ffdSToby Isaac } 9656a5a2ffdSToby Isaac } 9666a5a2ffdSToby Isaac if (down) { 9676a5a2ffdSToby Isaac PetscInt numChildren; 9686a5a2ffdSToby Isaac const PetscInt *children; 9696a5a2ffdSToby Isaac 9709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 9716a5a2ffdSToby Isaac if (numChildren) { 9726a5a2ffdSToby Isaac PetscInt i; 9736a5a2ffdSToby Isaac 9746a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9756a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9766a5a2ffdSToby Isaac 9779566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, cpoint)); 9789566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Tree(dm, ht, cpoint, PETSC_FALSE, PETSC_TRUE)); 9796a5a2ffdSToby Isaac } 9806a5a2ffdSToby Isaac } 9816a5a2ffdSToby Isaac } 9823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 983270bba0cSToby Isaac } 984270bba0cSToby Isaac 985d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 986d71ae5a4SJacob Faibussowitsch { 9878e330a33SStefano Zampini PetscInt parent; 988825f8a23SLisandro Dalcin 9898e330a33SStefano Zampini PetscFunctionBeginHot; 9909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL)); 9918e330a33SStefano Zampini if (point != parent) { 9928e330a33SStefano Zampini const PetscInt *cone; 9938e330a33SStefano Zampini PetscInt coneSize, c; 9948e330a33SStefano Zampini 9959566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, parent)); 9969566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosure_Private(dm, ht, parent)); 9979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, parent, &cone)); 9989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 9998e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 10008e330a33SStefano Zampini const PetscInt cp = cone[c]; 10018e330a33SStefano Zampini 10029566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, cp)); 10038e330a33SStefano Zampini } 10048e330a33SStefano Zampini } 10053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10068e330a33SStefano Zampini } 10078e330a33SStefano Zampini 1008d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 1009d71ae5a4SJacob Faibussowitsch { 10108e330a33SStefano Zampini PetscInt i, numChildren; 10118e330a33SStefano Zampini const PetscInt *children; 10128e330a33SStefano Zampini 10138e330a33SStefano Zampini PetscFunctionBeginHot; 10149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 101548a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(PetscHSetIAdd(ht, children[i])); 10163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10178e330a33SStefano Zampini } 10188e330a33SStefano Zampini 1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 1020d71ae5a4SJacob Faibussowitsch { 10218e330a33SStefano Zampini const PetscInt *cone; 10228e330a33SStefano Zampini PetscInt coneSize, c; 10238e330a33SStefano Zampini 10248e330a33SStefano Zampini PetscFunctionBeginHot; 10259566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 10269566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Up_Private(dm, ht, point)); 10279566063dSJacob Faibussowitsch PetscCall(DMPlexAddClosureTree_Down_Private(dm, ht, point)); 10289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 10299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 103048a46eb9SPierre Jolivet for (c = 0; c < coneSize; c++) PetscCall(DMPlexAddClosureTree_Private(dm, ht, cone[c])); 10313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10328e330a33SStefano Zampini } 10338e330a33SStefano Zampini 1034d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 1035d71ae5a4SJacob Faibussowitsch { 1036825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10378e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10388e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 103927104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1040825f8a23SLisandro Dalcin 1041825f8a23SLisandro Dalcin PetscFunctionBegin; 10429566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 10439566063dSJacob Faibussowitsch PetscCall(PetscHSetIResize(ht, numPoints * 16)); 10448e330a33SStefano Zampini if (!hasTree) { 104548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosure_Private(dm, ht, points[p])); 10468e330a33SStefano Zampini } else { 10478e330a33SStefano Zampini #if 1 104848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexAddClosureTree_Private(dm, ht, points[p])); 10498e330a33SStefano Zampini #else 10508e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1051825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 10529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 1053825f8a23SLisandro Dalcin for (c = 0; c < closureSize * 2; c += 2) { 10549566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closure[c])); 10559566063dSJacob Faibussowitsch if (hasTree) PetscCall(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE)); 1056825f8a23SLisandro Dalcin } 1057825f8a23SLisandro Dalcin } 10589566063dSJacob Faibussowitsch if (closure) PetscCall(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure)); 10598e330a33SStefano Zampini #endif 10608e330a33SStefano Zampini } 10619566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nelems)); 10629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nelems, &elems)); 10639566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &off, elems)); 10649566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 10659566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nelems, elems)); 10669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS)); 10673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1068825f8a23SLisandro Dalcin } 1069825f8a23SLisandro Dalcin 10705abbe4feSMichael Lange /*@ 10715abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10725abbe4feSMichael Lange 10735abbe4feSMichael Lange Input Parameters: 1074a1cb98faSBarry Smith + dm - The `DM` 1075a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots 10765abbe4feSMichael Lange 10775abbe4feSMichael Lange Level: developer 10785abbe4feSMichael Lange 10791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 10805abbe4feSMichael Lange @*/ 1081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 1082d71ae5a4SJacob Faibussowitsch { 1083825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 10845abbe4feSMichael Lange const PetscInt *ranks, *points; 1085825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 10869ffc88e4SToby Isaac 10879ffc88e4SToby Isaac PetscFunctionBegin; 10889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 10899566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 10909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 10915abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10925abbe4feSMichael Lange const PetscInt rank = ranks[r]; 10939566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 10949566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 10959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 10969566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS)); 10979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 10989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 10999566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, rank, closureIS)); 11009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&closureIS)); 11019ffc88e4SToby Isaac } 11029566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11059ffc88e4SToby Isaac } 11069ffc88e4SToby Isaac 110724d039d7SMichael Lange /*@ 110824d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 110924d039d7SMichael Lange 111024d039d7SMichael Lange Input Parameters: 1111a1cb98faSBarry Smith + dm - The `DM` 1112a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots 111324d039d7SMichael Lange 111424d039d7SMichael Lange Level: developer 111524d039d7SMichael Lange 11161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 111724d039d7SMichael Lange @*/ 1118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 1119d71ae5a4SJacob Faibussowitsch { 112024d039d7SMichael Lange IS rankIS, pointIS; 112124d039d7SMichael Lange const PetscInt *ranks, *points; 112224d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 112324d039d7SMichael Lange PetscInt *adj = NULL; 112470034214SMatthew G. Knepley 112570034214SMatthew G. Knepley PetscFunctionBegin; 11269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &rankIS)); 11279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 112924d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 113024d039d7SMichael Lange const PetscInt rank = ranks[r]; 113170034214SMatthew G. Knepley 11329566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &pointIS)); 11339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 11349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 113570034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 113624d039d7SMichael Lange adjSize = PETSC_DETERMINE; 11379566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj)); 11389566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(label, adj[a], rank)); 113970034214SMatthew G. Knepley } 11409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 11419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 114270034214SMatthew G. Knepley } 11439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11459566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 11463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 114770034214SMatthew G. Knepley } 114870034214SMatthew G. Knepley 1149be200f8dSMichael Lange /*@ 1150a1cb98faSBarry Smith DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point `PetscSF` 1151be200f8dSMichael Lange 1152be200f8dSMichael Lange Input Parameters: 1153a1cb98faSBarry Smith + dm - The `DM` 1154a1cb98faSBarry Smith - label - `DMLabel` assigning ranks to remote roots 1155be200f8dSMichael Lange 1156be200f8dSMichael Lange Level: developer 1157be200f8dSMichael Lange 1158a1cb98faSBarry Smith Note: 1159a1cb98faSBarry Smith This is required when generating multi-level overlaps to capture 1160be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1161be200f8dSMichael Lange 11621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1163be200f8dSMichael Lange @*/ 1164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1165d71ae5a4SJacob Faibussowitsch { 1166be200f8dSMichael Lange MPI_Comm comm; 1167be200f8dSMichael Lange PetscMPIInt rank; 1168be200f8dSMichael Lange PetscSF sfPoint; 11695d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1170be200f8dSMichael Lange IS rankIS, pointIS; 1171be200f8dSMichael Lange const PetscInt *ranks; 1172be200f8dSMichael Lange PetscInt numRanks, r; 1173be200f8dSMichael Lange 1174be200f8dSMichael Lange PetscFunctionBegin; 11759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11779566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 11785d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 11799566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 11809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &rankIS)); 11819566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 11835d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 11845d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 11855d04f6ebSMichael Lange if (remoteRank == rank) continue; 11869566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS)); 11879566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 11889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 11895d04f6ebSMichael Lange } 11909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 11919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 11929566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 1193be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 11949566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 11959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &rankIS)); 11969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rankIS, &numRanks)); 11979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rankIS, &ranks)); 1198be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1199be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1200be200f8dSMichael Lange if (remoteRank == rank) continue; 12019566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS)); 12029566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, remoteRank)); 12039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 1204be200f8dSMichael Lange } 12059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rankIS, &ranks)); 12069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rankIS)); 12079566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 12083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1209be200f8dSMichael Lange } 1210be200f8dSMichael Lange 12111fd9873aSMichael Lange /*@ 12121fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 12131fd9873aSMichael Lange 12141fd9873aSMichael Lange Input Parameters: 1215a1cb98faSBarry Smith + dm - The `DM` 1216a1cb98faSBarry Smith . rootLabel - `DMLabel` assigning ranks to local roots 1217fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 12181fd9873aSMichael Lange 12191fd9873aSMichael Lange Output Parameter: 1220a1cb98faSBarry Smith . leafLabel - `DMLabel` assigning ranks to remote roots 12211fd9873aSMichael Lange 12221fd9873aSMichael Lange Level: developer 12231fd9873aSMichael Lange 1224a1cb98faSBarry Smith Note: 1225a1cb98faSBarry Smith The rootLabel defines a send pattern by mapping local points to remote target ranks. The 1226a1cb98faSBarry Smith resulting leafLabel is a receiver mapping of remote roots to their parent rank. 1227a1cb98faSBarry Smith 12281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 12291fd9873aSMichael Lange @*/ 1230d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 1231d71ae5a4SJacob Faibussowitsch { 12321fd9873aSMichael Lange MPI_Comm comm; 1233874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1234874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12351fd9873aSMichael Lange PetscSF sfPoint; 1236874ddda9SLisandro Dalcin PetscSection rootSection; 12371fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12381fd9873aSMichael Lange const PetscSFNode *remote; 12391fd9873aSMichael Lange const PetscInt *local, *neighbors; 12401fd9873aSMichael Lange IS valueIS; 1241874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12421fd9873aSMichael Lange 12431fd9873aSMichael Lange PetscFunctionBegin; 12449566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelInvert, dm, 0, 0, 0)); 12459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 12489566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 12491fd9873aSMichael Lange 12501fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 12519566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 12529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, 0, size)); 12539566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(rootLabel, &valueIS)); 12549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numNeighbors)); 12559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &neighbors)); 12561fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12579566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints)); 12589566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(rootSection, neighbors[n], numPoints)); 12591fd9873aSMichael Lange } 12609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 12619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &rootSize)); 12629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rootSize, &rootPoints)); 12639566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 12641fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12651fd9873aSMichael Lange IS pointIS; 12661fd9873aSMichael Lange const PetscInt *points; 12671fd9873aSMichael Lange 12689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 12699566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS)); 12709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 12719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 12721fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 12739566063dSJacob Faibussowitsch if (local) PetscCall(PetscFindInt(points[p], nleaves, local, &l)); 1274ad540459SPierre Jolivet else l = -1; 12759371c9d4SSatish Balay if (l >= 0) { 12769371c9d4SSatish Balay rootPoints[off + p] = remote[l]; 12779371c9d4SSatish Balay } else { 12789371c9d4SSatish Balay rootPoints[off + p].index = points[p]; 12799371c9d4SSatish Balay rootPoints[off + p].rank = rank; 12809371c9d4SSatish Balay } 12811fd9873aSMichael Lange } 12829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 12839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 12841fd9873aSMichael Lange } 1285874ddda9SLisandro Dalcin 1286874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1287874ddda9SLisandro Dalcin if (!processSF) { 1288874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1289874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1290874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1291874ddda9SLisandro Dalcin 12929566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls)); 1293874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 12949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, neighbors[n], &dof)); 12959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1296874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 12979371c9d4SSatish Balay if (dof > PETSC_MPI_INT_MAX) { 12989371c9d4SSatish Balay locOverflow = PETSC_TRUE; 12999371c9d4SSatish Balay break; 13009371c9d4SSatish Balay } 13019371c9d4SSatish Balay if (off > PETSC_MPI_INT_MAX) { 13029371c9d4SSatish Balay locOverflow = PETSC_TRUE; 13039371c9d4SSatish Balay break; 13049371c9d4SSatish Balay } 1305874ddda9SLisandro Dalcin #endif 1306874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt)dof; 1307874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt)off; 1308874ddda9SLisandro Dalcin } 13099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm)); 13109371c9d4SSatish Balay for (r = 0; r < size; ++r) { 13119371c9d4SSatish Balay rdispls[r] = (int)counter; 13129371c9d4SSatish Balay counter += rcounts[r]; 13139371c9d4SSatish Balay } 1314874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 1315712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm)); 1316874ddda9SLisandro Dalcin if (!mpiOverflow) { 13179566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using Alltoallv for mesh distribution\n")); 1318874ddda9SLisandro Dalcin leafSize = (PetscInt)counter; 13199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafSize, &leafPoints)); 13209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm)); 1321874ddda9SLisandro Dalcin } 13229566063dSJacob Faibussowitsch PetscCall(PetscFree4(scounts, sdispls, rcounts, rdispls)); 1323874ddda9SLisandro Dalcin } 1324874ddda9SLisandro Dalcin 1325874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1326874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1327874ddda9SLisandro Dalcin PetscSF procSF; 1328874ddda9SLisandro Dalcin PetscSection leafSection; 1329874ddda9SLisandro Dalcin 1330874ddda9SLisandro Dalcin if (processSF) { 13319566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution\n")); 13329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)processSF)); 1333874ddda9SLisandro Dalcin procSF = processSF; 1334874ddda9SLisandro Dalcin } else { 13359566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Using processSF for mesh distribution (MPI overflow)\n")); 13369566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &procSF)); 13379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphWithPattern(procSF, NULL, PETSCSF_PATTERN_ALLTOALL)); 1338874ddda9SLisandro Dalcin } 1339874ddda9SLisandro Dalcin 13409566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection)); 13419566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void **)&leafPoints)); 13429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafSection, &leafSize)); 13439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 13449566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&procSF)); 1345874ddda9SLisandro Dalcin } 1346874ddda9SLisandro Dalcin 134748a46eb9SPierre Jolivet for (p = 0; p < leafSize; p++) PetscCall(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank)); 1348874ddda9SLisandro Dalcin 13499566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &neighbors)); 13509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 13529566063dSJacob Faibussowitsch PetscCall(PetscFree(rootPoints)); 13539566063dSJacob Faibussowitsch PetscCall(PetscFree(leafPoints)); 13549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelInvert, dm, 0, 0, 0)); 13553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13561fd9873aSMichael Lange } 13571fd9873aSMichael Lange 1358aa3148a8SMichael Lange /*@ 1359aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1360aa3148a8SMichael Lange 1361aa3148a8SMichael Lange Input Parameters: 1362a1cb98faSBarry Smith + dm - The `DM` 13633ac0285dSStefano Zampini . label - `DMLabel` assigning ranks to remote roots 13643ac0285dSStefano Zampini - sortRanks - Whether or not to sort the SF leaves by rank 1365aa3148a8SMichael Lange 1366aa3148a8SMichael Lange Output Parameter: 1367fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1368aa3148a8SMichael Lange 1369aa3148a8SMichael Lange Level: developer 1370aa3148a8SMichael Lange 1371a1cb98faSBarry Smith Note: 1372a1cb98faSBarry Smith The incoming label is a receiver mapping of remote points to their parent rank. 1373a1cb98faSBarry Smith 13741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `PetscSF`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1375aa3148a8SMichael Lange @*/ 13763ac0285dSStefano Zampini PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscBool sortRanks, PetscSF *sf) 1377d71ae5a4SJacob Faibussowitsch { 13786e203dd9SStefano Zampini PetscMPIInt rank; 13796e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1380aa3148a8SMichael Lange PetscSFNode *remotePoints; 13816e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13826e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 13833ac0285dSStefano Zampini PetscMPIInt myRank; 1384aa3148a8SMichael Lange 1385aa3148a8SMichael Lange PetscFunctionBegin; 13869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0)); 13879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 13889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &neighborsIS)); 13893ac0285dSStefano Zampini 13903ac0285dSStefano Zampini if (sortRanks) { 13916e203dd9SStefano Zampini IS is; 13923ac0285dSStefano Zampini 13939566063dSJacob Faibussowitsch PetscCall(ISDuplicate(neighborsIS, &is)); 13949566063dSJacob Faibussowitsch PetscCall(ISSort(is)); 13959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 13966e203dd9SStefano Zampini neighborsIS = is; 13976e203dd9SStefano Zampini } 13983ac0285dSStefano Zampini myRank = sortRanks ? -1 : rank; 13993ac0285dSStefano Zampini 14009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neighborsIS, &nNeighbors)); 14019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(neighborsIS, &neighbors)); 14026e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 14039566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, neighbors[n], &numPoints)); 1404aa3148a8SMichael Lange numRemote += numPoints; 1405aa3148a8SMichael Lange } 14069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRemote, &remotePoints)); 14073ac0285dSStefano Zampini 14083ac0285dSStefano Zampini /* Put owned points first if not sorting the ranks */ 14093ac0285dSStefano Zampini if (!sortRanks) { 14109566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, rank, &numPoints)); 141143f7d02bSMichael Lange if (numPoints > 0) { 14129566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, rank, &remoteRootIS)); 14139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 141443f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 141543f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 141643f7d02bSMichael Lange remotePoints[idx].rank = rank; 141743f7d02bSMichael Lange idx++; 141843f7d02bSMichael Lange } 14199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 142143f7d02bSMichael Lange } 14223ac0285dSStefano Zampini } 14233ac0285dSStefano Zampini 142443f7d02bSMichael Lange /* Now add remote points */ 14256e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 14266e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 14276e203dd9SStefano Zampini 14289566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, nn, &numPoints)); 14293ac0285dSStefano Zampini if (nn == myRank || numPoints <= 0) continue; 14309566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, nn, &remoteRootIS)); 14319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(remoteRootIS, &remoteRoots)); 1432aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1433aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 14346e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1435aa3148a8SMichael Lange idx++; 1436aa3148a8SMichael Lange } 14379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(remoteRootIS, &remoteRoots)); 14389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&remoteRootIS)); 1439aa3148a8SMichael Lange } 14403ac0285dSStefano Zampini 14419566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sf)); 14429566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14439566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, pEnd - pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 14449566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(*sf)); 14459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&neighborsIS)); 14469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartLabelCreateSF, dm, 0, 0, 0)); 14473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144870034214SMatthew G. Knepley } 1449cb87ef4cSFlorian Wechsung 1450abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1451abe9303eSLisandro Dalcin #include <parmetis.h> 1452abe9303eSLisandro Dalcin #endif 1453abe9303eSLisandro Dalcin 14546a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14556a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14566a3739e5SFlorian Wechsung * them out in that case. */ 14576a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1458a4e35b19SJacob Faibussowitsch /* 1459a1cb98faSBarry Smith DMPlexRewriteSF - Rewrites the ownership of the `PetsSF` of a `DM` (in place). 14607f57c1a4SFlorian Wechsung 14617f57c1a4SFlorian Wechsung Input parameters: 1462a1cb98faSBarry Smith + dm - The `DMPLEX` object. 1463fe2efc57SMark . n - The number of points. 1464a1cb98faSBarry Smith . pointsToRewrite - The points in the `PetscSF` whose ownership will change. 1465fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1466a1cb98faSBarry Smith - degrees - Degrees of the points in the `PetscSF` as obtained by `PetscSFComputeDegreeBegin()`/`PetscSFComputeDegreeEnd()`. 14677f57c1a4SFlorian Wechsung 14687f57c1a4SFlorian Wechsung Level: developer 14697f57c1a4SFlorian Wechsung 14701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `PetscSF`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1471a4e35b19SJacob Faibussowitsch */ 1472d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 1473d71ae5a4SJacob Faibussowitsch { 14745f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14757f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14767f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14777f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14787f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14797f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14807f57c1a4SFlorian Wechsung PetscSF sf; 14817f57c1a4SFlorian Wechsung MPI_Comm comm; 14825a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14837f57c1a4SFlorian Wechsung 14847f57c1a4SFlorian Wechsung PetscFunctionBegin; 14859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 14879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 14889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 14897f57c1a4SFlorian Wechsung 14909566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 14919566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 14929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf)); 1493ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) isLeaf[i] = PETSC_FALSE; 1494ad540459SPierre Jolivet for (i = 0; i < nleafs; i++) isLeaf[ilocal[i] - pStart] = PETSC_TRUE; 14957f57c1a4SFlorian Wechsung 14969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + 1, &cumSumDegrees)); 14977f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 1498ad540459SPierre Jolivet for (i = 1; i <= pEnd - pStart; i++) cumSumDegrees[i] = cumSumDegrees[i - 1] + degrees[i - 1]; 14997f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd - pStart]; 15007f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 15017f57c1a4SFlorian Wechsung 15029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &locationsOfLeafs)); 15039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &rankOnLeafs)); 1504ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) rankOnLeafs[i] = rank; 15059566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 15069566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 15079566063dSJacob Faibussowitsch PetscCall(PetscFree(rankOnLeafs)); 15087f57c1a4SFlorian Wechsung 15097f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 15109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs)); 15119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &points)); 1512ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) points[i] = pStart + i; 15139566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15149566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 15159566063dSJacob Faibussowitsch PetscCall(PetscFree(points)); 15167f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 15179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newOwners)); 15189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &newNumbers)); 15197f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 15207f57c1a4SFlorian Wechsung newOwners[i] = -1; 15217f57c1a4SFlorian Wechsung newNumbers[i] = -1; 15227f57c1a4SFlorian Wechsung } 15237f57c1a4SFlorian Wechsung { 15247f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 15257f57c1a4SFlorian Wechsung for (i = 0; i < n; i++) { 15267f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 15277f57c1a4SFlorian Wechsung newNumber = -1; 15287f57c1a4SFlorian Wechsung oldOwner = rank; 15297f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 15307f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 15317f57c1a4SFlorian Wechsung newNumber = oldNumber; 15327f57c1a4SFlorian Wechsung } else { 15337f57c1a4SFlorian Wechsung for (j = 0; j < degrees[oldNumber]; j++) { 15347f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber] + j] == newOwner) { 15357f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber] + j]; 15367f57c1a4SFlorian Wechsung break; 15377f57c1a4SFlorian Wechsung } 15387f57c1a4SFlorian Wechsung } 15397f57c1a4SFlorian Wechsung } 15405f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 15417f57c1a4SFlorian Wechsung 15427f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 15437f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 15447f57c1a4SFlorian Wechsung } 15457f57c1a4SFlorian Wechsung } 15469566063dSJacob Faibussowitsch PetscCall(PetscFree(cumSumDegrees)); 15479566063dSJacob Faibussowitsch PetscCall(PetscFree(locationsOfLeafs)); 15489566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteLocalPointOfLeafs)); 15497f57c1a4SFlorian Wechsung 15509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE)); 15519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners, MPI_REPLACE)); 15529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE)); 15539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers, MPI_REPLACE)); 15547f57c1a4SFlorian Wechsung 15557f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15567f57c1a4SFlorian Wechsung leafCounter = 0; 15577f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 15587f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 1559ad540459SPierre Jolivet if (newOwners[i] != rank) leafCounter++; 15607f57c1a4SFlorian Wechsung } else { 1561ad540459SPierre Jolivet if (isLeaf[i]) leafCounter++; 15627f57c1a4SFlorian Wechsung } 15637f57c1a4SFlorian Wechsung } 15647f57c1a4SFlorian Wechsung 15657f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 15669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafsNew)); 15679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(leafCounter, &leafLocationsNew)); 15687f57c1a4SFlorian Wechsung 15697f57c1a4SFlorian Wechsung leafCounter = 0; 15707f57c1a4SFlorian Wechsung counter = 0; 15717f57c1a4SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 15727f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15737f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15747f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15757f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15767f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15777f57c1a4SFlorian Wechsung leafCounter++; 15787f57c1a4SFlorian Wechsung } 15797f57c1a4SFlorian Wechsung } else { 15807f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15817f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15827f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15837f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 15847f57c1a4SFlorian Wechsung leafCounter++; 15857f57c1a4SFlorian Wechsung } 15867f57c1a4SFlorian Wechsung } 1587ad540459SPierre Jolivet if (isLeaf[i]) counter++; 15887f57c1a4SFlorian Wechsung } 15897f57c1a4SFlorian Wechsung 15909566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER)); 15919566063dSJacob Faibussowitsch PetscCall(PetscFree(newOwners)); 15929566063dSJacob Faibussowitsch PetscCall(PetscFree(newNumbers)); 15939566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 15943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15957f57c1a4SFlorian Wechsung } 15967f57c1a4SFlorian Wechsung 1597d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1598d71ae5a4SJacob Faibussowitsch { 15995f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum; 16005a30b08bSFlorian Wechsung PetscMPIInt rank, size; 16015f80ce2aSJacob Faibussowitsch 1602125d2a8fSFlorian Wechsung PetscFunctionBegin; 16039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 16049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &distribution)); 16065f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < n; i++) { 1607125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip * i]; 1608125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip * i]; 1609125d2a8fSFlorian Wechsung } 1610712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm)); 1611125d2a8fSFlorian Wechsung min = distribution[0]; 1612125d2a8fSFlorian Wechsung max = distribution[0]; 1613125d2a8fSFlorian Wechsung sum = distribution[0]; 16145f80ce2aSJacob Faibussowitsch for (PetscInt i = 1; i < size; i++) { 1615125d2a8fSFlorian Wechsung if (distribution[i] < min) min = distribution[i]; 1616125d2a8fSFlorian Wechsung if (distribution[i] > max) max = distribution[i]; 1617125d2a8fSFlorian Wechsung sum += distribution[i]; 1618125d2a8fSFlorian Wechsung } 161963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Min: %" PetscInt_FMT ", Avg: %" PetscInt_FMT ", Max: %" PetscInt_FMT ", Balance: %f\n", min, sum / size, max, (max * 1. * size) / sum)); 16209566063dSJacob Faibussowitsch PetscCall(PetscFree(distribution)); 16213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1622125d2a8fSFlorian Wechsung } 1623125d2a8fSFlorian Wechsung 16246a3739e5SFlorian Wechsung #endif 16256a3739e5SFlorian Wechsung 1626cb87ef4cSFlorian Wechsung /*@ 1627a1cb98faSBarry Smith DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the `PointSF` of the `DM` inplace. 1628cb87ef4cSFlorian Wechsung 162960225df5SJacob Faibussowitsch Input Parameters: 1630a1cb98faSBarry Smith + dm - The `DMPLEX` object. 1631fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1632fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1633fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1634cb87ef4cSFlorian Wechsung 163560225df5SJacob Faibussowitsch Output Parameter: 1636252a1336SBarry Smith . success - whether the graph partitioning was successful or not, optional. Unsuccessful simply means no change to the partitioning 1637252a1336SBarry Smith 1638a1cb98faSBarry Smith Options Database Keys: 1639252a1336SBarry Smith + -dm_plex_rebalance_shared_points_parmetis - Use ParMetis instead of Metis for the partitioner 1640252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_initial_guess - Use current partition to bootstrap ParMetis partition 1641252a1336SBarry Smith . -dm_plex_rebalance_shared_points_use_mat_partitioning - Use the MatPartitioning object to perform the partition, the prefix for those operations is -dm_plex_rebalance_shared_points_ 1642252a1336SBarry Smith - -dm_plex_rebalance_shared_points_monitor - Monitor the shared points rebalance process 1643252a1336SBarry Smith 164490ea27d8SSatish Balay Level: intermediate 1645a1cb98faSBarry Smith 16461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexDistribute()`, `DMPlexCreateOverlap()` 1647cb87ef4cSFlorian Wechsung @*/ 1648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1649d71ae5a4SJacob Faibussowitsch { 165041525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1651cb87ef4cSFlorian Wechsung PetscSF sf; 16520faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16537f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16547f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16557f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1656cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1657cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1658cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16597f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16605dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1661cb87ef4cSFlorian Wechsung PetscInt offset, counter; 1662252a1336SBarry Smith PetscInt *vtxwgt; 1663252a1336SBarry Smith const PetscInt *xadj, *adjncy; 1664cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1665cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1666cb87ef4cSFlorian Wechsung real_t *ubvec; 1667cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1668cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1669cb87ef4cSFlorian Wechsung MPI_Comm comm; 1670252a1336SBarry Smith Mat A; 16717d197802SFlorian Wechsung PetscViewer viewer; 16727d197802SFlorian Wechsung PetscViewerFormat format; 16735a30b08bSFlorian Wechsung PetscLayout layout; 1674252a1336SBarry Smith real_t *tpwgts; 1675252a1336SBarry Smith PetscMPIInt *counts, *mpiCumSumVertices; 1676252a1336SBarry Smith PetscInt *pointsToRewrite; 1677252a1336SBarry Smith PetscInt numRows; 1678252a1336SBarry Smith PetscBool done, usematpartitioning = PETSC_FALSE; 1679252a1336SBarry Smith IS ispart = NULL; 1680252a1336SBarry Smith MatPartitioning mp; 1681252a1336SBarry Smith const char *prefix; 168212617df9SFlorian Wechsung 168312617df9SFlorian Wechsung PetscFunctionBegin; 16849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 1686252a1336SBarry Smith if (size == 1) { 1687252a1336SBarry Smith if (success) *success = PETSC_TRUE; 16883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1689252a1336SBarry Smith } 1690252a1336SBarry Smith if (success) *success = PETSC_FALSE; 1691252a1336SBarry Smith PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1692252a1336SBarry Smith 1693252a1336SBarry Smith parallel = PETSC_FALSE; 1694252a1336SBarry Smith useInitialGuess = PETSC_FALSE; 1695252a1336SBarry Smith PetscObjectOptionsBegin((PetscObject)dm); 1696252a1336SBarry Smith PetscCall(PetscOptionsName("-dm_plex_rebalance_shared_points_parmetis", "Use ParMetis instead of Metis for the partitioner", "DMPlexRebalanceSharedPoints", ¶llel)); 1697252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_initial_guess", "Use current partition to bootstrap ParMetis partition", "DMPlexRebalanceSharedPoints", useInitialGuess, &useInitialGuess, NULL)); 1698252a1336SBarry Smith PetscCall(PetscOptionsBool("-dm_plex_rebalance_shared_points_use_mat_partitioning", "Use the MatPartitioning object to partition", "DMPlexRebalanceSharedPoints", usematpartitioning, &usematpartitioning, NULL)); 1699252a1336SBarry Smith PetscCall(PetscOptionsViewer("-dm_plex_rebalance_shared_points_monitor", "Monitor the shared points rebalance process", "DMPlexRebalanceSharedPoints", &viewer, &format, NULL)); 1700252a1336SBarry Smith PetscOptionsEnd(); 1701252a1336SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format)); 17027f57c1a4SFlorian Wechsung 17039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 170441525646SFlorian Wechsung 1705252a1336SBarry Smith PetscCall(DMGetOptionsPrefix(dm, &prefix)); 17069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)dm)->options, prefix, "-dm_rebalance_partition_view", &viewer, &format, NULL)); 17071baa6e33SBarry Smith if (viewer) PetscCall(PetscViewerPushFormat(viewer, format)); 17087d197802SFlorian Wechsung 1709ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 17109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd)); 17119566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 17129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &toBalance)); 1713ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) toBalance[i] = (PetscBool)(i >= eBegin && i < eEnd); 1714cb87ef4cSFlorian Wechsung 1715cf818975SFlorian Wechsung /* There are three types of points: 1716cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1717cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1718cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1719cf818975SFlorian Wechsung */ 17209566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 17219566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 17229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isLeaf)); 17239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isNonExclusivelyOwned)); 17249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &isExclusivelyOwned)); 1725cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1726cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1727cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1728cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1729cb87ef4cSFlorian Wechsung } 1730cf818975SFlorian Wechsung 1731252a1336SBarry Smith /* mark all the leafs */ 1732ad540459SPierre Jolivet for (i = 0; i < nleafs; i++) isLeaf[ilocal[i] - pStart] = PETSC_TRUE; 1733cb87ef4cSFlorian Wechsung 1734cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1735cf818975SFlorian Wechsung * not by calculating its degree */ 17369566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sf, °rees)); 17379566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sf, °rees)); 1738cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1739cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1740cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1741cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17427f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1743cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1744cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1745cb87ef4cSFlorian Wechsung } else { 1746cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1747cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1748cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1749cb87ef4cSFlorian Wechsung } 1750cb87ef4cSFlorian Wechsung } 1751cb87ef4cSFlorian Wechsung } 1752cb87ef4cSFlorian Wechsung } 1753cb87ef4cSFlorian Wechsung 1754252a1336SBarry Smith /* Build a graph with one vertex per core representing the 1755cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1756cf818975SFlorian Wechsung * point. */ 17579566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &layout)); 17589566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned)); 17599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(layout)); 17609566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRanges(layout, &cumSumVertices)); 17619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &globalNumbersOfLocalOwnedVertices)); 1762ad540459SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) globalNumbersOfLocalOwnedVertices[i] = pStart - 1; 1763cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1764cb87ef4cSFlorian Wechsung counter = 0; 1765cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 1766cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17677f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1768cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1769cb87ef4cSFlorian Wechsung counter++; 1770cb87ef4cSFlorian Wechsung } 1771cb87ef4cSFlorian Wechsung } 1772cb87ef4cSFlorian Wechsung } 1773cb87ef4cSFlorian Wechsung 1774cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 17759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &leafGlobalNumbers)); 17769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE)); 17779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers, MPI_REPLACE)); 1778cb87ef4cSFlorian Wechsung 1779252a1336SBarry Smith /* Build the graph for partitioning */ 1780252a1336SBarry Smith numRows = 1 + numNonExclusivelyOwned; 1781252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 17829566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 1783252a1336SBarry Smith PetscCall(MatSetType(A, MATMPIADJ)); 1784252a1336SBarry Smith PetscCall(MatSetSizes(A, numRows, numRows, cumSumVertices[size], cumSumVertices[size])); 1785252a1336SBarry Smith idx = cumSumVertices[rank]; 17864baf1206SFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 17874baf1206SFlorian Wechsung if (toBalance[i]) { 17880faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17890faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17900faf6628SFlorian Wechsung else continue; 17919566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, idx, jdx, 1, INSERT_VALUES)); 17929566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, jdx, idx, 1, INSERT_VALUES)); 17930941debbSFlorian Wechsung } 17940941debbSFlorian Wechsung } 1795252a1336SBarry Smith PetscCall(PetscFree(globalNumbersOfLocalOwnedVertices)); 1796252a1336SBarry Smith PetscCall(PetscFree(leafGlobalNumbers)); 17979566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 17989566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 1799252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalBuildGraph, dm, 0, 0, 0)); 18004baf1206SFlorian Wechsung 180141525646SFlorian Wechsung nparts = size; 1802252a1336SBarry Smith ncon = 1; 18039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * nparts, &tpwgts)); 1804ad540459SPierre Jolivet for (i = 0; i < ncon * nparts; i++) tpwgts[i] = 1. / (nparts); 18059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon, &ubvec)); 18066f2c871aSStefano Zampini for (i = 0; i < ncon; i++) ubvec[i] = 1.05; 18078c9a1619SFlorian Wechsung 18089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncon * (1 + numNonExclusivelyOwned), &vtxwgt)); 1809252a1336SBarry Smith if (ncon == 2) { 181041525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 1811252a1336SBarry Smith vtxwgt[1] = 1; 181241525646SFlorian Wechsung for (i = 0; i < numNonExclusivelyOwned; i++) { 181341525646SFlorian Wechsung vtxwgt[ncon * (i + 1)] = 1; 1814252a1336SBarry Smith vtxwgt[ncon * (i + 1) + 1] = 0; 1815252a1336SBarry Smith } 1816252a1336SBarry Smith } else { 1817252a1336SBarry Smith PetscInt base, ms; 1818a5a714f4SStefano Zampini PetscCall(MPIU_Allreduce(&numExclusivelyOwned, &base, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1819252a1336SBarry Smith PetscCall(MatGetSize(A, &ms, NULL)); 1820252a1336SBarry Smith ms -= size; 1821252a1336SBarry Smith base = PetscMax(base, ms); 1822252a1336SBarry Smith vtxwgt[0] = base + numExclusivelyOwned; 1823ad540459SPierre Jolivet for (i = 0; i < numNonExclusivelyOwned; i++) vtxwgt[i + 1] = 1; 182441525646SFlorian Wechsung } 18258c9a1619SFlorian Wechsung 18265dc86ac1SFlorian Wechsung if (viewer) { 182763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %" PetscInt_FMT " on interface of mesh distribution.\n", entityDepth)); 182863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %" PetscInt_FMT "\n", cumSumVertices[size])); 182912617df9SFlorian Wechsung } 1830252a1336SBarry Smith /* TODO: Drop the parallel/sequential choice here and just use MatPartioner for much more flexibility */ 1831252a1336SBarry Smith if (usematpartitioning) { 1832252a1336SBarry Smith const char *prefix; 1833252a1336SBarry Smith 1834252a1336SBarry Smith PetscCall(MatPartitioningCreate(PetscObjectComm((PetscObject)dm), &mp)); 1835252a1336SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mp, "dm_plex_rebalance_shared_points_")); 1836252a1336SBarry Smith PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1837252a1336SBarry Smith PetscCall(PetscObjectPrependOptionsPrefix((PetscObject)mp, prefix)); 1838252a1336SBarry Smith PetscCall(MatPartitioningSetAdjacency(mp, A)); 1839252a1336SBarry Smith PetscCall(MatPartitioningSetNumberVertexWeights(mp, ncon)); 1840252a1336SBarry Smith PetscCall(MatPartitioningSetVertexWeights(mp, vtxwgt)); 1841252a1336SBarry Smith PetscCall(MatPartitioningSetFromOptions(mp)); 1842252a1336SBarry Smith PetscCall(MatPartitioningApply(mp, &ispart)); 1843252a1336SBarry Smith PetscCall(ISGetIndices(ispart, (const PetscInt **)&part)); 1844252a1336SBarry Smith } else if (parallel) { 1845252a1336SBarry Smith if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n")); 1846252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part)); 1847252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done)); 1848252a1336SBarry Smith PetscCheck(done, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Could not get adjacency information"); 18499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(4, &options)); 18505a30b08bSFlorian Wechsung options[0] = 1; 18515a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 1852252a1336SBarry Smith if (viewer) options[1] = 1; 18535a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18545a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 1855252a1336SBarry Smith wgtflag = 2; 1856252a1336SBarry Smith numflag = 0; 18578c9a1619SFlorian Wechsung if (useInitialGuess) { 1858252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "THIS DOES NOT WORK! I don't know why. Using current distribution of points as initial guess.\n")); 1859252a1336SBarry Smith for (i = 0; i < numRows; i++) part[i] = rank; 18609566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n")); 1861792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_RefineKway"); 1862252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1863252a1336SBarry Smith ierr = ParMETIS_V3_RefineKway((PetscInt *)cumSumVertices, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 1864252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 18658c9a1619SFlorian Wechsung PetscStackPop; 1866252a1336SBarry Smith PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18678c9a1619SFlorian Wechsung } else { 1868792fecdfSBarry Smith PetscStackPushExternal("ParMETIS_V3_PartKway"); 1869252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1870252a1336SBarry Smith ierr = ParMETIS_V3_PartKway((PetscInt *)cumSumVertices, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 1871252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 18728c9a1619SFlorian Wechsung PetscStackPop; 18735f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18748c9a1619SFlorian Wechsung } 1875252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, &xadj, &adjncy, &done)); 18769566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 187741525646SFlorian Wechsung } else { 18789566063dSJacob Faibussowitsch if (viewer) PetscCall(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n")); 187941525646SFlorian Wechsung Mat As; 188041525646SFlorian Wechsung PetscInt *partGlobal; 188141525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 1882252a1336SBarry Smith 1883252a1336SBarry Smith PetscCall(PetscMalloc1(cumSumVertices[rank + 1] - cumSumVertices[rank], &part)); 1884252a1336SBarry Smith PetscCall(MatGetSize(A, &numRows, NULL)); 1885252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1886252a1336SBarry Smith PetscCall(MatMPIAdjToSeqRankZero(A, &As)); 1887252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalGatherGraph, dm, 0, 0, 0)); 1888252a1336SBarry Smith 18899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &numExclusivelyOwnedAll)); 189041525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 18919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, numExclusivelyOwnedAll, 1, MPIU_INT, comm)); 1892cb87ef4cSFlorian Wechsung 18939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &partGlobal)); 1894252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalPartition, 0, 0, 0, 0)); 1895dd400576SPatrick Sanan if (rank == 0) { 1896252a1336SBarry Smith PetscInt *vtxwgt_g, numRows_g; 189741525646SFlorian Wechsung 1898252a1336SBarry Smith PetscCall(MatGetRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done)); 1899252a1336SBarry Smith PetscCall(PetscMalloc1(2 * numRows_g, &vtxwgt_g)); 190041525646SFlorian Wechsung for (i = 0; i < size; i++) { 190141525646SFlorian Wechsung vtxwgt_g[ncon * cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 190241525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[ncon * cumSumVertices[i] + 1] = 1; 190341525646SFlorian Wechsung for (j = cumSumVertices[i] + 1; j < cumSumVertices[i + 1]; j++) { 190441525646SFlorian Wechsung vtxwgt_g[ncon * j] = 1; 190541525646SFlorian Wechsung if (ncon > 1) vtxwgt_g[2 * j + 1] = 0; 190641525646SFlorian Wechsung } 190741525646SFlorian Wechsung } 1908252a1336SBarry Smith 19099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(64, &options)); 191041525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 19115f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 191241525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 1913792fecdfSBarry Smith PetscStackPushExternal("METIS_PartGraphKway"); 1914252a1336SBarry Smith ierr = METIS_PartGraphKway(&numRows_g, &ncon, (idx_t *)xadj, (idx_t *)adjncy, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 191541525646SFlorian Wechsung PetscStackPop; 19165f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 19179566063dSJacob Faibussowitsch PetscCall(PetscFree(options)); 19189566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt_g)); 1919252a1336SBarry Smith PetscCall(MatRestoreRowIJ(As, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows_g, &xadj, &adjncy, &done)); 1920252a1336SBarry Smith PetscCall(MatDestroy(&As)); 192141525646SFlorian Wechsung } 1922252a1336SBarry Smith PetscCall(PetscBarrier((PetscObject)dm)); 1923252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalPartition, 0, 0, 0, 0)); 19249566063dSJacob Faibussowitsch PetscCall(PetscFree(numExclusivelyOwnedAll)); 192541525646SFlorian Wechsung 1926252a1336SBarry Smith /* scatter the partitioning information to ranks */ 1927252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalScatterPart, 0, 0, 0, 0)); 19289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &counts)); 19299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size + 1, &mpiCumSumVertices)); 1930*f4f49eeaSPierre Jolivet for (i = 0; i < size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i + 1] - cumSumVertices[i], &counts[i])); 1931*f4f49eeaSPierre Jolivet for (i = 0; i <= size; i++) PetscCall(PetscMPIIntCast(cumSumVertices[i], &mpiCumSumVertices[i])); 19329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm)); 19339566063dSJacob Faibussowitsch PetscCall(PetscFree(counts)); 19349566063dSJacob Faibussowitsch PetscCall(PetscFree(mpiCumSumVertices)); 19359566063dSJacob Faibussowitsch PetscCall(PetscFree(partGlobal)); 1936252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalScatterPart, 0, 0, 0, 0)); 193741525646SFlorian Wechsung } 19389566063dSJacob Faibussowitsch PetscCall(PetscFree(ubvec)); 19399566063dSJacob Faibussowitsch PetscCall(PetscFree(tpwgts)); 1940cb87ef4cSFlorian Wechsung 1941252a1336SBarry Smith /* Rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1942252a1336SBarry Smith PetscCall(PetscMalloc2(size, &firstVertices, size, &renumbering)); 1943cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 19449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, firstVertices, 1, MPIU_INT, comm)); 1945ad540459SPierre Jolivet for (i = 0; i < size; i++) renumbering[firstVertices[i]] = i; 1946ad540459SPierre Jolivet for (i = 0; i < cumSumVertices[rank + 1] - cumSumVertices[rank]; i++) part[i] = renumbering[part[i]]; 1947252a1336SBarry Smith PetscCall(PetscFree2(firstVertices, renumbering)); 1948252a1336SBarry Smith 1949cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1950cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 1951712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm)); 1952cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 1953aaa8cc7dSPierre Jolivet PetscCheck(failedGlobal <= 0, comm, PETSC_ERR_LIB, "Metis/Parmetis returned a bad partition"); 19549566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxwgt)); 19559566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 19569566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 19579566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 19589566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 1959252a1336SBarry Smith if (usematpartitioning) { 1960252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part)); 1961252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 1962252a1336SBarry Smith } else PetscCall(PetscFree(part)); 19637f57c1a4SFlorian Wechsung if (viewer) { 19649566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 1965cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 19667f57c1a4SFlorian Wechsung } 19679566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 19683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1969cb87ef4cSFlorian Wechsung } 1970cb87ef4cSFlorian Wechsung 1971252a1336SBarry Smith /* Check how well we did distributing points*/ 19725dc86ac1SFlorian Wechsung if (viewer) { 1973252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Number of owned entities of depth %" PetscInt_FMT ".\n", entityDepth)); 1974252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Initial ")); 19759566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, NULL, viewer)); 1976252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "Rebalanced ")); 19779566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 19787407ba93SFlorian Wechsung } 19797407ba93SFlorian Wechsung 1980252a1336SBarry Smith /* Check that every vertex is owned by a process that it is actually connected to. */ 1981252a1336SBarry Smith PetscCall(MatGetRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 198241525646SFlorian Wechsung for (i = 1; i <= numNonExclusivelyOwned; i++) { 1983cb87ef4cSFlorian Wechsung PetscInt loc = 0; 19849566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cumSumVertices[part[i]], xadj[i + 1] - xadj[i], &adjncy[xadj[i]], &loc)); 19857407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 1986ad540459SPierre Jolivet if (loc < 0) part[i] = rank; 1987cb87ef4cSFlorian Wechsung } 1988252a1336SBarry Smith PetscCall(MatRestoreRowIJ(A, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, &numRows, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 1989252a1336SBarry Smith PetscCall(MatDestroy(&A)); 1990cb87ef4cSFlorian Wechsung 1991252a1336SBarry Smith /* See how significant the influences of the previous fixing up step was.*/ 19925dc86ac1SFlorian Wechsung if (viewer) { 1993252a1336SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, "After fix ")); 19949566063dSJacob Faibussowitsch PetscCall(DMPlexViewDistribution(comm, cumSumVertices[rank + 1] - cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 19957407ba93SFlorian Wechsung } 1996252a1336SBarry Smith if (!usematpartitioning) PetscCall(PetscFree(vtxwgt)); 1997252a1336SBarry Smith else PetscCall(MatPartitioningDestroy(&mp)); 19987407ba93SFlorian Wechsung 19999566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 2000cb87ef4cSFlorian Wechsung 2001252a1336SBarry Smith PetscCall(PetscLogEventBegin(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 2002252a1336SBarry Smith /* Rewrite the SF to reflect the new ownership. */ 20039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite)); 20047f57c1a4SFlorian Wechsung counter = 0; 2005cb87ef4cSFlorian Wechsung for (i = 0; i < pEnd - pStart; i++) { 2006cb87ef4cSFlorian Wechsung if (toBalance[i]) { 2007cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 20087f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 2009cb87ef4cSFlorian Wechsung counter++; 2010cb87ef4cSFlorian Wechsung } 2011cb87ef4cSFlorian Wechsung } 2012cb87ef4cSFlorian Wechsung } 20139566063dSJacob Faibussowitsch PetscCall(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part + 1, degrees)); 20149566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsToRewrite)); 2015252a1336SBarry Smith PetscCall(PetscLogEventEnd(DMPLEX_RebalRewriteSF, dm, 0, 0, 0)); 2016cb87ef4cSFlorian Wechsung 20179566063dSJacob Faibussowitsch PetscCall(PetscFree(toBalance)); 20189566063dSJacob Faibussowitsch PetscCall(PetscFree(isLeaf)); 20199566063dSJacob Faibussowitsch PetscCall(PetscFree(isNonExclusivelyOwned)); 20209566063dSJacob Faibussowitsch PetscCall(PetscFree(isExclusivelyOwned)); 2021252a1336SBarry Smith if (usematpartitioning) { 2022252a1336SBarry Smith PetscCall(ISRestoreIndices(ispart, (const PetscInt **)&part)); 2023252a1336SBarry Smith PetscCall(ISDestroy(&ispart)); 2024252a1336SBarry Smith } else PetscCall(PetscFree(part)); 20255dc86ac1SFlorian Wechsung if (viewer) { 20269566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 20279566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 20287d197802SFlorian Wechsung } 20298b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 20309566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 20313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2032240408d3SFlorian Wechsung #else 20335f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 203441525646SFlorian Wechsung #endif 2035cb87ef4cSFlorian Wechsung } 2036