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 7*9fbee547SJacob Faibussowitsch static inline PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 80134a67bSLisandro Dalcin 95a107427SMatthew G. Knepley static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 105a107427SMatthew G. Knepley { 115a107427SMatthew G. Knepley DM ovdm; 125a107427SMatthew G. Knepley PetscSF sfPoint; 135a107427SMatthew G. Knepley IS cellNumbering; 145a107427SMatthew G. Knepley const PetscInt *cellNum; 155a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL; 165a107427SMatthew G. Knepley PetscBool useCone, useClosure; 175a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v; 185a107427SMatthew G. Knepley PetscMPIInt rank, size; 195a107427SMatthew G. Knepley PetscErrorCode ierr; 205a107427SMatthew G. Knepley 215a107427SMatthew G. Knepley PetscFunctionBegin; 225a107427SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 235a107427SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRMPI(ierr); 245a107427SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 255a107427SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 265a107427SMatthew G. Knepley if (dim != depth) { 275a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 285a107427SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 295a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 305a107427SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 315a107427SMatthew G. Knepley /* Different behavior for empty graphs */ 325a107427SMatthew G. Knepley if (!*numVertices) { 335a107427SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 345a107427SMatthew G. Knepley (*offsets)[0] = 0; 355a107427SMatthew G. Knepley } 365a107427SMatthew G. Knepley /* Broken in parallel */ 379ace16cdSJacob Faibussowitsch PetscAssertFalse(rank && *numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 385a107427SMatthew G. Knepley PetscFunctionReturn(0); 395a107427SMatthew G. Knepley } 405a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */ 415a107427SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 425a107427SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 435a107427SMatthew G. Knepley /* Need overlap >= 1 */ 445a107427SMatthew G. Knepley ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 455a107427SMatthew G. Knepley if (size && overlap < 1) { 465a107427SMatthew G. Knepley ierr = DMPlexDistributeOverlap(dm, 1, NULL, &ovdm);CHKERRQ(ierr); 475a107427SMatthew G. Knepley } else { 485a107427SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 495a107427SMatthew G. Knepley ovdm = dm; 505a107427SMatthew G. Knepley } 515a107427SMatthew G. Knepley ierr = DMGetPointSF(ovdm, &sfPoint);CHKERRQ(ierr); 525a107427SMatthew G. Knepley ierr = DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd);CHKERRQ(ierr); 535a107427SMatthew G. Knepley ierr = DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 545a107427SMatthew G. Knepley if (globalNumbering) { 555a107427SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) cellNumbering);CHKERRQ(ierr); 565a107427SMatthew G. Knepley *globalNumbering = cellNumbering; 575a107427SMatthew G. Knepley } 585a107427SMatthew G. Knepley ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 595a107427SMatthew G. Knepley /* Determine sizes */ 605a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) { 615a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 625a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 635a107427SMatthew G. Knepley (*numVertices)++; 645a107427SMatthew G. Knepley } 655a107427SMatthew G. Knepley ierr = PetscCalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 665a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 675a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0; 685a107427SMatthew G. Knepley 695a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 705a107427SMatthew G. Knepley ierr = DMPlexGetAdjacency(ovdm, c, &adjSize, &adj);CHKERRQ(ierr); 715a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 725a107427SMatthew G. Knepley const PetscInt point = adj[a]; 735a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize; 745a107427SMatthew G. Knepley } 755a107427SMatthew G. Knepley vOffsets[v+1] = vOffsets[v] + vsize; 765a107427SMatthew G. Knepley ++v; 775a107427SMatthew G. Knepley } 785a107427SMatthew G. Knepley /* Determine adjacency */ 795a107427SMatthew G. Knepley ierr = PetscMalloc1(vOffsets[*numVertices], &vAdj);CHKERRQ(ierr); 805a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 815a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v]; 825a107427SMatthew G. Knepley 835a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 845a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 855a107427SMatthew G. Knepley ierr = DMPlexGetAdjacency(ovdm, c, &adjSize, &adj);CHKERRQ(ierr); 865a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 875a107427SMatthew G. Knepley const PetscInt point = adj[a]; 885a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) { 895a107427SMatthew G. Knepley vAdj[off++] = DMPlex_GlobalID(cellNum[point]); 905a107427SMatthew G. Knepley } 915a107427SMatthew G. Knepley } 929ace16cdSJacob Faibussowitsch PetscAssertFalse(off != vOffsets[v+1],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %D should be %D", off, vOffsets[v+1]); 935a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */ 945a107427SMatthew G. Knepley ierr = PetscSortInt(off-vOffsets[v], &vAdj[vOffsets[v]]);CHKERRQ(ierr); 955a107427SMatthew G. Knepley ++v; 965a107427SMatthew G. Knepley } 975a107427SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 985a107427SMatthew G. Knepley ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 995a107427SMatthew G. Knepley ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 1005a107427SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 1015a107427SMatthew G. Knepley ierr = DMDestroy(&ovdm);CHKERRQ(ierr); 1025a107427SMatthew G. Knepley if (offsets) {*offsets = vOffsets;} 1035a107427SMatthew G. Knepley else {ierr = PetscFree(vOffsets);CHKERRQ(ierr);} 1045a107427SMatthew G. Knepley if (adjacency) {*adjacency = vAdj;} 1055a107427SMatthew G. Knepley else {ierr = PetscFree(vAdj);CHKERRQ(ierr);} 1065a107427SMatthew G. Knepley PetscFunctionReturn(0); 1075a107427SMatthew G. Knepley } 1085a107427SMatthew G. Knepley 109bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 110532c4e7dSMichael Lange { 111ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 112389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 1138cfe4c1fSMichael Lange IS cellNumbering; 1148cfe4c1fSMichael Lange const PetscInt *cellNum; 115532c4e7dSMichael Lange PetscBool useCone, useClosure; 116532c4e7dSMichael Lange PetscSection section; 117532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 1188cfe4c1fSMichael Lange PetscSF sfPoint; 1198f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 1208f4e72b9SMatthew G. Knepley const PetscInt *local; 1218f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 122532c4e7dSMichael Lange PetscMPIInt rank; 123532c4e7dSMichael Lange PetscErrorCode ierr; 124532c4e7dSMichael Lange 125532c4e7dSMichael Lange PetscFunctionBegin; 126ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 127ffbd6163SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 128ffbd6163SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 129ffbd6163SMatthew G. Knepley if (dim != depth) { 130ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 131ffbd6163SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 132ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 133ffbd6163SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 134ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 135ffbd6163SMatthew G. Knepley if (!*numVertices) { 136ffbd6163SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 137ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 138ffbd6163SMatthew G. Knepley } 139ffbd6163SMatthew G. Knepley /* Broken in parallel */ 1409ace16cdSJacob Faibussowitsch PetscAssertFalse(rank && *numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 141ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 142ffbd6163SMatthew G. Knepley } 1438cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 1440134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 145532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 146532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 147532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 148532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 149532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 150b0441da4SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 151b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 1529886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 1533fa7752dSToby Isaac if (globalNumbering) { 1543fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 1553fa7752dSToby Isaac *globalNumbering = cellNumbering; 1563fa7752dSToby Isaac } 1578cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 1588f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 1598f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 1608f4e72b9SMatthew G. Knepley */ 1610134a67bSLisandro Dalcin ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr); 1628f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1638f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1648f4e72b9SMatthew G. Knepley 1658f4e72b9SMatthew G. Knepley ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr); 1660134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 1678f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1688f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1698f4e72b9SMatthew G. Knepley const PetscInt *support; 1708f4e72b9SMatthew G. Knepley PetscInt supportSize; 1718f4e72b9SMatthew G. Knepley 1728f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 1738f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 1740134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1758f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 1768f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1770134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 1788f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1790134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1800134a67bSLisandro Dalcin } 1810134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1820134a67bSLisandro Dalcin if (supportSize > 2) { 1830134a67bSLisandro Dalcin PetscInt numChildren, i; 1840134a67bSLisandro Dalcin const PetscInt *children; 1850134a67bSLisandro Dalcin 1860134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr); 1870134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1880134a67bSLisandro Dalcin const PetscInt child = children[i]; 1890134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1900134a67bSLisandro Dalcin ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr); 1910134a67bSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr); 1920134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1930134a67bSLisandro Dalcin else if (supportSize == 2) { 1940134a67bSLisandro Dalcin ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1950134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 1960134a67bSLisandro Dalcin ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1970134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1980134a67bSLisandro Dalcin } 1990134a67bSLisandro Dalcin } 2000134a67bSLisandro Dalcin } 2018f4e72b9SMatthew G. Knepley } 2028f4e72b9SMatthew G. Knepley } 2038f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 204ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE);CHKERRQ(ierr); 205ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE);CHKERRQ(ierr); 2068f4e72b9SMatthew G. Knepley ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 2078f4e72b9SMatthew G. Knepley ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 2088f4e72b9SMatthew G. Knepley } 2098f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 2108cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 2118cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 2128cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 2138f4e72b9SMatthew G. Knepley /* Add remote cells */ 2148f4e72b9SMatthew G. Knepley if (remoteCells) { 2150134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 2160134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 2170134a67bSLisandro Dalcin const PetscInt *cone, *children; 2180134a67bSLisandro Dalcin 2198f4e72b9SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2208f4e72b9SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2218f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 2220134a67bSLisandro Dalcin const PetscInt point = cone[c]; 2230134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 2248f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 2258f4e72b9SMatthew G. Knepley ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 2268f4e72b9SMatthew G. Knepley ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 2270134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 2280134a67bSLisandro Dalcin } 2290134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 2300134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 2310134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 2320134a67bSLisandro Dalcin const PetscInt child = children[i]; 2330134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 2340134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 2350134a67bSLisandro Dalcin ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 2360134a67bSLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 2370134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 2380134a67bSLisandro Dalcin } 2398f4e72b9SMatthew G. Knepley } 2408f4e72b9SMatthew G. Knepley } 2418f4e72b9SMatthew G. Knepley } 2428f4e72b9SMatthew G. Knepley /* Add local cells */ 243532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 244532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 245532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 246532c4e7dSMichael Lange const PetscInt point = adj[a]; 247532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 248532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 249532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 250532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 2510134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 252532c4e7dSMichael Lange } 253532c4e7dSMichael Lange } 2548cfe4c1fSMichael Lange (*numVertices)++; 255532c4e7dSMichael Lange } 2564e468a93SLisandro Dalcin ierr = PetscFree(adj);CHKERRQ(ierr); 2578f4e72b9SMatthew G. Knepley ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr); 258b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 2594e468a93SLisandro Dalcin 260532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 261532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 262532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 263389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 26443f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 26543f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 26643f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 26743f7d02bSMichael Lange } 268532c4e7dSMichael Lange vOffsets[*numVertices] = size; 269389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 2704e468a93SLisandro Dalcin 2714e468a93SLisandro Dalcin if (nroots >= 0) { 2724e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 2734e468a93SLisandro Dalcin ierr = PetscSectionReset(section);CHKERRQ(ierr); 2744e468a93SLisandro Dalcin ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr); 2754e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2764e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2774e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 2784e468a93SLisandro Dalcin ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr); 2794e468a93SLisandro Dalcin ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr); 2804e468a93SLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr); 281580bdb30SBarry Smith ierr = PetscArraycpy(edges, &graph[start], numEdges);CHKERRQ(ierr); 2824e468a93SLisandro Dalcin } 2834e468a93SLisandro Dalcin ierr = PetscFree(vOffsets);CHKERRQ(ierr); 2844e468a93SLisandro Dalcin ierr = PetscFree(graph);CHKERRQ(ierr); 2854e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2864e468a93SLisandro Dalcin ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 2874e468a93SLisandro Dalcin ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2884e468a93SLisandro Dalcin ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 2894e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 2904e468a93SLisandro Dalcin ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 2914e468a93SLisandro Dalcin } 2924e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2934e468a93SLisandro Dalcin ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 2944e468a93SLisandro Dalcin } else { 2954e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2964e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2974e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2984e468a93SLisandro Dalcin ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr); 2994e468a93SLisandro Dalcin } 3004e468a93SLisandro Dalcin } 3014e468a93SLisandro Dalcin 3024e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 303389e55d8SMichael Lange if (adjacency) *adjacency = graph; 3044e468a93SLisandro Dalcin 305532c4e7dSMichael Lange /* Cleanup */ 306532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 307532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3084e468a93SLisandro Dalcin ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 3094e468a93SLisandro Dalcin ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 310532c4e7dSMichael Lange PetscFunctionReturn(0); 311532c4e7dSMichael Lange } 312532c4e7dSMichael Lange 313bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 314bbbc8e51SStefano Zampini { 315bbbc8e51SStefano Zampini Mat conn, CSR; 316bbbc8e51SStefano Zampini IS fis, cis, cis_own; 317bbbc8e51SStefano Zampini PetscSF sfPoint; 318bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 319bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 32083c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 321bbbc8e51SStefano Zampini PetscMPIInt rank; 322bbbc8e51SStefano Zampini PetscBool flg; 323bbbc8e51SStefano Zampini PetscErrorCode ierr; 324bbbc8e51SStefano Zampini 325bbbc8e51SStefano Zampini PetscFunctionBegin; 326ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 327bbbc8e51SStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 328bbbc8e51SStefano Zampini ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 329bbbc8e51SStefano Zampini if (dim != depth) { 330bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 331bbbc8e51SStefano Zampini ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 332bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 333bbbc8e51SStefano Zampini if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 334bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 335bbbc8e51SStefano Zampini if (!*numVertices) { 336bbbc8e51SStefano Zampini ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 337bbbc8e51SStefano Zampini (*offsets)[0] = 0; 338bbbc8e51SStefano Zampini } 339bbbc8e51SStefano Zampini /* Broken in parallel */ 3409ace16cdSJacob Faibussowitsch PetscAssertFalse(rank && *numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 341bbbc8e51SStefano Zampini PetscFunctionReturn(0); 342bbbc8e51SStefano Zampini } 343bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 344bbbc8e51SStefano Zampini 345bbbc8e51SStefano Zampini /* numbering */ 346bbbc8e51SStefano Zampini ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 347bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr); 348bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 3499886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr); 3509886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr); 351bbbc8e51SStefano Zampini if (globalNumbering) { 352bbbc8e51SStefano Zampini ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr); 353bbbc8e51SStefano Zampini } 354bbbc8e51SStefano Zampini 355bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 356bbbc8e51SStefano Zampini ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr); 357bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 358bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 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 } 369bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 370bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 371bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 372bbbc8e51SStefano Zampini 373bbbc8e51SStefano Zampini ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr); 374bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 375bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 376bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr); 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 } 387bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 388bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 389bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 390bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr); 391bbbc8e51SStefano Zampini 392bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 393bbbc8e51SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr); 394bbbc8e51SStefano Zampini ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr); 395bbbc8e51SStefano Zampini ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr); 39683c5d788SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, NULL, &lm);CHKERRQ(ierr); 397ffc4695bSBarry Smith ierr = MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 398bbbc8e51SStefano Zampini ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr); 399bbbc8e51SStefano Zampini 400bbbc8e51SStefano Zampini /* Assemble matrix */ 401bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 402bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 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]; 408bbbc8e51SStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 409bbbc8e51SStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 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]; 416bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 417bbbc8e51SStefano Zampini 418bbbc8e51SStefano Zampini /* non-conforming meshes */ 419bbbc8e51SStefano Zampini ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr); 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]; 425bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 426bbbc8e51SStefano Zampini } 427bbbc8e51SStefano Zampini } 428bbbc8e51SStefano Zampini } 429bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 430bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 431bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 432bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 433bbbc8e51SStefano Zampini ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 434bbbc8e51SStefano Zampini ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 435bbbc8e51SStefano Zampini 436bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 437bbbc8e51SStefano Zampini ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr); 438bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 439bbbc8e51SStefano Zampini 440bbbc8e51SStefano Zampini /* extract local part of the CSR */ 441bbbc8e51SStefano Zampini ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr); 442bbbc8e51SStefano Zampini ierr = MatDestroy(&CSR);CHKERRQ(ierr); 443bbbc8e51SStefano Zampini ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 4449ace16cdSJacob Faibussowitsch PetscAssertFalse(!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) { 449bbbc8e51SStefano Zampini ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr); 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) { 454bbbc8e51SStefano Zampini ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr); 455bbbc8e51SStefano Zampini ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr); 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 } 4649ace16cdSJacob Faibussowitsch PetscAssertFalse(c != ii[m] - m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 465bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr); 466bbbc8e51SStefano Zampini *adjacency = idxs; 467bbbc8e51SStefano Zampini } 468bbbc8e51SStefano Zampini 469bbbc8e51SStefano Zampini /* cleanup */ 470bbbc8e51SStefano Zampini ierr = ISDestroy(&cis_own);CHKERRQ(ierr); 471bbbc8e51SStefano Zampini ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 4729ace16cdSJacob Faibussowitsch PetscAssertFalse(!flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 473bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 474bbbc8e51SStefano Zampini PetscFunctionReturn(0); 475bbbc8e51SStefano Zampini } 476bbbc8e51SStefano Zampini 477bbbc8e51SStefano Zampini /*@C 478bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 479bbbc8e51SStefano Zampini 480bbbc8e51SStefano Zampini Input Parameters: 481bbbc8e51SStefano Zampini + dm - The mesh DM dm 482bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 483bbbc8e51SStefano Zampini 484d8d19677SJose E. Roman Output Parameters: 485bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 486bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 487bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 488bbbc8e51SStefano 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. 489bbbc8e51SStefano Zampini 490bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 491bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 492bbbc8e51SStefano Zampini 4935a107427SMatthew G. Knepley Options Database Keys: 4945a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4955a107427SMatthew G. Knepley 496bbbc8e51SStefano Zampini Level: developer 497bbbc8e51SStefano Zampini 498bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 499bbbc8e51SStefano Zampini @*/ 500bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 501bbbc8e51SStefano Zampini { 5025a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH; 503bbbc8e51SStefano Zampini PetscErrorCode ierr; 504bbbc8e51SStefano Zampini 505bbbc8e51SStefano Zampini PetscFunctionBegin; 5065a107427SMatthew G. Knepley ierr = PetscOptionsGetEnum(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *) &alg, NULL);CHKERRQ(ierr); 5075a107427SMatthew G. Knepley switch (alg) { 5085a107427SMatthew G. Knepley case DM_PLEX_CSR_MAT: 5095a107427SMatthew G. Knepley ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break; 5105a107427SMatthew G. Knepley case DM_PLEX_CSR_GRAPH: 5115a107427SMatthew G. Knepley ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break; 5125a107427SMatthew G. Knepley case DM_PLEX_CSR_OVERLAP: 5135a107427SMatthew G. Knepley ierr = DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break; 514bbbc8e51SStefano Zampini } 515bbbc8e51SStefano Zampini PetscFunctionReturn(0); 516bbbc8e51SStefano Zampini } 517bbbc8e51SStefano Zampini 518d5577e40SMatthew G. Knepley /*@C 519d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 520d5577e40SMatthew G. Knepley 521fe2efc57SMark Collective on DM 522d5577e40SMatthew G. Knepley 5234165533cSJose E. Roman Input Parameters: 524d5577e40SMatthew G. Knepley + dm - The DMPlex 525d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 526d5577e40SMatthew G. Knepley 5274165533cSJose E. Roman Output Parameters: 528d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 529d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 530d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 531d5577e40SMatthew G. Knepley 532d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 533d5577e40SMatthew G. Knepley 534d5577e40SMatthew G. Knepley Level: advanced 535d5577e40SMatthew G. Knepley 536d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 537d5577e40SMatthew G. Knepley @*/ 53870034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 53970034214SMatthew G. Knepley { 54070034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 54170034214SMatthew G. Knepley PetscInt numFaceCases = 0; 54270034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 54370034214SMatthew G. Knepley PetscInt *off, *adj; 54470034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 54570034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 54670034214SMatthew G. Knepley PetscErrorCode ierr; 54770034214SMatthew G. Knepley 54870034214SMatthew G. Knepley PetscFunctionBegin; 54970034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 550c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 55170034214SMatthew G. Knepley cellDim = dim - cellHeight; 55270034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 55370034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 55470034214SMatthew G. Knepley if (cEnd - cStart == 0) { 55570034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 55670034214SMatthew G. Knepley if (offsets) *offsets = NULL; 55770034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 55870034214SMatthew G. Knepley PetscFunctionReturn(0); 55970034214SMatthew G. Knepley } 56070034214SMatthew G. Knepley numCells = cEnd - cStart; 56170034214SMatthew G. Knepley faceDepth = depth - cellHeight; 56270034214SMatthew G. Knepley if (dim == depth) { 56370034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 56470034214SMatthew G. Knepley 56570034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 56670034214SMatthew G. Knepley /* Count neighboring cells */ 56770034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 56870034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 56970034214SMatthew G. Knepley const PetscInt *support; 57070034214SMatthew G. Knepley PetscInt supportSize; 57170034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 57270034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 57370034214SMatthew G. Knepley if (supportSize == 2) { 5749ffc88e4SToby Isaac PetscInt numChildren; 5759ffc88e4SToby Isaac 5769ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5779ffc88e4SToby Isaac if (!numChildren) { 57870034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 57970034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 58070034214SMatthew G. Knepley } 58170034214SMatthew G. Knepley } 5829ffc88e4SToby Isaac } 58370034214SMatthew G. Knepley /* Prefix sum */ 58470034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 58570034214SMatthew G. Knepley if (adjacency) { 58670034214SMatthew G. Knepley PetscInt *tmp; 58770034214SMatthew G. Knepley 58870034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 589854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 590580bdb30SBarry Smith ierr = PetscArraycpy(tmp, off, numCells+1);CHKERRQ(ierr); 59170034214SMatthew G. Knepley /* Get neighboring cells */ 59270034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 59370034214SMatthew G. Knepley const PetscInt *support; 59470034214SMatthew G. Knepley PetscInt supportSize; 59570034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 59670034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 59770034214SMatthew G. Knepley if (supportSize == 2) { 5989ffc88e4SToby Isaac PetscInt numChildren; 5999ffc88e4SToby Isaac 6009ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 6019ffc88e4SToby Isaac if (!numChildren) { 60270034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 60370034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 60470034214SMatthew G. Knepley } 60570034214SMatthew G. Knepley } 6069ffc88e4SToby Isaac } 60776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 6089ace16cdSJacob Faibussowitsch for (c = 0; c < cEnd-cStart; ++c) PetscAssertFalse(tmp[c] != off[c+1],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 60976bd3646SJed Brown } 61070034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 61170034214SMatthew G. Knepley } 61270034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 61370034214SMatthew G. Knepley if (offsets) *offsets = off; 61470034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 61570034214SMatthew G. Knepley PetscFunctionReturn(0); 61670034214SMatthew G. Knepley } 61770034214SMatthew G. Knepley /* Setup face recognition */ 61870034214SMatthew G. Knepley if (faceDepth == 1) { 61970034214SMatthew 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 */ 62070034214SMatthew G. Knepley 62170034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 62270034214SMatthew G. Knepley PetscInt corners; 62370034214SMatthew G. Knepley 62470034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 62570034214SMatthew G. Knepley if (!cornersSeen[corners]) { 62670034214SMatthew G. Knepley PetscInt nFV; 62770034214SMatthew G. Knepley 6289ace16cdSJacob Faibussowitsch PetscAssertFalse(numFaceCases >= maxFaceCases,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 62970034214SMatthew G. Knepley cornersSeen[corners] = 1; 63070034214SMatthew G. Knepley 63170034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 63270034214SMatthew G. Knepley 63370034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 63470034214SMatthew G. Knepley } 63570034214SMatthew G. Knepley } 63670034214SMatthew G. Knepley } 63770034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 63870034214SMatthew G. Knepley /* Count neighboring cells */ 63970034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 64070034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 64170034214SMatthew G. Knepley 6428b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 64370034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 64470034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 64570034214SMatthew G. Knepley PetscInt cellPair[2]; 64670034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 64770034214SMatthew G. Knepley PetscInt meetSize = 0; 64870034214SMatthew G. Knepley const PetscInt *meet = NULL; 64970034214SMatthew G. Knepley 65070034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 65170034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 65270034214SMatthew G. Knepley if (!found) { 65370034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 65470034214SMatthew G. Knepley if (meetSize) { 65570034214SMatthew G. Knepley PetscInt f; 65670034214SMatthew G. Knepley 65770034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 65870034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 65970034214SMatthew G. Knepley found = PETSC_TRUE; 66070034214SMatthew G. Knepley break; 66170034214SMatthew G. Knepley } 66270034214SMatthew G. Knepley } 66370034214SMatthew G. Knepley } 66470034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 66570034214SMatthew G. Knepley } 66670034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 66770034214SMatthew G. Knepley } 66870034214SMatthew G. Knepley } 66970034214SMatthew G. Knepley /* Prefix sum */ 67070034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 67170034214SMatthew G. Knepley 67270034214SMatthew G. Knepley if (adjacency) { 67370034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 67470034214SMatthew G. Knepley /* Get neighboring cells */ 67570034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 67670034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 67770034214SMatthew G. Knepley PetscInt cellOffset = 0; 67870034214SMatthew G. Knepley 6798b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 68070034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 68170034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 68270034214SMatthew G. Knepley PetscInt cellPair[2]; 68370034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 68470034214SMatthew G. Knepley PetscInt meetSize = 0; 68570034214SMatthew G. Knepley const PetscInt *meet = NULL; 68670034214SMatthew G. Knepley 68770034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 68870034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 68970034214SMatthew G. Knepley if (!found) { 69070034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 69170034214SMatthew G. Knepley if (meetSize) { 69270034214SMatthew G. Knepley PetscInt f; 69370034214SMatthew G. Knepley 69470034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 69570034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 69670034214SMatthew G. Knepley found = PETSC_TRUE; 69770034214SMatthew G. Knepley break; 69870034214SMatthew G. Knepley } 69970034214SMatthew G. Knepley } 70070034214SMatthew G. Knepley } 70170034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 70270034214SMatthew G. Knepley } 70370034214SMatthew G. Knepley if (found) { 70470034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 70570034214SMatthew G. Knepley ++cellOffset; 70670034214SMatthew G. Knepley } 70770034214SMatthew G. Knepley } 70870034214SMatthew G. Knepley } 70970034214SMatthew G. Knepley } 71070034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 71170034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 71270034214SMatthew G. Knepley if (offsets) *offsets = off; 71370034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 71470034214SMatthew G. Knepley PetscFunctionReturn(0); 71570034214SMatthew G. Knepley } 71670034214SMatthew G. Knepley 71777623264SMatthew G. Knepley /*@ 7183c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 71977623264SMatthew G. Knepley 720fe2efc57SMark Collective on PetscPartitioner 72177623264SMatthew G. Knepley 72277623264SMatthew G. Knepley Input Parameters: 72377623264SMatthew G. Knepley + part - The PetscPartitioner 7243c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 725f8987ae8SMichael Lange - dm - The mesh DM 72677623264SMatthew G. Knepley 72777623264SMatthew G. Knepley Output Parameters: 72877623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 729f8987ae8SMichael Lange - partition - The list of points by partition 73077623264SMatthew G. Knepley 7313c41b853SStefano Zampini Notes: 7323c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 7333c41b853SStefano Zampini by the section in the transitive closure of the point. 73477623264SMatthew G. Knepley 73577623264SMatthew G. Knepley Level: developer 73677623264SMatthew G. Knepley 7373c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition() 7384b15ede2SMatthew G. Knepley @*/ 7393c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 74077623264SMatthew G. Knepley { 74177623264SMatthew G. Knepley PetscMPIInt size; 7423c41b853SStefano Zampini PetscBool isplex; 74377623264SMatthew G. Knepley PetscErrorCode ierr; 7443c41b853SStefano Zampini PetscSection vertSection = NULL; 74577623264SMatthew G. Knepley 74677623264SMatthew G. Knepley PetscFunctionBegin; 74777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 74877623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7493c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 75077623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 75177623264SMatthew G. Knepley PetscValidPointer(partition, 5); 7523c41b853SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr); 7539ace16cdSJacob Faibussowitsch PetscAssertFalse(!isplex,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 754ffc4695bSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRMPI(ierr); 75577623264SMatthew G. Knepley if (size == 1) { 75677623264SMatthew G. Knepley PetscInt *points; 75777623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 75877623264SMatthew G. Knepley 75977623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 7603c41b853SStefano Zampini ierr = PetscSectionReset(partSection);CHKERRQ(ierr); 76177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 76277623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 76377623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 76477623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 76577623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 76677623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 76777623264SMatthew G. Knepley PetscFunctionReturn(0); 76877623264SMatthew G. Knepley } 76977623264SMatthew G. Knepley if (part->height == 0) { 770074d466cSStefano Zampini PetscInt numVertices = 0; 77177623264SMatthew G. Knepley PetscInt *start = NULL; 77277623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7733fa7752dSToby Isaac IS globalNumbering; 77477623264SMatthew G. Knepley 775074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 776074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 77713911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 778074d466cSStefano Zampini const PetscInt *idxs; 779074d466cSStefano Zampini PetscInt p, pStart, pEnd; 780074d466cSStefano Zampini 781074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 7829886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 783074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 784074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 785074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 786074d466cSStefano Zampini } 7873c41b853SStefano Zampini if (part->usevwgt) { 7883c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7893c41b853SStefano Zampini IS clPoints = NULL; 7903c41b853SStefano Zampini const PetscInt *gid,*clIdx; 7913c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7920358368aSMatthew G. Knepley 7933c41b853SStefano 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) */ 7943c41b853SStefano Zampini /* We do this only if the local section has been set */ 7953c41b853SStefano Zampini if (section) { 7963c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL);CHKERRQ(ierr); 7973c41b853SStefano Zampini if (!clSection) { 7983c41b853SStefano Zampini ierr = DMPlexCreateClosureIndex(dm,NULL);CHKERRQ(ierr); 7993c41b853SStefano Zampini } 8003c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints);CHKERRQ(ierr); 8013c41b853SStefano Zampini ierr = ISGetIndices(clPoints,&clIdx);CHKERRQ(ierr); 8023c41b853SStefano Zampini } 8033c41b853SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 8043c41b853SStefano Zampini ierr = PetscSectionCreate(PETSC_COMM_SELF, &vertSection);CHKERRQ(ierr); 8053c41b853SStefano Zampini ierr = PetscSectionSetChart(vertSection, 0, numVertices);CHKERRQ(ierr); 8063c41b853SStefano Zampini if (globalNumbering) { 8073c41b853SStefano Zampini ierr = ISGetIndices(globalNumbering,&gid);CHKERRQ(ierr); 8083c41b853SStefano Zampini } else gid = NULL; 8093c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 8103c41b853SStefano Zampini PetscInt dof = 1; 8110358368aSMatthew G. Knepley 8123c41b853SStefano Zampini /* skip cells in the overlap */ 8133c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 8143c41b853SStefano Zampini 8153c41b853SStefano Zampini if (section) { 8163c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8173c41b853SStefano Zampini 8183c41b853SStefano Zampini dof = 0; 8193c41b853SStefano Zampini ierr = PetscSectionGetDof(clSection, p, &clSize);CHKERRQ(ierr); 8203c41b853SStefano Zampini ierr = PetscSectionGetOffset(clSection, p, &clOff);CHKERRQ(ierr); 8213c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 8223c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8233c41b853SStefano Zampini 8243c41b853SStefano Zampini ierr = PetscSectionGetDof(section, clPoint, &clDof);CHKERRQ(ierr); 8253c41b853SStefano Zampini dof += clDof; 8260358368aSMatthew G. Knepley } 8270358368aSMatthew G. Knepley } 8289ace16cdSJacob Faibussowitsch PetscAssertFalse(!dof,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p); 8293c41b853SStefano Zampini ierr = PetscSectionSetDof(vertSection, v, dof);CHKERRQ(ierr); 8303c41b853SStefano Zampini v++; 8313c41b853SStefano Zampini } 8323c41b853SStefano Zampini if (globalNumbering) { 8333c41b853SStefano Zampini ierr = ISRestoreIndices(globalNumbering,&gid);CHKERRQ(ierr); 8343c41b853SStefano Zampini } 8353c41b853SStefano Zampini if (clPoints) { 8363c41b853SStefano Zampini ierr = ISRestoreIndices(clPoints,&clIdx);CHKERRQ(ierr); 8373c41b853SStefano Zampini } 8383c41b853SStefano Zampini ierr = PetscSectionSetUp(vertSection);CHKERRQ(ierr); 8393c41b853SStefano Zampini } 8403c41b853SStefano Zampini ierr = PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition);CHKERRQ(ierr); 84177623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 84277623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 8433fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8443fa7752dSToby Isaac const PetscInt *globalNum; 8453fa7752dSToby Isaac const PetscInt *partIdx; 8463fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8473fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8483fa7752dSToby Isaac IS newPartition; 8493fa7752dSToby Isaac 8503fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 8513fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 8523fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 8533fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 8543fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 8553fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 8563fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8573fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8583fa7752dSToby Isaac } 8593fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 8603fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 8613fa7752dSToby Isaac } 8623fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 8633fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 8643fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 8653fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 8663fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 8673fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 8683fa7752dSToby Isaac *partition = newPartition; 8693fa7752dSToby Isaac } 87098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 8713c41b853SStefano Zampini ierr = PetscSectionDestroy(&vertSection);CHKERRQ(ierr); 87277623264SMatthew G. Knepley PetscFunctionReturn(0); 87377623264SMatthew G. Knepley } 87477623264SMatthew G. Knepley 8755680f57bSMatthew G. Knepley /*@ 8765680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8775680f57bSMatthew G. Knepley 8785680f57bSMatthew G. Knepley Not collective 8795680f57bSMatthew G. Knepley 8805680f57bSMatthew G. Knepley Input Parameter: 8815680f57bSMatthew G. Knepley . dm - The DM 8825680f57bSMatthew G. Knepley 8835680f57bSMatthew G. Knepley Output Parameter: 8845680f57bSMatthew G. Knepley . part - The PetscPartitioner 8855680f57bSMatthew G. Knepley 8865680f57bSMatthew G. Knepley Level: developer 8875680f57bSMatthew G. Knepley 88898599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 88998599a47SLawrence Mitchell 8903c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate() 8915680f57bSMatthew G. Knepley @*/ 8925680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 8935680f57bSMatthew G. Knepley { 8945680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 8955680f57bSMatthew G. Knepley 8965680f57bSMatthew G. Knepley PetscFunctionBegin; 8975680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8985680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 8995680f57bSMatthew G. Knepley *part = mesh->partitioner; 9005680f57bSMatthew G. Knepley PetscFunctionReturn(0); 9015680f57bSMatthew G. Knepley } 9025680f57bSMatthew G. Knepley 90371bb2955SLawrence Mitchell /*@ 90471bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 90571bb2955SLawrence Mitchell 906fe2efc57SMark logically collective on DM 90771bb2955SLawrence Mitchell 90871bb2955SLawrence Mitchell Input Parameters: 90971bb2955SLawrence Mitchell + dm - The DM 91071bb2955SLawrence Mitchell - part - The partitioner 91171bb2955SLawrence Mitchell 91271bb2955SLawrence Mitchell Level: developer 91371bb2955SLawrence Mitchell 91471bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 91571bb2955SLawrence Mitchell 91671bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 91771bb2955SLawrence Mitchell @*/ 91871bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 91971bb2955SLawrence Mitchell { 92071bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 92171bb2955SLawrence Mitchell PetscErrorCode ierr; 92271bb2955SLawrence Mitchell 92371bb2955SLawrence Mitchell PetscFunctionBegin; 92471bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92571bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 92671bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 92771bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 92871bb2955SLawrence Mitchell mesh->partitioner = part; 92971bb2955SLawrence Mitchell PetscFunctionReturn(0); 93071bb2955SLawrence Mitchell } 93171bb2955SLawrence Mitchell 9328e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 9338e330a33SStefano Zampini { 9348e330a33SStefano Zampini const PetscInt *cone; 9358e330a33SStefano Zampini PetscInt coneSize, c; 9368e330a33SStefano Zampini PetscBool missing; 9378e330a33SStefano Zampini PetscErrorCode ierr; 9388e330a33SStefano Zampini 9398e330a33SStefano Zampini PetscFunctionBeginHot; 9408e330a33SStefano Zampini ierr = PetscHSetIQueryAdd(ht, point, &missing);CHKERRQ(ierr); 9418e330a33SStefano Zampini if (missing) { 9428e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 9438e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 9448e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9458e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, cone[c]);CHKERRQ(ierr); 9468e330a33SStefano Zampini } 9478e330a33SStefano Zampini } 9488e330a33SStefano Zampini PetscFunctionReturn(0); 9498e330a33SStefano Zampini } 9508e330a33SStefano Zampini 9518e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 952270bba0cSToby Isaac { 953270bba0cSToby Isaac PetscErrorCode ierr; 954270bba0cSToby Isaac 955270bba0cSToby Isaac PetscFunctionBegin; 9566a5a2ffdSToby Isaac if (up) { 9576a5a2ffdSToby Isaac PetscInt parent; 9586a5a2ffdSToby Isaac 959270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 9606a5a2ffdSToby Isaac if (parent != point) { 9616a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9626a5a2ffdSToby Isaac 963270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 964270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 965270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 966270bba0cSToby Isaac 967e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 9681b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 969270bba0cSToby Isaac } 970270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 9716a5a2ffdSToby Isaac } 9726a5a2ffdSToby Isaac } 9736a5a2ffdSToby Isaac if (down) { 9746a5a2ffdSToby Isaac PetscInt numChildren; 9756a5a2ffdSToby Isaac const PetscInt *children; 9766a5a2ffdSToby Isaac 9776a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 9786a5a2ffdSToby Isaac if (numChildren) { 9796a5a2ffdSToby Isaac PetscInt i; 9806a5a2ffdSToby Isaac 9816a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9826a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9836a5a2ffdSToby Isaac 984e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 9851b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 9866a5a2ffdSToby Isaac } 9876a5a2ffdSToby Isaac } 9886a5a2ffdSToby Isaac } 989270bba0cSToby Isaac PetscFunctionReturn(0); 990270bba0cSToby Isaac } 991270bba0cSToby Isaac 9928e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 9938e330a33SStefano Zampini { 9948e330a33SStefano Zampini PetscInt parent; 9958e330a33SStefano Zampini PetscErrorCode ierr; 996825f8a23SLisandro Dalcin 9978e330a33SStefano Zampini PetscFunctionBeginHot; 9988e330a33SStefano Zampini ierr = DMPlexGetTreeParent(dm, point, &parent,NULL);CHKERRQ(ierr); 9998e330a33SStefano Zampini if (point != parent) { 10008e330a33SStefano Zampini const PetscInt *cone; 10018e330a33SStefano Zampini PetscInt coneSize, c; 10028e330a33SStefano Zampini 10038e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, parent);CHKERRQ(ierr); 10048e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, parent);CHKERRQ(ierr); 10058e330a33SStefano Zampini ierr = DMPlexGetCone(dm, parent, &cone);CHKERRQ(ierr); 10068e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, parent, &coneSize);CHKERRQ(ierr); 10078e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 10088e330a33SStefano Zampini const PetscInt cp = cone[c]; 10098e330a33SStefano Zampini 10108e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, cp);CHKERRQ(ierr); 10118e330a33SStefano Zampini } 10128e330a33SStefano Zampini } 10138e330a33SStefano Zampini PetscFunctionReturn(0); 10148e330a33SStefano Zampini } 10158e330a33SStefano Zampini 10168e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 10178e330a33SStefano Zampini { 10188e330a33SStefano Zampini PetscInt i, numChildren; 10198e330a33SStefano Zampini const PetscInt *children; 10208e330a33SStefano Zampini PetscErrorCode ierr; 10218e330a33SStefano Zampini 10228e330a33SStefano Zampini PetscFunctionBeginHot; 10238e330a33SStefano Zampini ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 10248e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 10258e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, children[i]);CHKERRQ(ierr); 10268e330a33SStefano Zampini } 10278e330a33SStefano Zampini PetscFunctionReturn(0); 10288e330a33SStefano Zampini } 10298e330a33SStefano Zampini 10308e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 10318e330a33SStefano Zampini { 10328e330a33SStefano Zampini const PetscInt *cone; 10338e330a33SStefano Zampini PetscInt coneSize, c; 10348e330a33SStefano Zampini PetscErrorCode ierr; 10358e330a33SStefano Zampini 10368e330a33SStefano Zampini PetscFunctionBeginHot; 10378e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, point);CHKERRQ(ierr); 10388e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, point);CHKERRQ(ierr); 10398e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Down_Private(dm, ht, point);CHKERRQ(ierr); 10408e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 10418e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 10428e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 10438e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, cone[c]);CHKERRQ(ierr); 10448e330a33SStefano Zampini } 10458e330a33SStefano Zampini PetscFunctionReturn(0); 10468e330a33SStefano Zampini } 10478e330a33SStefano Zampini 10488e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 1049825f8a23SLisandro Dalcin { 1050825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10518e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10528e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 105327104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1054825f8a23SLisandro Dalcin PetscErrorCode ierr; 1055825f8a23SLisandro Dalcin 1056825f8a23SLisandro Dalcin PetscFunctionBegin; 1057825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 1058825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 10598e330a33SStefano Zampini if (!hasTree) { 10608e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10618e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, points[p]);CHKERRQ(ierr); 10628e330a33SStefano Zampini } 10638e330a33SStefano Zampini } else { 10648e330a33SStefano Zampini #if 1 10658e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 10668e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, points[p]);CHKERRQ(ierr); 10678e330a33SStefano Zampini } 10688e330a33SStefano Zampini #else 10698e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1070825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 1071825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1072825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 1073825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 1074825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 1075825f8a23SLisandro Dalcin } 1076825f8a23SLisandro Dalcin } 1077825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 10788e330a33SStefano Zampini #endif 10798e330a33SStefano Zampini } 1080825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 1081825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 1082825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 1083825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 1084825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 1085825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 1086825f8a23SLisandro Dalcin PetscFunctionReturn(0); 1087825f8a23SLisandro Dalcin } 1088825f8a23SLisandro Dalcin 10895abbe4feSMichael Lange /*@ 10905abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10915abbe4feSMichael Lange 10925abbe4feSMichael Lange Input Parameters: 10935abbe4feSMichael Lange + dm - The DM 1094a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 10955abbe4feSMichael Lange 10965abbe4feSMichael Lange Level: developer 10975abbe4feSMichael Lange 109830b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 10995abbe4feSMichael Lange @*/ 11005abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 11019ffc88e4SToby Isaac { 1102825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 11035abbe4feSMichael Lange const PetscInt *ranks, *points; 1104825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 11059ffc88e4SToby Isaac PetscErrorCode ierr; 11069ffc88e4SToby Isaac 11079ffc88e4SToby Isaac PetscFunctionBegin; 11085abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 11095abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 11105abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 11115abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 11125abbe4feSMichael Lange const PetscInt rank = ranks[r]; 11135abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 11145abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 11155abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 11168e330a33SStefano Zampini ierr = DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS);CHKERRQ(ierr); 11175abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 11185abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1119825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 1120825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 11219ffc88e4SToby Isaac } 11225abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 11235abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 11249ffc88e4SToby Isaac PetscFunctionReturn(0); 11259ffc88e4SToby Isaac } 11269ffc88e4SToby Isaac 112724d039d7SMichael Lange /*@ 112824d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 112924d039d7SMichael Lange 113024d039d7SMichael Lange Input Parameters: 113124d039d7SMichael Lange + dm - The DM 1132a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 113324d039d7SMichael Lange 113424d039d7SMichael Lange Level: developer 113524d039d7SMichael Lange 11362d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 113724d039d7SMichael Lange @*/ 113824d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 113970034214SMatthew G. Knepley { 114024d039d7SMichael Lange IS rankIS, pointIS; 114124d039d7SMichael Lange const PetscInt *ranks, *points; 114224d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 114324d039d7SMichael Lange PetscInt *adj = NULL; 114470034214SMatthew G. Knepley PetscErrorCode ierr; 114570034214SMatthew G. Knepley 114670034214SMatthew G. Knepley PetscFunctionBegin; 114724d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 114824d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 114924d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 115024d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 115124d039d7SMichael Lange const PetscInt rank = ranks[r]; 115270034214SMatthew G. Knepley 115324d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 115424d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 115524d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 115670034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 115724d039d7SMichael Lange adjSize = PETSC_DETERMINE; 115824d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 115924d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 116070034214SMatthew G. Knepley } 116124d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 116224d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 116370034214SMatthew G. Knepley } 116424d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 116524d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 116624d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 116724d039d7SMichael Lange PetscFunctionReturn(0); 116870034214SMatthew G. Knepley } 116970034214SMatthew G. Knepley 1170be200f8dSMichael Lange /*@ 1171be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1172be200f8dSMichael Lange 1173be200f8dSMichael Lange Input Parameters: 1174be200f8dSMichael Lange + dm - The DM 1175a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1176be200f8dSMichael Lange 1177be200f8dSMichael Lange Level: developer 1178be200f8dSMichael Lange 1179be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1180be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1181be200f8dSMichael Lange 11822d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 1183be200f8dSMichael Lange @*/ 1184be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1185be200f8dSMichael Lange { 1186be200f8dSMichael Lange MPI_Comm comm; 1187be200f8dSMichael Lange PetscMPIInt rank; 1188be200f8dSMichael Lange PetscSF sfPoint; 11895d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1190be200f8dSMichael Lange IS rankIS, pointIS; 1191be200f8dSMichael Lange const PetscInt *ranks; 1192be200f8dSMichael Lange PetscInt numRanks, r; 1193be200f8dSMichael Lange PetscErrorCode ierr; 1194be200f8dSMichael Lange 1195be200f8dSMichael Lange PetscFunctionBegin; 1196be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1197ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1198be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 11995d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 12005d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 12015d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 12025d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 12035d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 12045d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 12055d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 12065d04f6ebSMichael Lange if (remoteRank == rank) continue; 12075d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 12085d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 12095d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12105d04f6ebSMichael Lange } 12115d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 12125d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 12135d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 1214be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 1215be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 1216be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 1217be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 1218be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 1219be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1220be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1221be200f8dSMichael Lange if (remoteRank == rank) continue; 1222be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 1223be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 1224be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1225be200f8dSMichael Lange } 1226be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 1227be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 1228be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 1229be200f8dSMichael Lange PetscFunctionReturn(0); 1230be200f8dSMichael Lange } 1231be200f8dSMichael Lange 12321fd9873aSMichael Lange /*@ 12331fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 12341fd9873aSMichael Lange 12351fd9873aSMichael Lange Input Parameters: 12361fd9873aSMichael Lange + dm - The DM 1237a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots 1238fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 12391fd9873aSMichael Lange 12401fd9873aSMichael Lange Output Parameter: 1241a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots 12421fd9873aSMichael Lange 12431fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 12441fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 12451fd9873aSMichael Lange 12461fd9873aSMichael Lange Level: developer 12471fd9873aSMichael Lange 12482d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 12491fd9873aSMichael Lange @*/ 12501fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 12511fd9873aSMichael Lange { 12521fd9873aSMichael Lange MPI_Comm comm; 1253874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1254874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12551fd9873aSMichael Lange PetscSF sfPoint; 1256874ddda9SLisandro Dalcin PetscSection rootSection; 12571fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12581fd9873aSMichael Lange const PetscSFNode *remote; 12591fd9873aSMichael Lange const PetscInt *local, *neighbors; 12601fd9873aSMichael Lange IS valueIS; 1261874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12621fd9873aSMichael Lange PetscErrorCode ierr; 12631fd9873aSMichael Lange 12641fd9873aSMichael Lange PetscFunctionBegin; 126530b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 12661fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1267ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1268ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 12691fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 12701fd9873aSMichael Lange 12711fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 12721fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 12739852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 12741fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 12751fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 12761fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 12771fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12781fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 12791fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 12801fd9873aSMichael Lange } 12811fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 1282874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 1283874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 12841fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 12851fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12861fd9873aSMichael Lange IS pointIS; 12871fd9873aSMichael Lange const PetscInt *points; 12881fd9873aSMichael Lange 12891fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 12901fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 12911fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 12921fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 12931fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1294f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1295f8987ae8SMichael Lange else {l = -1;} 12961fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 12971fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 12981fd9873aSMichael Lange } 12991fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 13001fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 13011fd9873aSMichael Lange } 1302874ddda9SLisandro Dalcin 1303874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1304874ddda9SLisandro Dalcin if (!processSF) { 1305874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1306874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1307874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1308874ddda9SLisandro Dalcin 1309874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 1310874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 1311874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 1312874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 1313874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 1314874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1315874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1316874ddda9SLisandro Dalcin #endif 1317874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 1318874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 1319874ddda9SLisandro Dalcin } 1320ffc4695bSBarry Smith ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRMPI(ierr); 1321874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 1322874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 1323ffc4695bSBarry Smith ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRMPI(ierr); 1324874ddda9SLisandro Dalcin if (!mpiOverflow) { 132594b10faeSStefano Zampini ierr = PetscInfo(dm,"Using Alltoallv for mesh distribution\n");CHKERRQ(ierr); 1326874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 1327874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 1328ffc4695bSBarry Smith ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRMPI(ierr); 1329874ddda9SLisandro Dalcin } 1330874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 1331874ddda9SLisandro Dalcin } 1332874ddda9SLisandro Dalcin 1333874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1334874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1335874ddda9SLisandro Dalcin PetscSF procSF; 1336874ddda9SLisandro Dalcin PetscSection leafSection; 1337874ddda9SLisandro Dalcin 1338874ddda9SLisandro Dalcin if (processSF) { 133994b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution\n");CHKERRQ(ierr); 1340874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 1341874ddda9SLisandro Dalcin procSF = processSF; 1342874ddda9SLisandro Dalcin } else { 134394b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n");CHKERRQ(ierr); 1344874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm,&procSF);CHKERRQ(ierr); 1345900e0f05SJunchao Zhang ierr = PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr); 1346874ddda9SLisandro Dalcin } 1347874ddda9SLisandro Dalcin 1348874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 1349900e0f05SJunchao Zhang ierr = DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 1350874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 1351874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 1352874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 1353874ddda9SLisandro Dalcin } 1354874ddda9SLisandro Dalcin 1355874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 13561fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 13571fd9873aSMichael Lange } 1358874ddda9SLisandro Dalcin 1359874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 1360874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 13611fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 1362874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 13631fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 136430b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 13651fd9873aSMichael Lange PetscFunctionReturn(0); 13661fd9873aSMichael Lange } 13671fd9873aSMichael Lange 1368aa3148a8SMichael Lange /*@ 1369aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1370aa3148a8SMichael Lange 1371aa3148a8SMichael Lange Input Parameters: 1372aa3148a8SMichael Lange + dm - The DM 1373a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1374aa3148a8SMichael Lange 1375aa3148a8SMichael Lange Output Parameter: 1376fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1377aa3148a8SMichael Lange 1378aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1379aa3148a8SMichael Lange 1380aa3148a8SMichael Lange Level: developer 1381aa3148a8SMichael Lange 138230b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 1383aa3148a8SMichael Lange @*/ 1384aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1385aa3148a8SMichael Lange { 13866e203dd9SStefano Zampini PetscMPIInt rank; 13876e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1388aa3148a8SMichael Lange PetscSFNode *remotePoints; 13896e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13906e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1391aa3148a8SMichael Lange PetscErrorCode ierr; 1392aa3148a8SMichael Lange 1393aa3148a8SMichael Lange PetscFunctionBegin; 139430b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 1395ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1396aa3148a8SMichael Lange 13976e203dd9SStefano Zampini ierr = DMLabelGetValueIS(label, &neighborsIS);CHKERRQ(ierr); 13986e203dd9SStefano Zampini #if 0 13996e203dd9SStefano Zampini { 14006e203dd9SStefano Zampini IS is; 14016e203dd9SStefano Zampini ierr = ISDuplicate(neighborsIS, &is);CHKERRQ(ierr); 14026e203dd9SStefano Zampini ierr = ISSort(is);CHKERRQ(ierr); 14036e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 14046e203dd9SStefano Zampini neighborsIS = is; 14056e203dd9SStefano Zampini } 14066e203dd9SStefano Zampini #endif 14076e203dd9SStefano Zampini ierr = ISGetLocalSize(neighborsIS, &nNeighbors);CHKERRQ(ierr); 14086e203dd9SStefano Zampini ierr = ISGetIndices(neighborsIS, &neighbors);CHKERRQ(ierr); 14096e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 14106e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, neighbors[n], &numPoints);CHKERRQ(ierr); 1411aa3148a8SMichael Lange numRemote += numPoints; 1412aa3148a8SMichael Lange } 1413aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 141443f7d02bSMichael Lange /* Put owned points first */ 141543f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 141643f7d02bSMichael Lange if (numPoints > 0) { 141743f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 141843f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 141943f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 142043f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 142143f7d02bSMichael Lange remotePoints[idx].rank = rank; 142243f7d02bSMichael Lange idx++; 142343f7d02bSMichael Lange } 142443f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 142543f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 142643f7d02bSMichael Lange } 142743f7d02bSMichael Lange /* Now add remote points */ 14286e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 14296e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 14306e203dd9SStefano Zampini 14316e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, nn, &numPoints);CHKERRQ(ierr); 14326e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 14336e203dd9SStefano Zampini ierr = DMLabelGetStratumIS(label, nn, &remoteRootIS);CHKERRQ(ierr); 1434aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1435aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1436aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 14376e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1438aa3148a8SMichael Lange idx++; 1439aa3148a8SMichael Lange } 1440aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1441aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1442aa3148a8SMichael Lange } 1443aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1444aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1445aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 144630b0ce1bSStefano Zampini ierr = PetscSFSetUp(*sf);CHKERRQ(ierr); 14476e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 144830b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 144970034214SMatthew G. Knepley PetscFunctionReturn(0); 145070034214SMatthew G. Knepley } 1451cb87ef4cSFlorian Wechsung 1452abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1453abe9303eSLisandro Dalcin #include <parmetis.h> 1454abe9303eSLisandro Dalcin #endif 1455abe9303eSLisandro Dalcin 14566a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14576a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14586a3739e5SFlorian Wechsung * them out in that case. */ 14596a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 14607a82c785SFlorian Wechsung /*@C 14617f57c1a4SFlorian Wechsung 14627f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 14637f57c1a4SFlorian Wechsung 14647f57c1a4SFlorian Wechsung Input parameters: 14657f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1466fe2efc57SMark . n - The number of points. 1467fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1468fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1469fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 14707f57c1a4SFlorian Wechsung 14717f57c1a4SFlorian Wechsung Level: developer 14727f57c1a4SFlorian Wechsung 14737f57c1a4SFlorian Wechsung @*/ 14747f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 14757f57c1a4SFlorian Wechsung { 14767f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14777f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14787f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14797f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14807f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14817f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14827f57c1a4SFlorian Wechsung PetscSF sf; 14837f57c1a4SFlorian Wechsung MPI_Comm comm; 14845a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14857f57c1a4SFlorian Wechsung 14867f57c1a4SFlorian Wechsung PetscFunctionBegin; 14877f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1488ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1489ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 14907f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 14917f57c1a4SFlorian Wechsung 14927f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 14937f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr); 14947f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 14957f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14967f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 14977f57c1a4SFlorian Wechsung } 14987f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 14997f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 15007f57c1a4SFlorian Wechsung } 15017f57c1a4SFlorian Wechsung 15027f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 15037f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 15047f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 15057f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 15067f57c1a4SFlorian Wechsung } 15077f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 15087f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 15097f57c1a4SFlorian Wechsung 15107f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 15117f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 15127f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15137f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 15147f57c1a4SFlorian Wechsung } 15157f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 15167f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 15177f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 15187f57c1a4SFlorian Wechsung 15197f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 15207f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 15217f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 15227f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15237f57c1a4SFlorian Wechsung points[i] = pStart+i; 15247f57c1a4SFlorian Wechsung } 15257f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 15267f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 15277f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 15287f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 15297f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 15307f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 15317f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15327f57c1a4SFlorian Wechsung newOwners[i] = -1; 15337f57c1a4SFlorian Wechsung newNumbers[i] = -1; 15347f57c1a4SFlorian Wechsung } 15357f57c1a4SFlorian Wechsung { 15367f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 15377f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 15387f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 15397f57c1a4SFlorian Wechsung newNumber = -1; 15407f57c1a4SFlorian Wechsung oldOwner = rank; 15417f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 15427f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 15437f57c1a4SFlorian Wechsung newNumber = oldNumber; 15447f57c1a4SFlorian Wechsung } else { 15457f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 15467f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 15477f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 15487f57c1a4SFlorian Wechsung break; 15497f57c1a4SFlorian Wechsung } 15507f57c1a4SFlorian Wechsung } 15517f57c1a4SFlorian Wechsung } 15529ace16cdSJacob Faibussowitsch PetscAssertFalse(newNumber == -1,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 15537f57c1a4SFlorian Wechsung 15547f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 15557f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 15567f57c1a4SFlorian Wechsung } 15577f57c1a4SFlorian Wechsung } 15587f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 15597f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 15607f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 15617f57c1a4SFlorian Wechsung 1562ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE);CHKERRQ(ierr); 1563ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE);CHKERRQ(ierr); 1564ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE);CHKERRQ(ierr); 1565ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE);CHKERRQ(ierr); 15667f57c1a4SFlorian Wechsung 15677f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15687f57c1a4SFlorian Wechsung leafCounter=0; 15697f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15707f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15717f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15727f57c1a4SFlorian Wechsung leafCounter++; 15737f57c1a4SFlorian Wechsung } 15747f57c1a4SFlorian Wechsung } else { 15757f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15767f57c1a4SFlorian Wechsung leafCounter++; 15777f57c1a4SFlorian Wechsung } 15787f57c1a4SFlorian Wechsung } 15797f57c1a4SFlorian Wechsung } 15807f57c1a4SFlorian Wechsung 15817f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 15827f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 15837f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 15847f57c1a4SFlorian Wechsung 15857f57c1a4SFlorian Wechsung leafCounter = 0; 15867f57c1a4SFlorian Wechsung counter = 0; 15877f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15887f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15897f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15907f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15917f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15927f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15937f57c1a4SFlorian Wechsung leafCounter++; 15947f57c1a4SFlorian Wechsung } 15957f57c1a4SFlorian Wechsung } else { 15967f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15977f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15987f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15997f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 16007f57c1a4SFlorian Wechsung leafCounter++; 16017f57c1a4SFlorian Wechsung } 16027f57c1a4SFlorian Wechsung } 16037f57c1a4SFlorian Wechsung if (isLeaf[i]) { 16047f57c1a4SFlorian Wechsung counter++; 16057f57c1a4SFlorian Wechsung } 16067f57c1a4SFlorian Wechsung } 16077f57c1a4SFlorian Wechsung 16087f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 16097f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 16107f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 16117f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 16127f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 16137f57c1a4SFlorian Wechsung } 16147f57c1a4SFlorian Wechsung 1615125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1616125d2a8fSFlorian Wechsung { 16175a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 16185a30b08bSFlorian Wechsung PetscMPIInt rank, size; 1619125d2a8fSFlorian Wechsung PetscFunctionBegin; 1620ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1621ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1622125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 1623125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 1624125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 1625125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 1626125d2a8fSFlorian Wechsung } 1627ffc4695bSBarry Smith ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRMPI(ierr); 1628125d2a8fSFlorian Wechsung min = distribution[0]; 1629125d2a8fSFlorian Wechsung max = distribution[0]; 1630125d2a8fSFlorian Wechsung sum = distribution[0]; 1631125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 1632125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 1633125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 1634125d2a8fSFlorian Wechsung sum += distribution[i]; 1635125d2a8fSFlorian Wechsung } 1636125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 1637125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 1638125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1639125d2a8fSFlorian Wechsung } 1640125d2a8fSFlorian Wechsung 16416a3739e5SFlorian Wechsung #endif 16426a3739e5SFlorian Wechsung 1643cb87ef4cSFlorian Wechsung /*@ 16445dc86ac1SFlorian Wechsung DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace. 1645cb87ef4cSFlorian Wechsung 1646cb87ef4cSFlorian Wechsung Input parameters: 1647ed44d270SFlorian Wechsung + dm - The DMPlex object. 1648fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1649fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1650fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1651cb87ef4cSFlorian Wechsung 16528b879b41SFlorian Wechsung Output parameters: 1653fe2efc57SMark . success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 16548b879b41SFlorian Wechsung 165590ea27d8SSatish Balay Level: intermediate 1656cb87ef4cSFlorian Wechsung 1657cb87ef4cSFlorian Wechsung @*/ 1658cb87ef4cSFlorian Wechsung 16598b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1660cb87ef4cSFlorian Wechsung { 166141525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1662cb87ef4cSFlorian Wechsung PetscSF sf; 16630faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16647f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16657f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16667f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1667cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1668cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1669cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16707f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16715dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1672cb87ef4cSFlorian Wechsung PetscInt offset, counter; 16737f57c1a4SFlorian Wechsung PetscInt lenadjncy; 1674cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 1675cb87ef4cSFlorian Wechsung PetscInt lenxadj; 1676cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 1677cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1678cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1679cb87ef4cSFlorian Wechsung real_t *ubvec; 1680cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1681cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1682cb87ef4cSFlorian Wechsung MPI_Comm comm; 16834baf1206SFlorian Wechsung Mat A, Apre; 168412617df9SFlorian Wechsung const char *prefix = NULL; 16857d197802SFlorian Wechsung PetscViewer viewer; 16867d197802SFlorian Wechsung PetscViewerFormat format; 16875a30b08bSFlorian Wechsung PetscLayout layout; 168812617df9SFlorian Wechsung 168912617df9SFlorian Wechsung PetscFunctionBegin; 16908b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 16917f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1692ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1693ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 16947f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 16957f57c1a4SFlorian Wechsung 169641525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 169741525646SFlorian Wechsung 16985a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 16995dc86ac1SFlorian Wechsung if (viewer) { 17005a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 17017d197802SFlorian Wechsung } 17027d197802SFlorian Wechsung 1703ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 1704d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 1705cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1706cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 1707cf818975SFlorian Wechsung 1708cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17095a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 1710cb87ef4cSFlorian Wechsung } 1711cb87ef4cSFlorian Wechsung 1712cf818975SFlorian Wechsung /* There are three types of points: 1713cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1714cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1715cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1716cf818975SFlorian Wechsung */ 1717cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 1718cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr); 1719cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 1720cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 1721cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 1722cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1723cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1724cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1725cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1726cb87ef4cSFlorian Wechsung } 1727cf818975SFlorian Wechsung 1728cf818975SFlorian Wechsung /* start by marking all the leafs */ 1729cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 1730cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 1731cb87ef4cSFlorian Wechsung } 1732cb87ef4cSFlorian Wechsung 1733cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1734cf818975SFlorian Wechsung * not by calculating its degree */ 17357f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 17367f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 1737cf818975SFlorian Wechsung 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 1754cf818975SFlorian Wechsung /* We are going to 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. */ 1757cb87ef4cSFlorian Wechsung 17585dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 17595dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 17605dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 17615dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 17625dc86ac1SFlorian Wechsung 1763cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 17645a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 1765cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1766cb87ef4cSFlorian Wechsung counter = 0; 1767cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1768cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17697f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1770cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1771cb87ef4cSFlorian Wechsung counter++; 1772cb87ef4cSFlorian Wechsung } 1773cb87ef4cSFlorian Wechsung } 1774cb87ef4cSFlorian Wechsung } 1775cb87ef4cSFlorian Wechsung 1776cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 1777cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 1778ad227feaSJunchao Zhang ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE);CHKERRQ(ierr); 1779ad227feaSJunchao Zhang ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE);CHKERRQ(ierr); 1780cb87ef4cSFlorian Wechsung 17810faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 1782cb87ef4cSFlorian Wechsung 17834baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 17844baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 17854baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 17864baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 17878c9a1619SFlorian Wechsung 17888c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17898c9a1619SFlorian Wechsung if (toBalance[i]) { 17900faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17910faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17920faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17930faf6628SFlorian Wechsung else continue; 17940faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 17950faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 17964baf1206SFlorian Wechsung } 17974baf1206SFlorian Wechsung } 17984baf1206SFlorian Wechsung 17994baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 18004baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 18014baf1206SFlorian Wechsung 18024baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 18034baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 18044baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 18054baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 18064baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 18074baf1206SFlorian Wechsung 18084baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 18094baf1206SFlorian Wechsung if (toBalance[i]) { 18100faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 18110faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 18120faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 18130faf6628SFlorian Wechsung else continue; 18140faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 18150faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 18160941debbSFlorian Wechsung } 18170941debbSFlorian Wechsung } 18188c9a1619SFlorian Wechsung 18198c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 18208c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 18214baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 18224baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 18234baf1206SFlorian Wechsung 182441525646SFlorian Wechsung nparts = size; 182541525646SFlorian Wechsung wgtflag = 2; 182641525646SFlorian Wechsung numflag = 0; 182741525646SFlorian Wechsung ncon = 2; 182841525646SFlorian Wechsung real_t *tpwgts; 182941525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 183041525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 183141525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 183241525646SFlorian Wechsung } 183341525646SFlorian Wechsung 183441525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 183541525646SFlorian Wechsung ubvec[0] = 1.01; 18365a30b08bSFlorian Wechsung ubvec[1] = 1.01; 18378c9a1619SFlorian Wechsung lenadjncy = 0; 18388c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18398c9a1619SFlorian Wechsung PetscInt temp=0; 18408c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 18418c9a1619SFlorian Wechsung lenadjncy += temp; 18428c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 18438c9a1619SFlorian Wechsung } 18448c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 18457407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 18460941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 18470941debbSFlorian Wechsung xadj[0] = 0; 18488c9a1619SFlorian Wechsung counter = 0; 18498c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18502953a68cSFlorian Wechsung PetscInt temp=0; 18512953a68cSFlorian Wechsung const PetscInt *cols; 18528c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 1853580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy[counter], cols, temp);CHKERRQ(ierr); 18548c9a1619SFlorian Wechsung counter += temp; 18550941debbSFlorian Wechsung xadj[i+1] = counter; 18568c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 18578c9a1619SFlorian Wechsung } 18588c9a1619SFlorian Wechsung 1859cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 186041525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 186141525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 186241525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 186341525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 186441525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 186541525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 186641525646SFlorian Wechsung } 18678c9a1619SFlorian Wechsung 18685dc86ac1SFlorian Wechsung if (viewer) { 18697d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 18707d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 187112617df9SFlorian Wechsung } 187241525646SFlorian Wechsung if (parallel) { 18735a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 18745a30b08bSFlorian Wechsung options[0] = 1; 18755a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 18765a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18775a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 18785dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 18798c9a1619SFlorian Wechsung if (useInitialGuess) { 18805dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 18818c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 18825dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 18839ace16cdSJacob Faibussowitsch PetscAssertFalse(ierr != METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18848c9a1619SFlorian Wechsung PetscStackPop; 18858c9a1619SFlorian Wechsung } else { 18868c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 18875dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 18888c9a1619SFlorian Wechsung PetscStackPop; 18899ace16cdSJacob Faibussowitsch PetscAssertFalse(ierr != METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18908c9a1619SFlorian Wechsung } 1891ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 189241525646SFlorian Wechsung } else { 18935dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 189441525646SFlorian Wechsung Mat As; 189541525646SFlorian Wechsung PetscInt numRows; 189641525646SFlorian Wechsung PetscInt *partGlobal; 189741525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 1898cb87ef4cSFlorian Wechsung 189941525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 190041525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 190141525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 1902ffc4695bSBarry Smith ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRMPI(ierr); 1903cb87ef4cSFlorian Wechsung 190441525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 190541525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 1906dd400576SPatrick Sanan if (rank == 0) { 190741525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 190841525646SFlorian Wechsung lenadjncy = 0; 190941525646SFlorian Wechsung 191041525646SFlorian Wechsung for (i=0; i<numRows; i++) { 191141525646SFlorian Wechsung PetscInt temp=0; 191241525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 191341525646SFlorian Wechsung lenadjncy += temp; 191441525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 191541525646SFlorian Wechsung } 191641525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 191741525646SFlorian Wechsung lenxadj = 1 + numRows; 191841525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 191941525646SFlorian Wechsung xadj_g[0] = 0; 192041525646SFlorian Wechsung counter = 0; 192141525646SFlorian Wechsung for (i=0; i<numRows; i++) { 19222953a68cSFlorian Wechsung PetscInt temp=0; 19232953a68cSFlorian Wechsung const PetscInt *cols; 192441525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 1925580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy_g[counter], cols, temp);CHKERRQ(ierr); 192641525646SFlorian Wechsung counter += temp; 192741525646SFlorian Wechsung xadj_g[i+1] = counter; 192841525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 192941525646SFlorian Wechsung } 193041525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 193141525646SFlorian Wechsung for (i=0; i<size; i++) { 193241525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 193341525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 193441525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 193541525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 193641525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 193741525646SFlorian Wechsung } 193841525646SFlorian Wechsung } 193941525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 194041525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 19419ace16cdSJacob Faibussowitsch PetscAssertFalse(ierr != METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 194241525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 194341525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 194406b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 194541525646SFlorian Wechsung PetscStackPop; 19469ace16cdSJacob Faibussowitsch PetscAssertFalse(ierr != METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 1947ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 194841525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 194941525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 195041525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 195141525646SFlorian Wechsung } 195241525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 195341525646SFlorian Wechsung 19545dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 19555dc86ac1SFlorian Wechsung { 195681a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 19575dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 195881a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 19595dc86ac1SFlorian Wechsung for (i=0; i<size; i++) { 196081a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 196141525646SFlorian Wechsung } 196281a13b52SFlorian Wechsung for (i=0; i<=size; i++) { 196381a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 196481a13b52SFlorian Wechsung } 1965ffc4695bSBarry Smith ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRMPI(ierr); 19665dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 196781a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 19685dc86ac1SFlorian Wechsung } 19695dc86ac1SFlorian Wechsung 197041525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 19712953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 197241525646SFlorian Wechsung } 1973cb87ef4cSFlorian Wechsung 19742953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 1975cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 1976cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 1977cb87ef4cSFlorian Wechsung 1978cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1979cb87ef4cSFlorian Wechsung 1980cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 1981cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 1982cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 1983ffc4695bSBarry Smith ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRMPI(ierr); 1984cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 1985cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 1986cb87ef4cSFlorian Wechsung } 1987cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 1988cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 1989cb87ef4cSFlorian Wechsung } 1990cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1991cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 1992ffc4695bSBarry Smith ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRMPI(ierr); 1993cb87ef4cSFlorian Wechsung 19947f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 19957f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 19967f57c1a4SFlorian Wechsung 1997cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 19987f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 19997f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 20007f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 20017f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 20027f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 20037f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 20047f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 20057f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 20067f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 20077f57c1a4SFlorian Wechsung if (viewer) { 200806b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 200906b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 20107f57c1a4SFlorian Wechsung } 20117f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 20128b879b41SFlorian Wechsung PetscFunctionReturn(0); 2013cb87ef4cSFlorian Wechsung } 2014cb87ef4cSFlorian Wechsung 20157407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 20165dc86ac1SFlorian Wechsung if (viewer) { 20177d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth);CHKERRQ(ierr); 2018125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 2019125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 2020125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 2021125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 20227407ba93SFlorian Wechsung } 20237407ba93SFlorian Wechsung 2024cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 202541525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 2026cb87ef4cSFlorian Wechsung PetscInt loc = 0; 202741525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 20287407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 2029cb87ef4cSFlorian Wechsung if (loc<0) { 203041525646SFlorian Wechsung part[i] = rank; 2031cb87ef4cSFlorian Wechsung } 2032cb87ef4cSFlorian Wechsung } 2033cb87ef4cSFlorian Wechsung 20347407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 20355dc86ac1SFlorian Wechsung if (viewer) { 2036125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 2037125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 20387407ba93SFlorian Wechsung } 20397407ba93SFlorian Wechsung 20405dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 2041cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 2042cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 204341525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 2044cb87ef4cSFlorian Wechsung 20457f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 2046cf818975SFlorian Wechsung { 20477f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 204806b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 20497f57c1a4SFlorian Wechsung counter = 0; 2050cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2051cb87ef4cSFlorian Wechsung if (toBalance[i]) { 2052cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 20537f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 2054cb87ef4cSFlorian Wechsung counter++; 2055cb87ef4cSFlorian Wechsung } 2056cb87ef4cSFlorian Wechsung } 2057cb87ef4cSFlorian Wechsung } 20587f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 20597f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 2060cf818975SFlorian Wechsung } 2061cb87ef4cSFlorian Wechsung 2062cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 2063cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 2064cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 2065cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 20667f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 20675dc86ac1SFlorian Wechsung if (viewer) { 206806b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 206906b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 20707d197802SFlorian Wechsung } 20718b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 207241525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 2073b458e8f1SJose E. Roman PetscFunctionReturn(0); 2074240408d3SFlorian Wechsung #else 20755f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 207641525646SFlorian Wechsung #endif 2077cb87ef4cSFlorian Wechsung } 2078