1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h> 3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> 470034214SMatthew G. Knepley 54b876568SBarry Smith const char * const DMPlexCSRAlgorithms[] = {"mat", "graph", "overlap", "DMPlexCSRAlgorithm", "DM_PLEX_CSR_",NULL}; 65a107427SMatthew G. Knepley 79fbee547SJacob Faibussowitsch static inline PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 80134a67bSLisandro Dalcin 95a107427SMatthew G. Knepley static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 105a107427SMatthew G. Knepley { 115a107427SMatthew G. Knepley DM ovdm; 125a107427SMatthew G. Knepley PetscSF sfPoint; 135a107427SMatthew G. Knepley IS cellNumbering; 145a107427SMatthew G. Knepley const PetscInt *cellNum; 155a107427SMatthew G. Knepley PetscInt *adj = NULL, *vOffsets = NULL, *vAdj = NULL; 165a107427SMatthew G. Knepley PetscBool useCone, useClosure; 175a107427SMatthew G. Knepley PetscInt dim, depth, overlap, cStart, cEnd, c, v; 185a107427SMatthew G. Knepley PetscMPIInt rank, size; 195a107427SMatthew G. Knepley 205a107427SMatthew G. Knepley PetscFunctionBegin; 21*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 22*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size)); 23*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 24*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 255a107427SMatthew G. Knepley if (dim != depth) { 265a107427SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 27*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 285a107427SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 29*5f80ce2aSJacob Faibussowitsch if (globalNumbering) CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 305a107427SMatthew G. Knepley /* Different behavior for empty graphs */ 315a107427SMatthew G. Knepley if (!*numVertices) { 32*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1, offsets)); 335a107427SMatthew G. Knepley (*offsets)[0] = 0; 345a107427SMatthew G. Knepley } 355a107427SMatthew G. Knepley /* Broken in parallel */ 36*5f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 375a107427SMatthew G. Knepley PetscFunctionReturn(0); 385a107427SMatthew G. Knepley } 395a107427SMatthew G. Knepley /* Always use FVM adjacency to create partitioner graph */ 40*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 41*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 425a107427SMatthew G. Knepley /* Need overlap >= 1 */ 43*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetOverlap(dm, &overlap)); 445a107427SMatthew G. Knepley if (size && overlap < 1) { 45*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeOverlap(dm, 1, NULL, &ovdm)); 465a107427SMatthew G. Knepley } else { 47*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 485a107427SMatthew G. Knepley ovdm = dm; 495a107427SMatthew G. Knepley } 50*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(ovdm, &sfPoint)); 51*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd)); 52*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering)); 535a107427SMatthew G. Knepley if (globalNumbering) { 54*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) cellNumbering)); 555a107427SMatthew G. Knepley *globalNumbering = cellNumbering; 565a107427SMatthew G. Knepley } 57*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cellNumbering, &cellNum)); 585a107427SMatthew G. Knepley /* Determine sizes */ 595a107427SMatthew G. Knepley for (*numVertices = 0, c = cStart; c < cEnd; ++c) { 605a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 615a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 625a107427SMatthew G. Knepley (*numVertices)++; 635a107427SMatthew G. Knepley } 64*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(*numVertices+1, &vOffsets)); 655a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 665a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0; 675a107427SMatthew G. Knepley 685a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 69*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 705a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 715a107427SMatthew G. Knepley const PetscInt point = adj[a]; 725a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) ++vsize; 735a107427SMatthew G. Knepley } 745a107427SMatthew G. Knepley vOffsets[v+1] = vOffsets[v] + vsize; 755a107427SMatthew G. Knepley ++v; 765a107427SMatthew G. Knepley } 775a107427SMatthew G. Knepley /* Determine adjacency */ 78*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(vOffsets[*numVertices], &vAdj)); 795a107427SMatthew G. Knepley for (c = cStart, v = 0; c < cEnd; ++c) { 805a107427SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v]; 815a107427SMatthew G. Knepley 825a107427SMatthew G. Knepley /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 835a107427SMatthew G. Knepley if (cellNum[c] < 0) continue; 84*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(ovdm, c, &adjSize, &adj)); 855a107427SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 865a107427SMatthew G. Knepley const PetscInt point = adj[a]; 875a107427SMatthew G. Knepley if (point != c && cStart <= point && point < cEnd) { 885a107427SMatthew G. Knepley vAdj[off++] = DMPlex_GlobalID(cellNum[point]); 895a107427SMatthew G. Knepley } 905a107427SMatthew G. Knepley } 91*5f80ce2aSJacob Faibussowitsch PetscCheck(off == vOffsets[v+1],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %D should be %D", off, vOffsets[v+1]); 925a107427SMatthew G. Knepley /* Sort adjacencies (not strictly necessary) */ 93*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(off-vOffsets[v], &vAdj[vOffsets[v]])); 945a107427SMatthew G. Knepley ++v; 955a107427SMatthew G. Knepley } 96*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 97*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cellNumbering, &cellNum)); 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellNumbering)); 99*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, useCone, useClosure)); 100*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&ovdm)); 1015a107427SMatthew G. Knepley if (offsets) {*offsets = vOffsets;} 102*5f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscFree(vOffsets)); 1035a107427SMatthew G. Knepley if (adjacency) {*adjacency = vAdj;} 104*5f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscFree(vAdj)); 1055a107427SMatthew G. Knepley PetscFunctionReturn(0); 1065a107427SMatthew G. Knepley } 1075a107427SMatthew G. Knepley 108bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 109532c4e7dSMichael Lange { 110ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 111389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 1128cfe4c1fSMichael Lange IS cellNumbering; 1138cfe4c1fSMichael Lange const PetscInt *cellNum; 114532c4e7dSMichael Lange PetscBool useCone, useClosure; 115532c4e7dSMichael Lange PetscSection section; 116532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 1178cfe4c1fSMichael Lange PetscSF sfPoint; 1188f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 1198f4e72b9SMatthew G. Knepley const PetscInt *local; 1208f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 121532c4e7dSMichael Lange PetscMPIInt rank; 122532c4e7dSMichael Lange 123532c4e7dSMichael Lange PetscFunctionBegin; 124*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 125*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 126*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 127ffbd6163SMatthew G. Knepley if (dim != depth) { 128ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 129*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 130ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 131*5f80ce2aSJacob Faibussowitsch if (globalNumbering) CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 132ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 133ffbd6163SMatthew G. Knepley if (!*numVertices) { 134*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1, offsets)); 135ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 136ffbd6163SMatthew G. Knepley } 137ffbd6163SMatthew G. Knepley /* Broken in parallel */ 138*5f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 139ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 140ffbd6163SMatthew G. Knepley } 141*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 142*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, height, &pStart, &pEnd)); 143532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 144*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion)); 145*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(section, pStart, pEnd)); 146*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer)); 147532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 148*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 149*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 150*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering)); 1513fa7752dSToby Isaac if (globalNumbering) { 152*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)cellNumbering)); 1533fa7752dSToby Isaac *globalNumbering = cellNumbering; 1543fa7752dSToby Isaac } 155*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cellNumbering, &cellNum)); 1568f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 1578f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 1588f4e72b9SMatthew G. Knepley */ 159*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL)); 1608f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1618f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1628f4e72b9SMatthew G. Knepley 163*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(nroots, &adjCells, nroots, &remoteCells)); 164*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd)); 1658f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1668f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1678f4e72b9SMatthew G. Knepley const PetscInt *support; 1688f4e72b9SMatthew G. Knepley PetscInt supportSize; 1698f4e72b9SMatthew G. Knepley 170*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, f, &support)); 171*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, f, &supportSize)); 1720134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1738f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 174*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(support[0], nleaves, local, &p)); 1750134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 176*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(support[1], nleaves, local, &p)); 1770134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1780134a67bSLisandro Dalcin } 1790134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1800134a67bSLisandro Dalcin if (supportSize > 2) { 1810134a67bSLisandro Dalcin PetscInt numChildren, i; 1820134a67bSLisandro Dalcin const PetscInt *children; 1830134a67bSLisandro Dalcin 184*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm, f, &numChildren, &children)); 1850134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1860134a67bSLisandro Dalcin const PetscInt child = children[i]; 1870134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 188*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, child, &support)); 189*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, child, &supportSize)); 1900134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1910134a67bSLisandro Dalcin else if (supportSize == 2) { 192*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(support[0], nleaves, local, &p)); 1930134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 194*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(support[1], nleaves, local, &p)); 1950134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1960134a67bSLisandro Dalcin } 1970134a67bSLisandro Dalcin } 1980134a67bSLisandro Dalcin } 1998f4e72b9SMatthew G. Knepley } 2008f4e72b9SMatthew G. Knepley } 2018f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 202*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE)); 203*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE)); 204*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 205*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX)); 2068f4e72b9SMatthew G. Knepley } 2078f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 2088cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 2098cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 2108cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 2118f4e72b9SMatthew G. Knepley /* Add remote cells */ 2128f4e72b9SMatthew G. Knepley if (remoteCells) { 2130134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 2140134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 2150134a67bSLisandro Dalcin const PetscInt *cone, *children; 2160134a67bSLisandro Dalcin 217*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, p, &cone)); 218*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 2198f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 2200134a67bSLisandro Dalcin const PetscInt point = cone[c]; 2210134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 2228f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 223*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(section, p, 1)); 224*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2250134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 2260134a67bSLisandro Dalcin } 2270134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 228*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 2290134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 2300134a67bSLisandro Dalcin const PetscInt child = children[i]; 2310134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 2320134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 233*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(section, p, 1)); 234*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2350134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 2360134a67bSLisandro Dalcin } 2378f4e72b9SMatthew G. Knepley } 2388f4e72b9SMatthew G. Knepley } 2398f4e72b9SMatthew G. Knepley } 2408f4e72b9SMatthew G. Knepley /* Add local cells */ 241532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 242*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 243532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 244532c4e7dSMichael Lange const PetscInt point = adj[a]; 245532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 246532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 247*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(section, p, 1)); 248*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2490134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 250532c4e7dSMichael Lange } 251532c4e7dSMichael Lange } 2528cfe4c1fSMichael Lange (*numVertices)++; 253532c4e7dSMichael Lange } 254*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 255*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(adjCells, remoteCells)); 256*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dm, useCone, useClosure)); 2574e468a93SLisandro Dalcin 258532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 259*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(section)); 260*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(section, &size)); 261*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(*numVertices+1, &vOffsets)); 26243f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 26343f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 264*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 26543f7d02bSMichael Lange } 266532c4e7dSMichael Lange vOffsets[*numVertices] = size; 267*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2684e468a93SLisandro Dalcin 2694e468a93SLisandro Dalcin if (nroots >= 0) { 2704e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 271*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionReset(section)); 272*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(section, 0, *numVertices)); 2734e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2744e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2754e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 276*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortRemoveDupsInt(&numEdges, &graph[start])); 277*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(section, p, numEdges)); 278*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferGetInts(adjBuffer, numEdges, &edges)); 279*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(edges, &graph[start], numEdges)); 2804e468a93SLisandro Dalcin } 281*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vOffsets)); 282*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(graph)); 2834e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 284*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(section)); 285*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(section, &size)); 286*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(*numVertices+1, &vOffsets)); 2874e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 288*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &(vOffsets[idx++]))); 2894e468a93SLisandro Dalcin } 2904e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 291*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferExtractAlloc(adjBuffer, &graph)); 2924e468a93SLisandro Dalcin } else { 2934e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2944e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2954e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 296*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(end-start, &graph[start])); 2974e468a93SLisandro Dalcin } 2984e468a93SLisandro Dalcin } 2994e468a93SLisandro Dalcin 3004e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 301389e55d8SMichael Lange if (adjacency) *adjacency = graph; 3024e468a93SLisandro Dalcin 303532c4e7dSMichael Lange /* Cleanup */ 304*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSegBufferDestroy(&adjBuffer)); 305*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(§ion)); 306*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cellNumbering, &cellNum)); 307*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellNumbering)); 308532c4e7dSMichael Lange PetscFunctionReturn(0); 309532c4e7dSMichael Lange } 310532c4e7dSMichael Lange 311bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 312bbbc8e51SStefano Zampini { 313bbbc8e51SStefano Zampini Mat conn, CSR; 314bbbc8e51SStefano Zampini IS fis, cis, cis_own; 315bbbc8e51SStefano Zampini PetscSF sfPoint; 316bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 317bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 31883c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 319bbbc8e51SStefano Zampini PetscMPIInt rank; 320bbbc8e51SStefano Zampini PetscBool flg; 321bbbc8e51SStefano Zampini 322bbbc8e51SStefano Zampini PetscFunctionBegin; 323*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 324*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 325*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 326bbbc8e51SStefano Zampini if (dim != depth) { 327bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 328*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency)); 329bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 330*5f80ce2aSJacob Faibussowitsch if (globalNumbering) CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering)); 331bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 332bbbc8e51SStefano Zampini if (!*numVertices) { 333*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1, offsets)); 334bbbc8e51SStefano Zampini (*offsets)[0] = 0; 335bbbc8e51SStefano Zampini } 336bbbc8e51SStefano Zampini /* Broken in parallel */ 337*5f80ce2aSJacob Faibussowitsch if (rank) PetscCheck(!*numVertices,PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 338bbbc8e51SStefano Zampini PetscFunctionReturn(0); 339bbbc8e51SStefano Zampini } 340bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 341bbbc8e51SStefano Zampini 342bbbc8e51SStefano Zampini /* numbering */ 343*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 344*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 345*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd)); 346*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis)); 347*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis)); 348bbbc8e51SStefano Zampini if (globalNumbering) { 349*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDuplicate(cis, globalNumbering)); 350bbbc8e51SStefano Zampini } 351bbbc8e51SStefano Zampini 352bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 353*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(fis, &m)); 354*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(fis, &rows)); 355*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m, &idxs)); 356bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 357bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 358bbbc8e51SStefano Zampini 359bbbc8e51SStefano Zampini if (p < 0) { 360bbbc8e51SStefano Zampini idxs[i] = -(p+1); 361bbbc8e51SStefano Zampini } else { 362bbbc8e51SStefano Zampini idxs[i] = p; 363bbbc8e51SStefano Zampini floc += 1; 364bbbc8e51SStefano Zampini } 365bbbc8e51SStefano Zampini } 366*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(fis, &rows)); 367*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&fis)); 368*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis)); 369bbbc8e51SStefano Zampini 370*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(cis, &m)); 371*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cis, &cols)); 372*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m, &idxs)); 373*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(m, &idxs2)); 374bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 375bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 376bbbc8e51SStefano Zampini 377bbbc8e51SStefano Zampini if (p < 0) { 378bbbc8e51SStefano Zampini idxs[i] = -(p+1); 379bbbc8e51SStefano Zampini } else { 380bbbc8e51SStefano Zampini idxs[i] = p; 381bbbc8e51SStefano Zampini idxs2[cloc++] = p; 382bbbc8e51SStefano Zampini } 383bbbc8e51SStefano Zampini } 384*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cis, &cols)); 385*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cis)); 386*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis)); 387*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own)); 388bbbc8e51SStefano Zampini 389bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 390*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)dm), &conn)); 391*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(conn, floc, cloc, M, N)); 392*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(conn, MATMPIAIJ)); 393*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMaxSizes(dm, NULL, &lm)); 394*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm))); 395*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL)); 396bbbc8e51SStefano Zampini 397bbbc8e51SStefano Zampini /* Assemble matrix */ 398*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(fis, &rows)); 399*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cis, &cols)); 400bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 401bbbc8e51SStefano Zampini const PetscInt *cone; 402bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 403bbbc8e51SStefano Zampini 404bbbc8e51SStefano Zampini col = cols[c-cStart]; 405*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, c, &cone)); 406*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize)); 407bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 408bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 409bbbc8e51SStefano Zampini const PetscInt *children; 410bbbc8e51SStefano Zampini PetscInt numChildren, ch; 411bbbc8e51SStefano Zampini 412bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 413*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 414bbbc8e51SStefano Zampini 415bbbc8e51SStefano Zampini /* non-conforming meshes */ 416*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children)); 417bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 418bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 419bbbc8e51SStefano Zampini 420bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 421bbbc8e51SStefano Zampini row = rows[child-fStart]; 422*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES)); 423bbbc8e51SStefano Zampini } 424bbbc8e51SStefano Zampini } 425bbbc8e51SStefano Zampini } 426*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(fis, &rows)); 427*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cis, &cols)); 428*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&fis)); 429*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cis)); 430*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY)); 431*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY)); 432bbbc8e51SStefano Zampini 433bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 434*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR)); 435*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&conn)); 436bbbc8e51SStefano Zampini 437bbbc8e51SStefano Zampini /* extract local part of the CSR */ 438*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn)); 439*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&CSR)); 440*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 441*5f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 442bbbc8e51SStefano Zampini 443bbbc8e51SStefano Zampini /* get back requested output */ 444bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 445bbbc8e51SStefano Zampini if (offsets) { 446*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(m+1, &idxs)); 447bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 448bbbc8e51SStefano Zampini *offsets = idxs; 449bbbc8e51SStefano Zampini } 450bbbc8e51SStefano Zampini if (adjacency) { 451*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ii[m] - m, &idxs)); 452*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cis_own, &rows)); 453bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 454bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 455bbbc8e51SStefano Zampini 456bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 457bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 458bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 459bbbc8e51SStefano Zampini } 460bbbc8e51SStefano Zampini } 461*5f80ce2aSJacob Faibussowitsch PetscCheck(c == ii[m] - m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 462*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cis_own, &rows)); 463bbbc8e51SStefano Zampini *adjacency = idxs; 464bbbc8e51SStefano Zampini } 465bbbc8e51SStefano Zampini 466bbbc8e51SStefano Zampini /* cleanup */ 467*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cis_own)); 468*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 469*5f80ce2aSJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 470*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&conn)); 471bbbc8e51SStefano Zampini PetscFunctionReturn(0); 472bbbc8e51SStefano Zampini } 473bbbc8e51SStefano Zampini 474bbbc8e51SStefano Zampini /*@C 475bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 476bbbc8e51SStefano Zampini 477bbbc8e51SStefano Zampini Input Parameters: 478bbbc8e51SStefano Zampini + dm - The mesh DM dm 479bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 480bbbc8e51SStefano Zampini 481d8d19677SJose E. Roman Output Parameters: 482bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 483bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 484bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 485bbbc8e51SStefano Zampini - globalNumbering - A map from the local cell numbering to the global numbering used in "adjacency". Negative indicates that the cell is a duplicate from another process. 486bbbc8e51SStefano Zampini 487bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 488bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 489bbbc8e51SStefano Zampini 4905a107427SMatthew G. Knepley Options Database Keys: 4915a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph 4925a107427SMatthew G. Knepley 493bbbc8e51SStefano Zampini Level: developer 494bbbc8e51SStefano Zampini 495bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 496bbbc8e51SStefano Zampini @*/ 497bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 498bbbc8e51SStefano Zampini { 4995a107427SMatthew G. Knepley DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH; 500bbbc8e51SStefano Zampini 501bbbc8e51SStefano Zampini PetscFunctionBegin; 502*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetEnum(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *) &alg, NULL)); 5035a107427SMatthew G. Knepley switch (alg) { 5045a107427SMatthew G. Knepley case DM_PLEX_CSR_MAT: 505*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5065a107427SMatthew G. Knepley case DM_PLEX_CSR_GRAPH: 507*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 5085a107427SMatthew G. Knepley case DM_PLEX_CSR_OVERLAP: 509*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering));break; 510bbbc8e51SStefano Zampini } 511bbbc8e51SStefano Zampini PetscFunctionReturn(0); 512bbbc8e51SStefano Zampini } 513bbbc8e51SStefano Zampini 514d5577e40SMatthew G. Knepley /*@C 515d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 516d5577e40SMatthew G. Knepley 517fe2efc57SMark Collective on DM 518d5577e40SMatthew G. Knepley 5194165533cSJose E. Roman Input Parameters: 520d5577e40SMatthew G. Knepley + dm - The DMPlex 521d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 522d5577e40SMatthew G. Knepley 5234165533cSJose E. Roman Output Parameters: 524d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 525d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 526d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 527d5577e40SMatthew G. Knepley 528d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 529d5577e40SMatthew G. Knepley 530d5577e40SMatthew G. Knepley Level: advanced 531d5577e40SMatthew G. Knepley 532d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 533d5577e40SMatthew G. Knepley @*/ 53470034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 53570034214SMatthew G. Knepley { 53670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 53770034214SMatthew G. Knepley PetscInt numFaceCases = 0; 53870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 53970034214SMatthew G. Knepley PetscInt *off, *adj; 54070034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 54170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 54270034214SMatthew G. Knepley 54370034214SMatthew G. Knepley PetscFunctionBegin; 54470034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 545*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 54670034214SMatthew G. Knepley cellDim = dim - cellHeight; 547*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 548*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 54970034214SMatthew G. Knepley if (cEnd - cStart == 0) { 55070034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 55170034214SMatthew G. Knepley if (offsets) *offsets = NULL; 55270034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 55370034214SMatthew G. Knepley PetscFunctionReturn(0); 55470034214SMatthew G. Knepley } 55570034214SMatthew G. Knepley numCells = cEnd - cStart; 55670034214SMatthew G. Knepley faceDepth = depth - cellHeight; 55770034214SMatthew G. Knepley if (dim == depth) { 55870034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 55970034214SMatthew G. Knepley 560*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numCells+1, &off)); 56170034214SMatthew G. Knepley /* Count neighboring cells */ 562*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd)); 56370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 56470034214SMatthew G. Knepley const PetscInt *support; 56570034214SMatthew G. Knepley PetscInt supportSize; 566*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, f, &supportSize)); 567*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, f, &support)); 56870034214SMatthew G. Knepley if (supportSize == 2) { 5699ffc88e4SToby Isaac PetscInt numChildren; 5709ffc88e4SToby Isaac 571*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5729ffc88e4SToby Isaac if (!numChildren) { 57370034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 57470034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 57570034214SMatthew G. Knepley } 57670034214SMatthew G. Knepley } 5779ffc88e4SToby Isaac } 57870034214SMatthew G. Knepley /* Prefix sum */ 57970034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 58070034214SMatthew G. Knepley if (adjacency) { 58170034214SMatthew G. Knepley PetscInt *tmp; 58270034214SMatthew G. Knepley 583*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(off[numCells], &adj)); 584*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numCells+1, &tmp)); 585*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(tmp, off, numCells+1)); 58670034214SMatthew G. Knepley /* Get neighboring cells */ 58770034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 58870034214SMatthew G. Knepley const PetscInt *support; 58970034214SMatthew G. Knepley PetscInt supportSize; 590*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, f, &supportSize)); 591*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupport(dm, f, &support)); 59270034214SMatthew G. Knepley if (supportSize == 2) { 5939ffc88e4SToby Isaac PetscInt numChildren; 5949ffc88e4SToby Isaac 595*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,f,&numChildren,NULL)); 5969ffc88e4SToby Isaac if (!numChildren) { 59770034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 59870034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 59970034214SMatthew G. Knepley } 60070034214SMatthew G. Knepley } 6019ffc88e4SToby Isaac } 602*5f80ce2aSJacob Faibussowitsch for (c = 0; c < cEnd-cStart; ++c) PetscAssert(tmp[c] == off[c+1],PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 603*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tmp)); 60470034214SMatthew G. Knepley } 60570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 60670034214SMatthew G. Knepley if (offsets) *offsets = off; 60770034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 60870034214SMatthew G. Knepley PetscFunctionReturn(0); 60970034214SMatthew G. Knepley } 61070034214SMatthew G. Knepley /* Setup face recognition */ 61170034214SMatthew G. Knepley if (faceDepth == 1) { 61270034214SMatthew G. Knepley PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 61370034214SMatthew G. Knepley 61470034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 61570034214SMatthew G. Knepley PetscInt corners; 61670034214SMatthew G. Knepley 617*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, c, &corners)); 61870034214SMatthew G. Knepley if (!cornersSeen[corners]) { 61970034214SMatthew G. Knepley PetscInt nFV; 62070034214SMatthew G. Knepley 621*5f80ce2aSJacob Faibussowitsch PetscCheck(numFaceCases < maxFaceCases,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 62270034214SMatthew G. Knepley cornersSeen[corners] = 1; 62370034214SMatthew G. Knepley 624*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV)); 62570034214SMatthew G. Knepley 62670034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 62770034214SMatthew G. Knepley } 62870034214SMatthew G. Knepley } 62970034214SMatthew G. Knepley } 630*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(numCells+1, &off)); 63170034214SMatthew G. Knepley /* Count neighboring cells */ 63270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 63370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 63470034214SMatthew G. Knepley 635*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 63670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 63770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 63870034214SMatthew G. Knepley PetscInt cellPair[2]; 63970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 64070034214SMatthew G. Knepley PetscInt meetSize = 0; 64170034214SMatthew G. Knepley const PetscInt *meet = NULL; 64270034214SMatthew G. Knepley 64370034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 64470034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 64570034214SMatthew G. Knepley if (!found) { 646*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 64770034214SMatthew G. Knepley if (meetSize) { 64870034214SMatthew G. Knepley PetscInt f; 64970034214SMatthew G. Knepley 65070034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 65170034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 65270034214SMatthew G. Knepley found = PETSC_TRUE; 65370034214SMatthew G. Knepley break; 65470034214SMatthew G. Knepley } 65570034214SMatthew G. Knepley } 65670034214SMatthew G. Knepley } 657*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 65870034214SMatthew G. Knepley } 65970034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 66070034214SMatthew G. Knepley } 66170034214SMatthew G. Knepley } 66270034214SMatthew G. Knepley /* Prefix sum */ 66370034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 66470034214SMatthew G. Knepley 66570034214SMatthew G. Knepley if (adjacency) { 666*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(off[numCells], &adj)); 66770034214SMatthew G. Knepley /* Get neighboring cells */ 66870034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 66970034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 67070034214SMatthew G. Knepley PetscInt cellOffset = 0; 67170034214SMatthew G. Knepley 672*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells)); 67370034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 67470034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 67570034214SMatthew G. Knepley PetscInt cellPair[2]; 67670034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 67770034214SMatthew G. Knepley PetscInt meetSize = 0; 67870034214SMatthew G. Knepley const PetscInt *meet = NULL; 67970034214SMatthew G. Knepley 68070034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 68170034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 68270034214SMatthew G. Knepley if (!found) { 683*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet)); 68470034214SMatthew G. Knepley if (meetSize) { 68570034214SMatthew G. Knepley PetscInt f; 68670034214SMatthew G. Knepley 68770034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 68870034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 68970034214SMatthew G. Knepley found = PETSC_TRUE; 69070034214SMatthew G. Knepley break; 69170034214SMatthew G. Knepley } 69270034214SMatthew G. Knepley } 69370034214SMatthew G. Knepley } 694*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet)); 69570034214SMatthew G. Knepley } 69670034214SMatthew G. Knepley if (found) { 69770034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 69870034214SMatthew G. Knepley ++cellOffset; 69970034214SMatthew G. Knepley } 70070034214SMatthew G. Knepley } 70170034214SMatthew G. Knepley } 70270034214SMatthew G. Knepley } 703*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(neighborCells)); 70470034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 70570034214SMatthew G. Knepley if (offsets) *offsets = off; 70670034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 70770034214SMatthew G. Knepley PetscFunctionReturn(0); 70870034214SMatthew G. Knepley } 70970034214SMatthew G. Knepley 71077623264SMatthew G. Knepley /*@ 7113c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 71277623264SMatthew G. Knepley 713fe2efc57SMark Collective on PetscPartitioner 71477623264SMatthew G. Knepley 71577623264SMatthew G. Knepley Input Parameters: 71677623264SMatthew G. Knepley + part - The PetscPartitioner 7173c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 718f8987ae8SMichael Lange - dm - The mesh DM 71977623264SMatthew G. Knepley 72077623264SMatthew G. Knepley Output Parameters: 72177623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 722f8987ae8SMichael Lange - partition - The list of points by partition 72377623264SMatthew G. Knepley 7243c41b853SStefano Zampini Notes: 7253c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 7263c41b853SStefano Zampini by the section in the transitive closure of the point. 72777623264SMatthew G. Knepley 72877623264SMatthew G. Knepley Level: developer 72977623264SMatthew G. Knepley 7303c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition() 7314b15ede2SMatthew G. Knepley @*/ 7323c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 73377623264SMatthew G. Knepley { 73477623264SMatthew G. Knepley PetscMPIInt size; 7353c41b853SStefano Zampini PetscBool isplex; 7363c41b853SStefano Zampini PetscSection vertSection = NULL; 73777623264SMatthew G. Knepley 73877623264SMatthew G. Knepley PetscFunctionBegin; 73977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 74077623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 7413c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 74277623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 74377623264SMatthew G. Knepley PetscValidPointer(partition, 5); 744*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex)); 745*5f80ce2aSJacob Faibussowitsch PetscCheck(isplex,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 746*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) part), &size)); 74777623264SMatthew G. Knepley if (size == 1) { 74877623264SMatthew G. Knepley PetscInt *points; 74977623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 75077623264SMatthew G. Knepley 751*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 752*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionReset(partSection)); 753*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(partSection, 0, size)); 754*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(partSection, 0, cEnd-cStart)); 755*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(partSection)); 756*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cEnd-cStart, &points)); 75777623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 758*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition)); 75977623264SMatthew G. Knepley PetscFunctionReturn(0); 76077623264SMatthew G. Knepley } 76177623264SMatthew G. Knepley if (part->height == 0) { 762074d466cSStefano Zampini PetscInt numVertices = 0; 76377623264SMatthew G. Knepley PetscInt *start = NULL; 76477623264SMatthew G. Knepley PetscInt *adjacency = NULL; 7653fa7752dSToby Isaac IS globalNumbering; 76677623264SMatthew G. Knepley 767074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 768*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering)); 76913911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 770074d466cSStefano Zampini const PetscInt *idxs; 771074d466cSStefano Zampini PetscInt p, pStart, pEnd; 772074d466cSStefano Zampini 773*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 774*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering)); 775*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(globalNumbering, &idxs)); 776074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 777*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(globalNumbering, &idxs)); 778074d466cSStefano Zampini } 7793c41b853SStefano Zampini if (part->usevwgt) { 7803c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 7813c41b853SStefano Zampini IS clPoints = NULL; 7823c41b853SStefano Zampini const PetscInt *gid,*clIdx; 7833c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 7840358368aSMatthew G. Knepley 7853c41b853SStefano Zampini /* dm->localSection encodes degrees of freedom per point, not per cell. We need to get the closure index to properly specify cell weights (aka dofs) */ 7863c41b853SStefano Zampini /* We do this only if the local section has been set */ 7873c41b853SStefano Zampini if (section) { 788*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL)); 7893c41b853SStefano Zampini if (!clSection) { 790*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateClosureIndex(dm,NULL)); 7913c41b853SStefano Zampini } 792*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints)); 793*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(clPoints,&clIdx)); 7943c41b853SStefano Zampini } 795*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd)); 796*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, &vertSection)); 797*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(vertSection, 0, numVertices)); 7983c41b853SStefano Zampini if (globalNumbering) { 799*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(globalNumbering,&gid)); 8003c41b853SStefano Zampini } else gid = NULL; 8013c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 8023c41b853SStefano Zampini PetscInt dof = 1; 8030358368aSMatthew G. Knepley 8043c41b853SStefano Zampini /* skip cells in the overlap */ 8053c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 8063c41b853SStefano Zampini 8073c41b853SStefano Zampini if (section) { 8083c41b853SStefano Zampini PetscInt cl, clSize, clOff; 8093c41b853SStefano Zampini 8103c41b853SStefano Zampini dof = 0; 811*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(clSection, p, &clSize)); 812*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(clSection, p, &clOff)); 8133c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 8143c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 8153c41b853SStefano Zampini 816*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, clPoint, &clDof)); 8173c41b853SStefano Zampini dof += clDof; 8180358368aSMatthew G. Knepley } 8190358368aSMatthew G. Knepley } 820*5f80ce2aSJacob Faibussowitsch PetscCheck(dof,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p); 821*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(vertSection, v, dof)); 8223c41b853SStefano Zampini v++; 8233c41b853SStefano Zampini } 8243c41b853SStefano Zampini if (globalNumbering) { 825*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(globalNumbering,&gid)); 8263c41b853SStefano Zampini } 8273c41b853SStefano Zampini if (clPoints) { 828*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(clPoints,&clIdx)); 8293c41b853SStefano Zampini } 830*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(vertSection)); 8313c41b853SStefano Zampini } 832*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition)); 833*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(start)); 834*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjacency)); 8353fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8363fa7752dSToby Isaac const PetscInt *globalNum; 8373fa7752dSToby Isaac const PetscInt *partIdx; 8383fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8393fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8403fa7752dSToby Isaac IS newPartition; 8413fa7752dSToby Isaac 842*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(*partition,&localSize)); 843*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(localSize,&adjusted)); 844*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(globalNumbering,&globalNum)); 845*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(*partition,&partIdx)); 846*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(localSize,&map)); 847*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd)); 8483fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8493fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8503fa7752dSToby Isaac } 8513fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 8523fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 8533fa7752dSToby Isaac } 854*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(map)); 855*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(*partition,&partIdx)); 856*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(globalNumbering,&globalNum)); 857*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition)); 858*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&globalNumbering)); 859*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(partition)); 8603fa7752dSToby Isaac *partition = newPartition; 8613fa7752dSToby Isaac } 86298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 863*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&vertSection)); 86477623264SMatthew G. Knepley PetscFunctionReturn(0); 86577623264SMatthew G. Knepley } 86677623264SMatthew G. Knepley 8675680f57bSMatthew G. Knepley /*@ 8685680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 8695680f57bSMatthew G. Knepley 8705680f57bSMatthew G. Knepley Not collective 8715680f57bSMatthew G. Knepley 8725680f57bSMatthew G. Knepley Input Parameter: 8735680f57bSMatthew G. Knepley . dm - The DM 8745680f57bSMatthew G. Knepley 8755680f57bSMatthew G. Knepley Output Parameter: 8765680f57bSMatthew G. Knepley . part - The PetscPartitioner 8775680f57bSMatthew G. Knepley 8785680f57bSMatthew G. Knepley Level: developer 8795680f57bSMatthew G. Knepley 88098599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 88198599a47SLawrence Mitchell 8823c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate() 8835680f57bSMatthew G. Knepley @*/ 8845680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 8855680f57bSMatthew G. Knepley { 8865680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 8875680f57bSMatthew G. Knepley 8885680f57bSMatthew G. Knepley PetscFunctionBegin; 8895680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8905680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 8915680f57bSMatthew G. Knepley *part = mesh->partitioner; 8925680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8935680f57bSMatthew G. Knepley } 8945680f57bSMatthew G. Knepley 89571bb2955SLawrence Mitchell /*@ 89671bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 89771bb2955SLawrence Mitchell 898fe2efc57SMark logically collective on DM 89971bb2955SLawrence Mitchell 90071bb2955SLawrence Mitchell Input Parameters: 90171bb2955SLawrence Mitchell + dm - The DM 90271bb2955SLawrence Mitchell - part - The partitioner 90371bb2955SLawrence Mitchell 90471bb2955SLawrence Mitchell Level: developer 90571bb2955SLawrence Mitchell 90671bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 90771bb2955SLawrence Mitchell 90871bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 90971bb2955SLawrence Mitchell @*/ 91071bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 91171bb2955SLawrence Mitchell { 91271bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 91371bb2955SLawrence Mitchell 91471bb2955SLawrence Mitchell PetscFunctionBegin; 91571bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91671bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 917*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)part)); 918*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerDestroy(&mesh->partitioner)); 91971bb2955SLawrence Mitchell mesh->partitioner = part; 92071bb2955SLawrence Mitchell PetscFunctionReturn(0); 92171bb2955SLawrence Mitchell } 92271bb2955SLawrence Mitchell 9238e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 9248e330a33SStefano Zampini { 9258e330a33SStefano Zampini const PetscInt *cone; 9268e330a33SStefano Zampini PetscInt coneSize, c; 9278e330a33SStefano Zampini PetscBool missing; 9288e330a33SStefano Zampini 9298e330a33SStefano Zampini PetscFunctionBeginHot; 930*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIQueryAdd(ht, point, &missing)); 9318e330a33SStefano Zampini if (missing) { 932*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 933*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize)); 9348e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 935*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosure_Private(dm, ht, cone[c])); 9368e330a33SStefano Zampini } 9378e330a33SStefano Zampini } 9388e330a33SStefano Zampini PetscFunctionReturn(0); 9398e330a33SStefano Zampini } 9408e330a33SStefano Zampini 9418e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 942270bba0cSToby Isaac { 943270bba0cSToby Isaac PetscFunctionBegin; 9446a5a2ffdSToby Isaac if (up) { 9456a5a2ffdSToby Isaac PetscInt parent; 9466a5a2ffdSToby Isaac 947*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm,point,&parent,NULL)); 9486a5a2ffdSToby Isaac if (parent != point) { 9496a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 9506a5a2ffdSToby Isaac 951*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 952270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 953270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 954270bba0cSToby Isaac 955*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(ht, cpoint)); 956*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE)); 957270bba0cSToby Isaac } 958*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure)); 9596a5a2ffdSToby Isaac } 9606a5a2ffdSToby Isaac } 9616a5a2ffdSToby Isaac if (down) { 9626a5a2ffdSToby Isaac PetscInt numChildren; 9636a5a2ffdSToby Isaac const PetscInt *children; 9646a5a2ffdSToby Isaac 965*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm,point,&numChildren,&children)); 9666a5a2ffdSToby Isaac if (numChildren) { 9676a5a2ffdSToby Isaac PetscInt i; 9686a5a2ffdSToby Isaac 9696a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 9706a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 9716a5a2ffdSToby Isaac 972*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(ht, cpoint)); 973*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE)); 9746a5a2ffdSToby Isaac } 9756a5a2ffdSToby Isaac } 9766a5a2ffdSToby Isaac } 977270bba0cSToby Isaac PetscFunctionReturn(0); 978270bba0cSToby Isaac } 979270bba0cSToby Isaac 9808e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 9818e330a33SStefano Zampini { 9828e330a33SStefano Zampini PetscInt parent; 983825f8a23SLisandro Dalcin 9848e330a33SStefano Zampini PetscFunctionBeginHot; 985*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeParent(dm, point, &parent,NULL)); 9868e330a33SStefano Zampini if (point != parent) { 9878e330a33SStefano Zampini const PetscInt *cone; 9888e330a33SStefano Zampini PetscInt coneSize, c; 9898e330a33SStefano Zampini 990*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Up_Private(dm, ht, parent)); 991*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosure_Private(dm, ht, parent)); 992*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, parent, &cone)); 993*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, parent, &coneSize)); 9948e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 9958e330a33SStefano Zampini const PetscInt cp = cone[c]; 9968e330a33SStefano Zampini 997*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Up_Private(dm, ht, cp)); 9988e330a33SStefano Zampini } 9998e330a33SStefano Zampini } 10008e330a33SStefano Zampini PetscFunctionReturn(0); 10018e330a33SStefano Zampini } 10028e330a33SStefano Zampini 10038e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 10048e330a33SStefano Zampini { 10058e330a33SStefano Zampini PetscInt i, numChildren; 10068e330a33SStefano Zampini const PetscInt *children; 10078e330a33SStefano Zampini 10088e330a33SStefano Zampini PetscFunctionBeginHot; 1009*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTreeChildren(dm, point, &numChildren, &children)); 10108e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 1011*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(ht, children[i])); 10128e330a33SStefano Zampini } 10138e330a33SStefano Zampini PetscFunctionReturn(0); 10148e330a33SStefano Zampini } 10158e330a33SStefano Zampini 10168e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 10178e330a33SStefano Zampini { 10188e330a33SStefano Zampini const PetscInt *cone; 10198e330a33SStefano Zampini PetscInt coneSize, c; 10208e330a33SStefano Zampini 10218e330a33SStefano Zampini PetscFunctionBeginHot; 1022*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(ht, point)); 1023*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Up_Private(dm, ht, point)); 1024*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Down_Private(dm, ht, point)); 1025*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCone(dm, point, &cone)); 1026*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize)); 10278e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 1028*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Private(dm, ht, cone[c])); 10298e330a33SStefano Zampini } 10308e330a33SStefano Zampini PetscFunctionReturn(0); 10318e330a33SStefano Zampini } 10328e330a33SStefano Zampini 10338e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 1034825f8a23SLisandro Dalcin { 1035825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 10368e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 10378e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 103827104ee2SJacob Faibussowitsch PetscHSetI ht = NULL; 1039825f8a23SLisandro Dalcin 1040825f8a23SLisandro Dalcin PetscFunctionBegin; 1041*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetICreate(&ht)); 1042*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIResize(ht, numPoints*16)); 10438e330a33SStefano Zampini if (!hasTree) { 10448e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 1045*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosure_Private(dm, ht, points[p])); 10468e330a33SStefano Zampini } 10478e330a33SStefano Zampini } else { 10488e330a33SStefano Zampini #if 1 10498e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 1050*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexAddClosureTree_Private(dm, ht, points[p])); 10518e330a33SStefano Zampini } 10528e330a33SStefano Zampini #else 10538e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 1054825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 1055*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 1056825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 1057*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIAdd(ht, closure[c])); 1058*5f80ce2aSJacob Faibussowitsch if (hasTree) CHKERRQ(DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE)); 1059825f8a23SLisandro Dalcin } 1060825f8a23SLisandro Dalcin } 1061*5f80ce2aSJacob Faibussowitsch if (closure) CHKERRQ(DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure)); 10628e330a33SStefano Zampini #endif 10638e330a33SStefano Zampini } 1064*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetSize(ht, &nelems)); 1065*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nelems, &elems)); 1066*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetElems(ht, &off, elems)); 1067*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIDestroy(&ht)); 1068*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSortInt(nelems, elems)); 1069*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS)); 1070825f8a23SLisandro Dalcin PetscFunctionReturn(0); 1071825f8a23SLisandro Dalcin } 1072825f8a23SLisandro Dalcin 10735abbe4feSMichael Lange /*@ 10745abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 10755abbe4feSMichael Lange 10765abbe4feSMichael Lange Input Parameters: 10775abbe4feSMichael Lange + dm - The DM 1078a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 10795abbe4feSMichael Lange 10805abbe4feSMichael Lange Level: developer 10815abbe4feSMichael Lange 108230b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 10835abbe4feSMichael Lange @*/ 10845abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 10859ffc88e4SToby Isaac { 1086825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 10875abbe4feSMichael Lange const PetscInt *ranks, *points; 1088825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 10899ffc88e4SToby Isaac 10909ffc88e4SToby Isaac PetscFunctionBegin; 1091*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(label, &rankIS)); 1092*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(rankIS, &numRanks)); 1093*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rankIS, &ranks)); 10945abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 10955abbe4feSMichael Lange const PetscInt rank = ranks[r]; 1096*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, rank, &pointIS)); 1097*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pointIS, &numPoints)); 1098*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pointIS, &points)); 1099*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS)); 1100*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pointIS, &points)); 1101*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 1102*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetStratumIS(label, rank, closureIS)); 1103*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&closureIS)); 11049ffc88e4SToby Isaac } 1105*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rankIS, &ranks)); 1106*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rankIS)); 11079ffc88e4SToby Isaac PetscFunctionReturn(0); 11089ffc88e4SToby Isaac } 11099ffc88e4SToby Isaac 111024d039d7SMichael Lange /*@ 111124d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 111224d039d7SMichael Lange 111324d039d7SMichael Lange Input Parameters: 111424d039d7SMichael Lange + dm - The DM 1115a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 111624d039d7SMichael Lange 111724d039d7SMichael Lange Level: developer 111824d039d7SMichael Lange 11192d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 112024d039d7SMichael Lange @*/ 112124d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 112270034214SMatthew G. Knepley { 112324d039d7SMichael Lange IS rankIS, pointIS; 112424d039d7SMichael Lange const PetscInt *ranks, *points; 112524d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 112624d039d7SMichael Lange PetscInt *adj = NULL; 112770034214SMatthew G. Knepley 112870034214SMatthew G. Knepley PetscFunctionBegin; 1129*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(label, &rankIS)); 1130*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(rankIS, &numRanks)); 1131*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rankIS, &ranks)); 113224d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 113324d039d7SMichael Lange const PetscInt rank = ranks[r]; 113470034214SMatthew G. Knepley 1135*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, rank, &pointIS)); 1136*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pointIS, &numPoints)); 1137*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pointIS, &points)); 113870034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 113924d039d7SMichael Lange adjSize = PETSC_DETERMINE; 1140*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, points[p], &adjSize, &adj)); 1141*5f80ce2aSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(label, adj[a], rank)); 114270034214SMatthew G. Knepley } 1143*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pointIS, &points)); 1144*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 114570034214SMatthew G. Knepley } 1146*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rankIS, &ranks)); 1147*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rankIS)); 1148*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 114924d039d7SMichael Lange PetscFunctionReturn(0); 115070034214SMatthew G. Knepley } 115170034214SMatthew G. Knepley 1152be200f8dSMichael Lange /*@ 1153be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1154be200f8dSMichael Lange 1155be200f8dSMichael Lange Input Parameters: 1156be200f8dSMichael Lange + dm - The DM 1157a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1158be200f8dSMichael Lange 1159be200f8dSMichael Lange Level: developer 1160be200f8dSMichael Lange 1161be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1162be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1163be200f8dSMichael Lange 11642d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 1165be200f8dSMichael Lange @*/ 1166be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1167be200f8dSMichael Lange { 1168be200f8dSMichael Lange MPI_Comm comm; 1169be200f8dSMichael Lange PetscMPIInt rank; 1170be200f8dSMichael Lange PetscSF sfPoint; 11715d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1172be200f8dSMichael Lange IS rankIS, pointIS; 1173be200f8dSMichael Lange const PetscInt *ranks; 1174be200f8dSMichael Lange PetscInt numRanks, r; 1175be200f8dSMichael Lange 1176be200f8dSMichael Lange PetscFunctionBegin; 1177*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 1178*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1179*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 11805d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 1181*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGather(label, sfPoint, &lblLeaves)); 1182*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(lblLeaves, &rankIS)); 1183*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(rankIS, &numRanks)); 1184*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rankIS, &ranks)); 11855d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 11865d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 11875d04f6ebSMichael Lange if (remoteRank == rank) continue; 1188*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS)); 1189*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelInsertIS(label, pointIS, remoteRank)); 1190*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 11915d04f6ebSMichael Lange } 1192*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rankIS, &ranks)); 1193*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rankIS)); 1194*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&lblLeaves)); 1195be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 1196*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDistribute(label, sfPoint, &lblRoots)); 1197*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(lblRoots, &rankIS)); 1198*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(rankIS, &numRanks)); 1199*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rankIS, &ranks)); 1200be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1201be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1202be200f8dSMichael Lange if (remoteRank == rank) continue; 1203*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS)); 1204*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelInsertIS(label, pointIS, remoteRank)); 1205*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 1206be200f8dSMichael Lange } 1207*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rankIS, &ranks)); 1208*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rankIS)); 1209*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&lblRoots)); 1210be200f8dSMichael Lange PetscFunctionReturn(0); 1211be200f8dSMichael Lange } 1212be200f8dSMichael Lange 12131fd9873aSMichael Lange /*@ 12141fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 12151fd9873aSMichael Lange 12161fd9873aSMichael Lange Input Parameters: 12171fd9873aSMichael Lange + dm - The DM 1218a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots 1219fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 12201fd9873aSMichael Lange 12211fd9873aSMichael Lange Output Parameter: 1222a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots 12231fd9873aSMichael Lange 12241fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 12251fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 12261fd9873aSMichael Lange 12271fd9873aSMichael Lange Level: developer 12281fd9873aSMichael Lange 12292d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 12301fd9873aSMichael Lange @*/ 12311fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 12321fd9873aSMichael Lange { 12331fd9873aSMichael Lange MPI_Comm comm; 1234874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 1235874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 12361fd9873aSMichael Lange PetscSF sfPoint; 1237874ddda9SLisandro Dalcin PetscSection rootSection; 12381fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 12391fd9873aSMichael Lange const PetscSFNode *remote; 12401fd9873aSMichael Lange const PetscInt *local, *neighbors; 12411fd9873aSMichael Lange IS valueIS; 1242874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 12431fd9873aSMichael Lange 12441fd9873aSMichael Lange PetscFunctionBegin; 1245*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0)); 1246*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 1247*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1248*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 1249*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 12501fd9873aSMichael Lange 12511fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 1252*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &rootSection)); 1253*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(rootSection, 0, size)); 1254*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(rootLabel, &valueIS)); 1255*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(valueIS, &numNeighbors)); 1256*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(valueIS, &neighbors)); 12571fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 1258*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints)); 1259*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionAddDof(rootSection, neighbors[n], numPoints)); 12601fd9873aSMichael Lange } 1261*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(rootSection)); 1262*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootSection, &rootSize)); 1263*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(rootSize, &rootPoints)); 1264*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 12651fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 12661fd9873aSMichael Lange IS pointIS; 12671fd9873aSMichael Lange const PetscInt *points; 12681fd9873aSMichael Lange 1269*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1270*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS)); 1271*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(pointIS, &numPoints)); 1272*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(pointIS, &points)); 12731fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1274*5f80ce2aSJacob Faibussowitsch if (local) CHKERRQ(PetscFindInt(points[p], nleaves, local, &l)); 1275f8987ae8SMichael Lange else {l = -1;} 12761fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 12771fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 12781fd9873aSMichael Lange } 1279*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(pointIS, &points)); 1280*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 12811fd9873aSMichael Lange } 1282874ddda9SLisandro Dalcin 1283874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 1284874ddda9SLisandro Dalcin if (!processSF) { 1285874ddda9SLisandro Dalcin PetscInt64 counter = 0; 1286874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 1287874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 1288874ddda9SLisandro Dalcin 1289*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls)); 1290874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 1291*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootSection, neighbors[n], &dof)); 1292*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootSection, neighbors[n], &off)); 1293874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 1294874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1295874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 1296874ddda9SLisandro Dalcin #endif 1297874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 1298874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 1299874ddda9SLisandro Dalcin } 1300*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm)); 1301874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 1302874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 1303*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm)); 1304874ddda9SLisandro Dalcin if (!mpiOverflow) { 1305*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(dm,"Using Alltoallv for mesh distribution\n")); 1306874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 1307*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(leafSize, &leafPoints)); 1308*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm)); 1309874ddda9SLisandro Dalcin } 1310*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree4(scounts, sdispls, rcounts, rdispls)); 1311874ddda9SLisandro Dalcin } 1312874ddda9SLisandro Dalcin 1313874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 1314874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 1315874ddda9SLisandro Dalcin PetscSF procSF; 1316874ddda9SLisandro Dalcin PetscSection leafSection; 1317874ddda9SLisandro Dalcin 1318874ddda9SLisandro Dalcin if (processSF) { 1319*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(dm,"Using processSF for mesh distribution\n")); 1320*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)processSF)); 1321874ddda9SLisandro Dalcin procSF = processSF; 1322874ddda9SLisandro Dalcin } else { 1323*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n")); 1324*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm,&procSF)); 1325*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL)); 1326874ddda9SLisandro Dalcin } 1327874ddda9SLisandro Dalcin 1328*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection)); 1329*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints)); 1330*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(leafSection, &leafSize)); 1331*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafSection)); 1332*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&procSF)); 1333874ddda9SLisandro Dalcin } 1334874ddda9SLisandro Dalcin 1335874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 1336*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank)); 13371fd9873aSMichael Lange } 1338874ddda9SLisandro Dalcin 1339*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(valueIS, &neighbors)); 1340*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&valueIS)); 1341*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootSection)); 1342*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rootPoints)); 1343*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafPoints)); 1344*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0)); 13451fd9873aSMichael Lange PetscFunctionReturn(0); 13461fd9873aSMichael Lange } 13471fd9873aSMichael Lange 1348aa3148a8SMichael Lange /*@ 1349aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1350aa3148a8SMichael Lange 1351aa3148a8SMichael Lange Input Parameters: 1352aa3148a8SMichael Lange + dm - The DM 1353a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots 1354aa3148a8SMichael Lange 1355aa3148a8SMichael Lange Output Parameter: 1356fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 1357aa3148a8SMichael Lange 1358aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1359aa3148a8SMichael Lange 1360aa3148a8SMichael Lange Level: developer 1361aa3148a8SMichael Lange 136230b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 1363aa3148a8SMichael Lange @*/ 1364aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1365aa3148a8SMichael Lange { 13666e203dd9SStefano Zampini PetscMPIInt rank; 13676e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 1368aa3148a8SMichael Lange PetscSFNode *remotePoints; 13696e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 13706e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 1371aa3148a8SMichael Lange 1372aa3148a8SMichael Lange PetscFunctionBegin; 1373*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 1374*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 1375aa3148a8SMichael Lange 1376*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValueIS(label, &neighborsIS)); 13776e203dd9SStefano Zampini #if 0 13786e203dd9SStefano Zampini { 13796e203dd9SStefano Zampini IS is; 1380*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDuplicate(neighborsIS, &is)); 1381*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISSort(is)); 1382*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&neighborsIS)); 13836e203dd9SStefano Zampini neighborsIS = is; 13846e203dd9SStefano Zampini } 13856e203dd9SStefano Zampini #endif 1386*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetLocalSize(neighborsIS, &nNeighbors)); 1387*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(neighborsIS, &neighbors)); 13886e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 1389*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(label, neighbors[n], &numPoints)); 1390aa3148a8SMichael Lange numRemote += numPoints; 1391aa3148a8SMichael Lange } 1392*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numRemote, &remotePoints)); 139343f7d02bSMichael Lange /* Put owned points first */ 1394*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(label, rank, &numPoints)); 139543f7d02bSMichael Lange if (numPoints > 0) { 1396*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, rank, &remoteRootIS)); 1397*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(remoteRootIS, &remoteRoots)); 139843f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 139943f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 140043f7d02bSMichael Lange remotePoints[idx].rank = rank; 140143f7d02bSMichael Lange idx++; 140243f7d02bSMichael Lange } 1403*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(remoteRootIS, &remoteRoots)); 1404*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&remoteRootIS)); 140543f7d02bSMichael Lange } 140643f7d02bSMichael Lange /* Now add remote points */ 14076e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 14086e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 14096e203dd9SStefano Zampini 1410*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(label, nn, &numPoints)); 14116e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 1412*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, nn, &remoteRootIS)); 1413*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(remoteRootIS, &remoteRoots)); 1414aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1415aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 14166e203dd9SStefano Zampini remotePoints[idx].rank = nn; 1417aa3148a8SMichael Lange idx++; 1418aa3148a8SMichael Lange } 1419*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(remoteRootIS, &remoteRoots)); 1420*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&remoteRootIS)); 1421aa3148a8SMichael Lange } 1422*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject) dm), sf)); 1423*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 1424*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 1425*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(*sf)); 1426*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&neighborsIS)); 1427*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0)); 142870034214SMatthew G. Knepley PetscFunctionReturn(0); 142970034214SMatthew G. Knepley } 1430cb87ef4cSFlorian Wechsung 1431abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 1432abe9303eSLisandro Dalcin #include <parmetis.h> 1433abe9303eSLisandro Dalcin #endif 1434abe9303eSLisandro Dalcin 14356a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 14366a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 14376a3739e5SFlorian Wechsung * them out in that case. */ 14386a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 14397a82c785SFlorian Wechsung /*@C 14407f57c1a4SFlorian Wechsung 14417f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 14427f57c1a4SFlorian Wechsung 14437f57c1a4SFlorian Wechsung Input parameters: 14447f57c1a4SFlorian Wechsung + dm - The DMPlex object. 1445fe2efc57SMark . n - The number of points. 1446fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 1447fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 1448fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 14497f57c1a4SFlorian Wechsung 14507f57c1a4SFlorian Wechsung Level: developer 14517f57c1a4SFlorian Wechsung 14527f57c1a4SFlorian Wechsung @*/ 14537f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 14547f57c1a4SFlorian Wechsung { 1455*5f80ce2aSJacob Faibussowitsch PetscInt pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 14567f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 14577f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 14587f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 14597f57c1a4SFlorian Wechsung const PetscInt *ilocal; 14607f57c1a4SFlorian Wechsung PetscBool *isLeaf; 14617f57c1a4SFlorian Wechsung PetscSF sf; 14627f57c1a4SFlorian Wechsung MPI_Comm comm; 14635a30b08bSFlorian Wechsung PetscMPIInt rank, size; 14647f57c1a4SFlorian Wechsung 14657f57c1a4SFlorian Wechsung PetscFunctionBegin; 1466*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 1467*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1468*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 1469*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 14707f57c1a4SFlorian Wechsung 1471*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 1472*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 1473*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &isLeaf)); 14747f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14757f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 14767f57c1a4SFlorian Wechsung } 14777f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 14787f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 14797f57c1a4SFlorian Wechsung } 14807f57c1a4SFlorian Wechsung 1481*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart+1, &cumSumDegrees)); 14827f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 14837f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 14847f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 14857f57c1a4SFlorian Wechsung } 14867f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 14877f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 14887f57c1a4SFlorian Wechsung 1489*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(sumDegrees, &locationsOfLeafs)); 1490*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &rankOnLeafs)); 14917f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 14927f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 14937f57c1a4SFlorian Wechsung } 1494*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 1495*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs)); 1496*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rankOnLeafs)); 14977f57c1a4SFlorian Wechsung 14987f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 1499*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs)); 1500*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &points)); 15017f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15027f57c1a4SFlorian Wechsung points[i] = pStart+i; 15037f57c1a4SFlorian Wechsung } 1504*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 1505*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs)); 1506*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(points)); 15077f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 1508*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &newOwners)); 1509*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &newNumbers)); 15107f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15117f57c1a4SFlorian Wechsung newOwners[i] = -1; 15127f57c1a4SFlorian Wechsung newNumbers[i] = -1; 15137f57c1a4SFlorian Wechsung } 15147f57c1a4SFlorian Wechsung { 15157f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 15167f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 15177f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 15187f57c1a4SFlorian Wechsung newNumber = -1; 15197f57c1a4SFlorian Wechsung oldOwner = rank; 15207f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 15217f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 15227f57c1a4SFlorian Wechsung newNumber = oldNumber; 15237f57c1a4SFlorian Wechsung } else { 15247f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 15257f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 15267f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 15277f57c1a4SFlorian Wechsung break; 15287f57c1a4SFlorian Wechsung } 15297f57c1a4SFlorian Wechsung } 15307f57c1a4SFlorian Wechsung } 1531*5f80ce2aSJacob Faibussowitsch PetscCheck(newNumber != -1,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 15327f57c1a4SFlorian Wechsung 15337f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 15347f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 15357f57c1a4SFlorian Wechsung } 15367f57c1a4SFlorian Wechsung } 1537*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cumSumDegrees)); 1538*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(locationsOfLeafs)); 1539*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteLocalPointOfLeafs)); 15407f57c1a4SFlorian Wechsung 1541*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 1542*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE)); 1543*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 1544*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE)); 15457f57c1a4SFlorian Wechsung 15467f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 15477f57c1a4SFlorian Wechsung leafCounter=0; 15487f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15497f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15507f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15517f57c1a4SFlorian Wechsung leafCounter++; 15527f57c1a4SFlorian Wechsung } 15537f57c1a4SFlorian Wechsung } else { 15547f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15557f57c1a4SFlorian Wechsung leafCounter++; 15567f57c1a4SFlorian Wechsung } 15577f57c1a4SFlorian Wechsung } 15587f57c1a4SFlorian Wechsung } 15597f57c1a4SFlorian Wechsung 15607f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 1561*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(leafCounter, &leafsNew)); 1562*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(leafCounter, &leafLocationsNew)); 15637f57c1a4SFlorian Wechsung 15647f57c1a4SFlorian Wechsung leafCounter = 0; 15657f57c1a4SFlorian Wechsung counter = 0; 15667f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 15677f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 15687f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 15697f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15707f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 15717f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 15727f57c1a4SFlorian Wechsung leafCounter++; 15737f57c1a4SFlorian Wechsung } 15747f57c1a4SFlorian Wechsung } else { 15757f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15767f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 15777f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 15787f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 15797f57c1a4SFlorian Wechsung leafCounter++; 15807f57c1a4SFlorian Wechsung } 15817f57c1a4SFlorian Wechsung } 15827f57c1a4SFlorian Wechsung if (isLeaf[i]) { 15837f57c1a4SFlorian Wechsung counter++; 15847f57c1a4SFlorian Wechsung } 15857f57c1a4SFlorian Wechsung } 15867f57c1a4SFlorian Wechsung 1587*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER)); 1588*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(newOwners)); 1589*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(newNumbers)); 1590*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isLeaf)); 15917f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 15927f57c1a4SFlorian Wechsung } 15937f57c1a4SFlorian Wechsung 1594125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 1595125d2a8fSFlorian Wechsung { 1596*5f80ce2aSJacob Faibussowitsch PetscInt *distribution, min, max, sum; 15975a30b08bSFlorian Wechsung PetscMPIInt rank, size; 1598*5f80ce2aSJacob Faibussowitsch 1599125d2a8fSFlorian Wechsung PetscFunctionBegin; 1600*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 1601*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1602*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(size, &distribution)); 1603*5f80ce2aSJacob Faibussowitsch for (PetscInt i=0; i<n; i++) { 1604125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 1605125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 1606125d2a8fSFlorian Wechsung } 1607*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm)); 1608125d2a8fSFlorian Wechsung min = distribution[0]; 1609125d2a8fSFlorian Wechsung max = distribution[0]; 1610125d2a8fSFlorian Wechsung sum = distribution[0]; 1611*5f80ce2aSJacob Faibussowitsch for (PetscInt i=1; i<size; i++) { 1612125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 1613125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 1614125d2a8fSFlorian Wechsung sum += distribution[i]; 1615125d2a8fSFlorian Wechsung } 1616*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum)); 1617*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(distribution)); 1618125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 1619125d2a8fSFlorian Wechsung } 1620125d2a8fSFlorian Wechsung 16216a3739e5SFlorian Wechsung #endif 16226a3739e5SFlorian Wechsung 1623cb87ef4cSFlorian Wechsung /*@ 16245dc86ac1SFlorian Wechsung DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace. 1625cb87ef4cSFlorian Wechsung 1626cb87ef4cSFlorian Wechsung Input parameters: 1627ed44d270SFlorian Wechsung + dm - The DMPlex object. 1628fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 1629fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 1630fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 1631cb87ef4cSFlorian Wechsung 16328b879b41SFlorian Wechsung Output parameters: 1633fe2efc57SMark . success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 16348b879b41SFlorian Wechsung 163590ea27d8SSatish Balay Level: intermediate 1636cb87ef4cSFlorian Wechsung 1637cb87ef4cSFlorian Wechsung @*/ 1638cb87ef4cSFlorian Wechsung 16398b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 1640cb87ef4cSFlorian Wechsung { 164141525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 1642cb87ef4cSFlorian Wechsung PetscSF sf; 16430faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 16447f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 16457f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 16467f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 1647cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 1648cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 1649cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 16507f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 16515dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 1652cb87ef4cSFlorian Wechsung PetscInt offset, counter; 16537f57c1a4SFlorian Wechsung PetscInt lenadjncy; 1654cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 1655cb87ef4cSFlorian Wechsung PetscInt lenxadj; 1656cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 1657cb87ef4cSFlorian Wechsung PetscInt *part, *options; 1658cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 1659cb87ef4cSFlorian Wechsung real_t *ubvec; 1660cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 1661cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 1662cb87ef4cSFlorian Wechsung MPI_Comm comm; 16634baf1206SFlorian Wechsung Mat A, Apre; 166412617df9SFlorian Wechsung const char *prefix = NULL; 16657d197802SFlorian Wechsung PetscViewer viewer; 16667d197802SFlorian Wechsung PetscViewerFormat format; 16675a30b08bSFlorian Wechsung PetscLayout layout; 166812617df9SFlorian Wechsung 166912617df9SFlorian Wechsung PetscFunctionBegin; 16708b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 1671*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 1672*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 1673*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 16747f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 16757f57c1a4SFlorian Wechsung 1676*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 167741525646SFlorian Wechsung 1678*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL)); 16795dc86ac1SFlorian Wechsung if (viewer) { 1680*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,format)); 16817d197802SFlorian Wechsung } 16827d197802SFlorian Wechsung 1683ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 1684*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd)); 1685*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 1686*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &toBalance)); 1687cf818975SFlorian Wechsung 1688cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 16895a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 1690cb87ef4cSFlorian Wechsung } 1691cb87ef4cSFlorian Wechsung 1692cf818975SFlorian Wechsung /* There are three types of points: 1693cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 1694cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 1695cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 1696cf818975SFlorian Wechsung */ 1697*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sf)); 1698*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote)); 1699*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &isLeaf)); 1700*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned)); 1701*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &isExclusivelyOwned)); 1702cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1703cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 1704cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 1705cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 1706cb87ef4cSFlorian Wechsung } 1707cf818975SFlorian Wechsung 1708cf818975SFlorian Wechsung /* start by marking all the leafs */ 1709cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 1710cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 1711cb87ef4cSFlorian Wechsung } 1712cb87ef4cSFlorian Wechsung 1713cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 1714cf818975SFlorian Wechsung * not by calculating its degree */ 1715*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(sf, °rees)); 1716*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(sf, °rees)); 1717cf818975SFlorian Wechsung 1718cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 1719cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 1720cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1721cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17227f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1723cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 1724cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 1725cb87ef4cSFlorian Wechsung } else { 1726cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 1727cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 1728cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 1729cb87ef4cSFlorian Wechsung } 1730cb87ef4cSFlorian Wechsung } 1731cb87ef4cSFlorian Wechsung } 1732cb87ef4cSFlorian Wechsung } 1733cb87ef4cSFlorian Wechsung 1734cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 1735cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 1736cf818975SFlorian Wechsung * point. */ 1737cb87ef4cSFlorian Wechsung 1738*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutCreate(comm, &layout)); 1739*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned)); 1740*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(layout)); 1741*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRanges(layout, &cumSumVertices)); 17425dc86ac1SFlorian Wechsung 1743*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices)); 17445a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 1745cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 1746cb87ef4cSFlorian Wechsung counter = 0; 1747cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 1748cb87ef4cSFlorian Wechsung if (toBalance[i]) { 17497f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 1750cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 1751cb87ef4cSFlorian Wechsung counter++; 1752cb87ef4cSFlorian Wechsung } 1753cb87ef4cSFlorian Wechsung } 1754cb87ef4cSFlorian Wechsung } 1755cb87ef4cSFlorian Wechsung 1756cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 1757*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &leafGlobalNumbers)); 1758*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 1759*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE)); 1760cb87ef4cSFlorian Wechsung 17610faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 1762cb87ef4cSFlorian Wechsung 1763*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm, &Apre)); 1764*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(Apre, MATPREALLOCATOR)); 1765*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size])); 1766*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(Apre)); 17678c9a1619SFlorian Wechsung 17688c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17698c9a1619SFlorian Wechsung if (toBalance[i]) { 17700faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17710faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17720faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17730faf6628SFlorian Wechsung else continue; 1774*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES)); 1775*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES)); 17764baf1206SFlorian Wechsung } 17774baf1206SFlorian Wechsung } 17784baf1206SFlorian Wechsung 1779*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY)); 1780*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY)); 17814baf1206SFlorian Wechsung 1782*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm, &A)); 1783*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(A, MATMPIAIJ)); 1784*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size])); 1785*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatPreallocatorPreallocate(Apre, PETSC_FALSE, A)); 1786*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Apre)); 17874baf1206SFlorian Wechsung 17884baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 17894baf1206SFlorian Wechsung if (toBalance[i]) { 17900faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 17910faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 17920faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 17930faf6628SFlorian Wechsung else continue; 1794*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(A, idx, jdx, 1, INSERT_VALUES)); 1795*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(A, jdx, idx, 1, INSERT_VALUES)); 17960941debbSFlorian Wechsung } 17970941debbSFlorian Wechsung } 17988c9a1619SFlorian Wechsung 1799*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 1800*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 1801*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafGlobalNumbers)); 1802*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(globalNumbersOfLocalOwnedVertices)); 18034baf1206SFlorian Wechsung 180441525646SFlorian Wechsung nparts = size; 180541525646SFlorian Wechsung wgtflag = 2; 180641525646SFlorian Wechsung numflag = 0; 180741525646SFlorian Wechsung ncon = 2; 180841525646SFlorian Wechsung real_t *tpwgts; 1809*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ncon * nparts, &tpwgts)); 181041525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 181141525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 181241525646SFlorian Wechsung } 181341525646SFlorian Wechsung 1814*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ncon, &ubvec)); 181541525646SFlorian Wechsung ubvec[0] = 1.01; 18165a30b08bSFlorian Wechsung ubvec[1] = 1.01; 18178c9a1619SFlorian Wechsung lenadjncy = 0; 18188c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18198c9a1619SFlorian Wechsung PetscInt temp=0; 1820*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL)); 18218c9a1619SFlorian Wechsung lenadjncy += temp; 1822*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL)); 18238c9a1619SFlorian Wechsung } 1824*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lenadjncy, &adjncy)); 18257407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 1826*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lenxadj, &xadj)); 18270941debbSFlorian Wechsung xadj[0] = 0; 18288c9a1619SFlorian Wechsung counter = 0; 18298c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 18302953a68cSFlorian Wechsung PetscInt temp=0; 18312953a68cSFlorian Wechsung const PetscInt *cols; 1832*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL)); 1833*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&adjncy[counter], cols, temp)); 18348c9a1619SFlorian Wechsung counter += temp; 18350941debbSFlorian Wechsung xadj[i+1] = counter; 1836*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL)); 18378c9a1619SFlorian Wechsung } 18388c9a1619SFlorian Wechsung 1839*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part)); 1840*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt)); 184141525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 184241525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 184341525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 184441525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 184541525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 184641525646SFlorian Wechsung } 18478c9a1619SFlorian Wechsung 18485dc86ac1SFlorian Wechsung if (viewer) { 1849*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth)); 1850*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size])); 185112617df9SFlorian Wechsung } 185241525646SFlorian Wechsung if (parallel) { 1853*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(4, &options)); 18545a30b08bSFlorian Wechsung options[0] = 1; 18555a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 18565a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 18575a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 1858*5f80ce2aSJacob Faibussowitsch if (viewer) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n")); 18598c9a1619SFlorian Wechsung if (useInitialGuess) { 1860*5f80ce2aSJacob Faibussowitsch if (viewer) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n")); 18618c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 18625dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 1863*5f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 18648c9a1619SFlorian Wechsung PetscStackPop; 18658c9a1619SFlorian Wechsung } else { 18668c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 18675dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 18688c9a1619SFlorian Wechsung PetscStackPop; 1869*5f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 18708c9a1619SFlorian Wechsung } 1871*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(options)); 187241525646SFlorian Wechsung } else { 1873*5f80ce2aSJacob Faibussowitsch if (viewer) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n")); 187441525646SFlorian Wechsung Mat As; 187541525646SFlorian Wechsung PetscInt numRows; 187641525646SFlorian Wechsung PetscInt *partGlobal; 1877*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As)); 1878cb87ef4cSFlorian Wechsung 187941525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 1880*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &numExclusivelyOwnedAll)); 188141525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 1882*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm)); 1883cb87ef4cSFlorian Wechsung 1884*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(As, &numRows, NULL)); 1885*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numRows, &partGlobal)); 1886dd400576SPatrick Sanan if (rank == 0) { 188741525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 188841525646SFlorian Wechsung lenadjncy = 0; 188941525646SFlorian Wechsung 189041525646SFlorian Wechsung for (i=0; i<numRows; i++) { 189141525646SFlorian Wechsung PetscInt temp=0; 1892*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(As, i, &temp, NULL, NULL)); 189341525646SFlorian Wechsung lenadjncy += temp; 1894*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(As, i, &temp, NULL, NULL)); 189541525646SFlorian Wechsung } 1896*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lenadjncy, &adjncy_g)); 189741525646SFlorian Wechsung lenxadj = 1 + numRows; 1898*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(lenxadj, &xadj_g)); 189941525646SFlorian Wechsung xadj_g[0] = 0; 190041525646SFlorian Wechsung counter = 0; 190141525646SFlorian Wechsung for (i=0; i<numRows; i++) { 19022953a68cSFlorian Wechsung PetscInt temp=0; 19032953a68cSFlorian Wechsung const PetscInt *cols; 1904*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(As, i, &temp, &cols, NULL)); 1905*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(&adjncy_g[counter], cols, temp)); 190641525646SFlorian Wechsung counter += temp; 190741525646SFlorian Wechsung xadj_g[i+1] = counter; 1908*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(As, i, &temp, &cols, NULL)); 190941525646SFlorian Wechsung } 1910*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(2*numRows, &vtxwgt_g)); 191141525646SFlorian Wechsung for (i=0; i<size; i++) { 191241525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 191341525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 191441525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 191541525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 191641525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 191741525646SFlorian Wechsung } 191841525646SFlorian Wechsung } 1919*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(64, &options)); 192041525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 1921*5f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 192241525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 192341525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 192406b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 192541525646SFlorian Wechsung PetscStackPop; 1926*5f80ce2aSJacob Faibussowitsch PetscCheck(ierr == METIS_OK,PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 1927*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(options)); 1928*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj_g)); 1929*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy_g)); 1930*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vtxwgt_g)); 193141525646SFlorian Wechsung } 1932*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(numExclusivelyOwnedAll)); 193341525646SFlorian Wechsung 19345dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 19355dc86ac1SFlorian Wechsung { 193681a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 1937*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &counts)); 1938*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size+1, &mpiCumSumVertices)); 19395dc86ac1SFlorian Wechsung for (i=0; i<size; i++) { 1940*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]))); 194141525646SFlorian Wechsung } 194281a13b52SFlorian Wechsung for (i=0; i<=size; i++) { 1943*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]))); 194481a13b52SFlorian Wechsung } 1945*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm)); 1946*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(counts)); 1947*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(mpiCumSumVertices)); 19485dc86ac1SFlorian Wechsung } 19495dc86ac1SFlorian Wechsung 1950*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(partGlobal)); 1951*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&As)); 195241525646SFlorian Wechsung } 1953cb87ef4cSFlorian Wechsung 1954*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 1955*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ubvec)); 1956*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tpwgts)); 1957cb87ef4cSFlorian Wechsung 1958cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 1959cb87ef4cSFlorian Wechsung 1960*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &firstVertices)); 1961*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(size, &renumbering)); 1962cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 1963*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm)); 1964cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 1965cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 1966cb87ef4cSFlorian Wechsung } 1967cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 1968cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 1969cb87ef4cSFlorian Wechsung } 1970cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 1971cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 1972*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm)); 1973cb87ef4cSFlorian Wechsung 1974*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(firstVertices)); 1975*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(renumbering)); 19767f57c1a4SFlorian Wechsung 1977cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 1978*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 1979*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj)); 1980*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy)); 1981*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vtxwgt)); 1982*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(toBalance)); 1983*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isLeaf)); 1984*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isNonExclusivelyOwned)); 1985*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isExclusivelyOwned)); 1986*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(part)); 19877f57c1a4SFlorian Wechsung if (viewer) { 1988*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 1989*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 19907f57c1a4SFlorian Wechsung } 1991*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 19928b879b41SFlorian Wechsung PetscFunctionReturn(0); 1993cb87ef4cSFlorian Wechsung } 1994cb87ef4cSFlorian Wechsung 19957407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 19965dc86ac1SFlorian Wechsung if (viewer) { 1997*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth)); 1998*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Initial. ")); 1999*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer)); 2000*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "Rebalanced. ")); 2001*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 20027407ba93SFlorian Wechsung } 20037407ba93SFlorian Wechsung 2004cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 200541525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 2006cb87ef4cSFlorian Wechsung PetscInt loc = 0; 2007*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc)); 20087407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 2009cb87ef4cSFlorian Wechsung if (loc<0) { 201041525646SFlorian Wechsung part[i] = rank; 2011cb87ef4cSFlorian Wechsung } 2012cb87ef4cSFlorian Wechsung } 2013cb87ef4cSFlorian Wechsung 20147407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 20155dc86ac1SFlorian Wechsung if (viewer) { 2016*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "After. ")); 2017*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer)); 20187407ba93SFlorian Wechsung } 20197407ba93SFlorian Wechsung 2020*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 2021*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(xadj)); 2022*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adjncy)); 2023*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vtxwgt)); 2024cb87ef4cSFlorian Wechsung 20257f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 2026cf818975SFlorian Wechsung { 20277f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 2028*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite)); 20297f57c1a4SFlorian Wechsung counter = 0; 2030cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2031cb87ef4cSFlorian Wechsung if (toBalance[i]) { 2032cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 20337f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 2034cb87ef4cSFlorian Wechsung counter++; 2035cb87ef4cSFlorian Wechsung } 2036cb87ef4cSFlorian Wechsung } 2037cb87ef4cSFlorian Wechsung } 2038*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees)); 2039*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pointsToRewrite)); 2040cf818975SFlorian Wechsung } 2041cb87ef4cSFlorian Wechsung 2042*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(toBalance)); 2043*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isLeaf)); 2044*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isNonExclusivelyOwned)); 2045*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(isExclusivelyOwned)); 2046*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(part)); 20475dc86ac1SFlorian Wechsung if (viewer) { 2048*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 2049*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 20507d197802SFlorian Wechsung } 20518b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 2052*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0)); 2053b458e8f1SJose E. Roman PetscFunctionReturn(0); 2054240408d3SFlorian Wechsung #else 20555f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 205641525646SFlorian Wechsung #endif 2057cb87ef4cSFlorian Wechsung } 2058