1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h> 370034214SMatthew G. Knepley 477623264SMatthew G. Knepley PetscClassId PETSCPARTITIONER_CLASSID = 0; 577623264SMatthew G. Knepley 677623264SMatthew G. Knepley PetscFunctionList PetscPartitionerList = NULL; 777623264SMatthew G. Knepley PetscBool PetscPartitionerRegisterAllCalled = PETSC_FALSE; 877623264SMatthew G. Knepley 977623264SMatthew G. Knepley PetscBool ChacoPartitionercite = PETSC_FALSE; 1077623264SMatthew G. Knepley const char ChacoPartitionerCitation[] = "@inproceedings{Chaco95,\n" 1177623264SMatthew G. Knepley " author = {Bruce Hendrickson and Robert Leland},\n" 1277623264SMatthew G. Knepley " title = {A multilevel algorithm for partitioning graphs},\n" 1377623264SMatthew G. Knepley " booktitle = {Supercomputing '95: Proceedings of the 1995 ACM/IEEE Conference on Supercomputing (CDROM)}," 1477623264SMatthew G. Knepley " isbn = {0-89791-816-9},\n" 1577623264SMatthew G. Knepley " pages = {28},\n" 1677623264SMatthew G. Knepley " doi = {http://doi.acm.org/10.1145/224170.224228},\n" 1777623264SMatthew G. Knepley " publisher = {ACM Press},\n" 1877623264SMatthew G. Knepley " address = {New York},\n" 1977623264SMatthew G. Knepley " year = {1995}\n}\n"; 2077623264SMatthew G. Knepley 2177623264SMatthew G. Knepley PetscBool ParMetisPartitionercite = PETSC_FALSE; 2277623264SMatthew G. Knepley const char ParMetisPartitionerCitation[] = "@article{KarypisKumar98,\n" 2377623264SMatthew G. Knepley " author = {George Karypis and Vipin Kumar},\n" 2477623264SMatthew G. Knepley " title = {A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering},\n" 2577623264SMatthew G. Knepley " journal = {Journal of Parallel and Distributed Computing},\n" 2677623264SMatthew G. Knepley " volume = {48},\n" 2777623264SMatthew G. Knepley " pages = {71--85},\n" 2877623264SMatthew G. Knepley " year = {1998}\n}\n"; 2977623264SMatthew G. Knepley 300134a67bSLisandro Dalcin PETSC_STATIC_INLINE PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 310134a67bSLisandro Dalcin 32532c4e7dSMichael Lange /*@C 33532c4e7dSMichael Lange DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 34532c4e7dSMichael Lange 35532c4e7dSMichael Lange Input Parameters: 36532c4e7dSMichael Lange + dm - The mesh DM dm 37532c4e7dSMichael Lange - height - Height of the strata from which to construct the graph 38532c4e7dSMichael Lange 39532c4e7dSMichael Lange Output Parameter: 40532c4e7dSMichael Lange + numVertices - Number of vertices in the graph 413fa7752dSToby Isaac . offsets - Point offsets in the graph 423fa7752dSToby Isaac . adjacency - Point connectivity in the graph 433fa7752dSToby Isaac - 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. 44532c4e7dSMichael Lange 45b0441da4SMatthew G. Knepley The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 46532c4e7dSMichael Lange representation on the mesh. 47532c4e7dSMichael Lange 48532c4e7dSMichael Lange Level: developer 49532c4e7dSMichael Lange 50b0441da4SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 51532c4e7dSMichael Lange @*/ 523fa7752dSToby Isaac PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 53532c4e7dSMichael Lange { 54ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 55389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 568cfe4c1fSMichael Lange IS cellNumbering; 578cfe4c1fSMichael Lange const PetscInt *cellNum; 58532c4e7dSMichael Lange PetscBool useCone, useClosure; 59532c4e7dSMichael Lange PetscSection section; 60532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 618cfe4c1fSMichael Lange PetscSF sfPoint; 628f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 638f4e72b9SMatthew G. Knepley const PetscInt *local; 648f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 65532c4e7dSMichael Lange PetscMPIInt rank; 66532c4e7dSMichael Lange PetscErrorCode ierr; 67532c4e7dSMichael Lange 68532c4e7dSMichael Lange PetscFunctionBegin; 69532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 70ffbd6163SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 71ffbd6163SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 72ffbd6163SMatthew G. Knepley if (dim != depth) { 73ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 74ffbd6163SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 75ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 76ffbd6163SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 77ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 78ffbd6163SMatthew G. Knepley if (!*numVertices) { 79ffbd6163SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 80ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 81ffbd6163SMatthew G. Knepley } 82ffbd6163SMatthew G. Knepley /* Broken in parallel */ 83ffbd6163SMatthew G. Knepley if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 84ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 85ffbd6163SMatthew G. Knepley } 868cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 870134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 88532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 89532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 90532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 91532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 92532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 93b0441da4SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 94b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 950134a67bSLisandro Dalcin ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 963fa7752dSToby Isaac if (globalNumbering) { 973fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 983fa7752dSToby Isaac *globalNumbering = cellNumbering; 993fa7752dSToby Isaac } 1008cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 1018f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 1028f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 1038f4e72b9SMatthew G. Knepley */ 1040134a67bSLisandro Dalcin ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr); 1058f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1068f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1078f4e72b9SMatthew G. Knepley 1088f4e72b9SMatthew G. Knepley ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr); 1090134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 1108f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1118f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1128f4e72b9SMatthew G. Knepley const PetscInt *support; 1138f4e72b9SMatthew G. Knepley PetscInt supportSize; 1148f4e72b9SMatthew G. Knepley 1158f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 1168f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 1170134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1188f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 1198f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1200134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 1218f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1220134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1230134a67bSLisandro Dalcin } 1240134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1250134a67bSLisandro Dalcin if (supportSize > 2) { 1260134a67bSLisandro Dalcin PetscInt numChildren, i; 1270134a67bSLisandro Dalcin const PetscInt *children; 1280134a67bSLisandro Dalcin 1290134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr); 1300134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1310134a67bSLisandro Dalcin const PetscInt child = children[i]; 1320134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1330134a67bSLisandro Dalcin ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr); 1340134a67bSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr); 1350134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1360134a67bSLisandro Dalcin else if (supportSize == 2) { 1370134a67bSLisandro Dalcin ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1380134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 1390134a67bSLisandro Dalcin ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1400134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1410134a67bSLisandro Dalcin } 1420134a67bSLisandro Dalcin } 1430134a67bSLisandro Dalcin } 1448f4e72b9SMatthew G. Knepley } 1458f4e72b9SMatthew G. Knepley } 1468f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 1478f4e72b9SMatthew G. Knepley ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1488f4e72b9SMatthew G. Knepley ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1498f4e72b9SMatthew G. Knepley ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1508f4e72b9SMatthew G. Knepley ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1518f4e72b9SMatthew G. Knepley } 1528f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 1538cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 1548cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 1558cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 1568f4e72b9SMatthew G. Knepley /* Add remote cells */ 1578f4e72b9SMatthew G. Knepley if (remoteCells) { 1580134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 1590134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 1600134a67bSLisandro Dalcin const PetscInt *cone, *children; 1610134a67bSLisandro Dalcin 1628f4e72b9SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1638f4e72b9SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1648f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1650134a67bSLisandro Dalcin const PetscInt point = cone[c]; 1660134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 1678f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 1688f4e72b9SMatthew G. Knepley ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1698f4e72b9SMatthew G. Knepley ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1700134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 1710134a67bSLisandro Dalcin } 1720134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1730134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 1740134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1750134a67bSLisandro Dalcin const PetscInt child = children[i]; 1760134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 1770134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 1780134a67bSLisandro Dalcin ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1790134a67bSLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1800134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 1810134a67bSLisandro Dalcin } 1828f4e72b9SMatthew G. Knepley } 1838f4e72b9SMatthew G. Knepley } 1848f4e72b9SMatthew G. Knepley } 1858f4e72b9SMatthew G. Knepley /* Add local cells */ 186532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 187532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 188532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 189532c4e7dSMichael Lange const PetscInt point = adj[a]; 190532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 191532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 192532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 193532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1940134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 195532c4e7dSMichael Lange } 196532c4e7dSMichael Lange } 1978cfe4c1fSMichael Lange (*numVertices)++; 198532c4e7dSMichael Lange } 199*4e468a93SLisandro Dalcin ierr = PetscFree(adj);CHKERRQ(ierr); 2008f4e72b9SMatthew G. Knepley ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr); 201b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 202*4e468a93SLisandro Dalcin 203532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 204532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 205532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 206389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 20743f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 20843f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 20943f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 21043f7d02bSMichael Lange } 211532c4e7dSMichael Lange vOffsets[*numVertices] = size; 212389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 213*4e468a93SLisandro Dalcin 214*4e468a93SLisandro Dalcin if (nroots >= 0) { 215*4e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 216*4e468a93SLisandro Dalcin ierr = PetscSectionReset(section);CHKERRQ(ierr); 217*4e468a93SLisandro Dalcin ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr); 218*4e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 219*4e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 220*4e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 221*4e468a93SLisandro Dalcin ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr); 222*4e468a93SLisandro Dalcin ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr); 223*4e468a93SLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr); 224*4e468a93SLisandro Dalcin ierr = PetscMemcpy(edges, &graph[start], numEdges*sizeof(*edges));CHKERRQ(ierr); 225*4e468a93SLisandro Dalcin } 226*4e468a93SLisandro Dalcin ierr = PetscFree(vOffsets);CHKERRQ(ierr); 227*4e468a93SLisandro Dalcin ierr = PetscFree(graph);CHKERRQ(ierr); 228*4e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 229*4e468a93SLisandro Dalcin ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 230*4e468a93SLisandro Dalcin ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 231*4e468a93SLisandro Dalcin ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 232*4e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 233*4e468a93SLisandro Dalcin ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 234*4e468a93SLisandro Dalcin } 235*4e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 236*4e468a93SLisandro Dalcin ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 237*4e468a93SLisandro Dalcin } else { 238*4e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 239*4e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 240*4e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 241*4e468a93SLisandro Dalcin ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr); 242*4e468a93SLisandro Dalcin } 243*4e468a93SLisandro Dalcin } 244*4e468a93SLisandro Dalcin 245*4e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 246389e55d8SMichael Lange if (adjacency) *adjacency = graph; 247*4e468a93SLisandro Dalcin 248532c4e7dSMichael Lange /* Cleanup */ 249532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 250532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 251*4e468a93SLisandro Dalcin ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 252*4e468a93SLisandro Dalcin ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 253532c4e7dSMichael Lange PetscFunctionReturn(0); 254532c4e7dSMichael Lange } 255532c4e7dSMichael Lange 256d5577e40SMatthew G. Knepley /*@C 257d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 258d5577e40SMatthew G. Knepley 259d5577e40SMatthew G. Knepley Collective 260d5577e40SMatthew G. Knepley 261d5577e40SMatthew G. Knepley Input Arguments: 262d5577e40SMatthew G. Knepley + dm - The DMPlex 263d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 264d5577e40SMatthew G. Knepley 265d5577e40SMatthew G. Knepley Output Arguments: 266d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 267d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 268d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 269d5577e40SMatthew G. Knepley 270d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 271d5577e40SMatthew G. Knepley 272d5577e40SMatthew G. Knepley Level: advanced 273d5577e40SMatthew G. Knepley 274d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 275d5577e40SMatthew G. Knepley @*/ 27670034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 27770034214SMatthew G. Knepley { 27870034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 27970034214SMatthew G. Knepley PetscInt numFaceCases = 0; 28070034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 28170034214SMatthew G. Knepley PetscInt *off, *adj; 28270034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 28370034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 28470034214SMatthew G. Knepley PetscErrorCode ierr; 28570034214SMatthew G. Knepley 28670034214SMatthew G. Knepley PetscFunctionBegin; 28770034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 288c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 28970034214SMatthew G. Knepley cellDim = dim - cellHeight; 29070034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 29170034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 29270034214SMatthew G. Knepley if (cEnd - cStart == 0) { 29370034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 29470034214SMatthew G. Knepley if (offsets) *offsets = NULL; 29570034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 29670034214SMatthew G. Knepley PetscFunctionReturn(0); 29770034214SMatthew G. Knepley } 29870034214SMatthew G. Knepley numCells = cEnd - cStart; 29970034214SMatthew G. Knepley faceDepth = depth - cellHeight; 30070034214SMatthew G. Knepley if (dim == depth) { 30170034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 30270034214SMatthew G. Knepley 30370034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 30470034214SMatthew G. Knepley /* Count neighboring cells */ 30570034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 30670034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 30770034214SMatthew G. Knepley const PetscInt *support; 30870034214SMatthew G. Knepley PetscInt supportSize; 30970034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 31070034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 31170034214SMatthew G. Knepley if (supportSize == 2) { 3129ffc88e4SToby Isaac PetscInt numChildren; 3139ffc88e4SToby Isaac 3149ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 3159ffc88e4SToby Isaac if (!numChildren) { 31670034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 31770034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 31870034214SMatthew G. Knepley } 31970034214SMatthew G. Knepley } 3209ffc88e4SToby Isaac } 32170034214SMatthew G. Knepley /* Prefix sum */ 32270034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 32370034214SMatthew G. Knepley if (adjacency) { 32470034214SMatthew G. Knepley PetscInt *tmp; 32570034214SMatthew G. Knepley 32670034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 327854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 32870034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 32970034214SMatthew G. Knepley /* Get neighboring cells */ 33070034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 33170034214SMatthew G. Knepley const PetscInt *support; 33270034214SMatthew G. Knepley PetscInt supportSize; 33370034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 33470034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 33570034214SMatthew G. Knepley if (supportSize == 2) { 3369ffc88e4SToby Isaac PetscInt numChildren; 3379ffc88e4SToby Isaac 3389ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 3399ffc88e4SToby Isaac if (!numChildren) { 34070034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 34170034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 34270034214SMatthew G. Knepley } 34370034214SMatthew G. Knepley } 3449ffc88e4SToby Isaac } 34570034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 34670034214SMatthew G. Knepley for (c = 0; c < cEnd-cStart; ++c) if (tmp[c] != off[c+1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 34770034214SMatthew G. Knepley #endif 34870034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 34970034214SMatthew G. Knepley } 35070034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 35170034214SMatthew G. Knepley if (offsets) *offsets = off; 35270034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 35370034214SMatthew G. Knepley PetscFunctionReturn(0); 35470034214SMatthew G. Knepley } 35570034214SMatthew G. Knepley /* Setup face recognition */ 35670034214SMatthew G. Knepley if (faceDepth == 1) { 35770034214SMatthew 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 */ 35870034214SMatthew G. Knepley 35970034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 36070034214SMatthew G. Knepley PetscInt corners; 36170034214SMatthew G. Knepley 36270034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 36370034214SMatthew G. Knepley if (!cornersSeen[corners]) { 36470034214SMatthew G. Knepley PetscInt nFV; 36570034214SMatthew G. Knepley 36670034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 36770034214SMatthew G. Knepley cornersSeen[corners] = 1; 36870034214SMatthew G. Knepley 36970034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 37070034214SMatthew G. Knepley 37170034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 37270034214SMatthew G. Knepley } 37370034214SMatthew G. Knepley } 37470034214SMatthew G. Knepley } 37570034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 37670034214SMatthew G. Knepley /* Count neighboring cells */ 37770034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 37870034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 37970034214SMatthew G. Knepley 3808b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 38170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 38270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 38370034214SMatthew G. Knepley PetscInt cellPair[2]; 38470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 38570034214SMatthew G. Knepley PetscInt meetSize = 0; 38670034214SMatthew G. Knepley const PetscInt *meet = NULL; 38770034214SMatthew G. Knepley 38870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 38970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 39070034214SMatthew G. Knepley if (!found) { 39170034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 39270034214SMatthew G. Knepley if (meetSize) { 39370034214SMatthew G. Knepley PetscInt f; 39470034214SMatthew G. Knepley 39570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 39670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 39770034214SMatthew G. Knepley found = PETSC_TRUE; 39870034214SMatthew G. Knepley break; 39970034214SMatthew G. Knepley } 40070034214SMatthew G. Knepley } 40170034214SMatthew G. Knepley } 40270034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 40370034214SMatthew G. Knepley } 40470034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 40570034214SMatthew G. Knepley } 40670034214SMatthew G. Knepley } 40770034214SMatthew G. Knepley /* Prefix sum */ 40870034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 40970034214SMatthew G. Knepley 41070034214SMatthew G. Knepley if (adjacency) { 41170034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 41270034214SMatthew G. Knepley /* Get neighboring cells */ 41370034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 41470034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 41570034214SMatthew G. Knepley PetscInt cellOffset = 0; 41670034214SMatthew G. Knepley 4178b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 41870034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 41970034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 42070034214SMatthew G. Knepley PetscInt cellPair[2]; 42170034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 42270034214SMatthew G. Knepley PetscInt meetSize = 0; 42370034214SMatthew G. Knepley const PetscInt *meet = NULL; 42470034214SMatthew G. Knepley 42570034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 42670034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 42770034214SMatthew G. Knepley if (!found) { 42870034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 42970034214SMatthew G. Knepley if (meetSize) { 43070034214SMatthew G. Knepley PetscInt f; 43170034214SMatthew G. Knepley 43270034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 43370034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 43470034214SMatthew G. Knepley found = PETSC_TRUE; 43570034214SMatthew G. Knepley break; 43670034214SMatthew G. Knepley } 43770034214SMatthew G. Knepley } 43870034214SMatthew G. Knepley } 43970034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 44070034214SMatthew G. Knepley } 44170034214SMatthew G. Knepley if (found) { 44270034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 44370034214SMatthew G. Knepley ++cellOffset; 44470034214SMatthew G. Knepley } 44570034214SMatthew G. Knepley } 44670034214SMatthew G. Knepley } 44770034214SMatthew G. Knepley } 44870034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 44970034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 45070034214SMatthew G. Knepley if (offsets) *offsets = off; 45170034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 45270034214SMatthew G. Knepley PetscFunctionReturn(0); 45370034214SMatthew G. Knepley } 45470034214SMatthew G. Knepley 45577623264SMatthew G. Knepley /*@C 45677623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 45777623264SMatthew G. Knepley 45877623264SMatthew G. Knepley Not Collective 45977623264SMatthew G. Knepley 46077623264SMatthew G. Knepley Input Parameters: 46177623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 46277623264SMatthew G. Knepley - create_func - The creation routine itself 46377623264SMatthew G. Knepley 46477623264SMatthew G. Knepley Notes: 46577623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 46677623264SMatthew G. Knepley 46777623264SMatthew G. Knepley Sample usage: 46877623264SMatthew G. Knepley .vb 46977623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 47077623264SMatthew G. Knepley .ve 47177623264SMatthew G. Knepley 47277623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 47377623264SMatthew G. Knepley .vb 47477623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 47577623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 47677623264SMatthew G. Knepley .ve 47777623264SMatthew G. Knepley or at runtime via the option 47877623264SMatthew G. Knepley .vb 47977623264SMatthew G. Knepley -petscpartitioner_type my_part 48077623264SMatthew G. Knepley .ve 48177623264SMatthew G. Knepley 48277623264SMatthew G. Knepley Level: advanced 48377623264SMatthew G. Knepley 48477623264SMatthew G. Knepley .keywords: PetscPartitioner, register 48577623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 48677623264SMatthew G. Knepley 48777623264SMatthew G. Knepley @*/ 48877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 48977623264SMatthew G. Knepley { 49077623264SMatthew G. Knepley PetscErrorCode ierr; 49177623264SMatthew G. Knepley 49277623264SMatthew G. Knepley PetscFunctionBegin; 49377623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 49477623264SMatthew G. Knepley PetscFunctionReturn(0); 49577623264SMatthew G. Knepley } 49677623264SMatthew G. Knepley 49777623264SMatthew G. Knepley /*@C 49877623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 49977623264SMatthew G. Knepley 50077623264SMatthew G. Knepley Collective on PetscPartitioner 50177623264SMatthew G. Knepley 50277623264SMatthew G. Knepley Input Parameters: 50377623264SMatthew G. Knepley + part - The PetscPartitioner object 50477623264SMatthew G. Knepley - name - The kind of partitioner 50577623264SMatthew G. Knepley 50677623264SMatthew G. Knepley Options Database Key: 50777623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 50877623264SMatthew G. Knepley 50977623264SMatthew G. Knepley Level: intermediate 51077623264SMatthew G. Knepley 51177623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 51277623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 51377623264SMatthew G. Knepley @*/ 51477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 51577623264SMatthew G. Knepley { 51677623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 51777623264SMatthew G. Knepley PetscBool match; 51877623264SMatthew G. Knepley PetscErrorCode ierr; 51977623264SMatthew G. Knepley 52077623264SMatthew G. Knepley PetscFunctionBegin; 52177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 52277623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 52377623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 52477623264SMatthew G. Knepley 5250f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 52677623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 52777623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 52877623264SMatthew G. Knepley 52977623264SMatthew G. Knepley if (part->ops->destroy) { 53077623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 53177623264SMatthew G. Knepley } 53209161815SVaclav Hapla ierr = PetscMemzero(part->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 53377623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 53477623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 53577623264SMatthew G. Knepley PetscFunctionReturn(0); 53677623264SMatthew G. Knepley } 53777623264SMatthew G. Knepley 53877623264SMatthew G. Knepley /*@C 53977623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 54077623264SMatthew G. Knepley 54177623264SMatthew G. Knepley Not Collective 54277623264SMatthew G. Knepley 54377623264SMatthew G. Knepley Input Parameter: 54477623264SMatthew G. Knepley . part - The PetscPartitioner 54577623264SMatthew G. Knepley 54677623264SMatthew G. Knepley Output Parameter: 54777623264SMatthew G. Knepley . name - The PetscPartitioner type name 54877623264SMatthew G. Knepley 54977623264SMatthew G. Knepley Level: intermediate 55077623264SMatthew G. Knepley 55177623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 55277623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 55377623264SMatthew G. Knepley @*/ 55477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 55577623264SMatthew G. Knepley { 55677623264SMatthew G. Knepley PetscErrorCode ierr; 55777623264SMatthew G. Knepley 55877623264SMatthew G. Knepley PetscFunctionBegin; 55977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 56077623264SMatthew G. Knepley PetscValidPointer(name, 2); 5610f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 56277623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 56377623264SMatthew G. Knepley PetscFunctionReturn(0); 56477623264SMatthew G. Knepley } 56577623264SMatthew G. Knepley 56677623264SMatthew G. Knepley /*@C 56777623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 56877623264SMatthew G. Knepley 56977623264SMatthew G. Knepley Collective on PetscPartitioner 57077623264SMatthew G. Knepley 57177623264SMatthew G. Knepley Input Parameter: 57277623264SMatthew G. Knepley + part - the PetscPartitioner object to view 57377623264SMatthew G. Knepley - v - the viewer 57477623264SMatthew G. Knepley 57577623264SMatthew G. Knepley Level: developer 57677623264SMatthew G. Knepley 57777623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 57877623264SMatthew G. Knepley @*/ 57977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 58077623264SMatthew G. Knepley { 581ffc59708SMatthew G. Knepley PetscMPIInt size; 5822abdaa70SMatthew G. Knepley PetscBool isascii; 58377623264SMatthew G. Knepley PetscErrorCode ierr; 58477623264SMatthew G. Knepley 58577623264SMatthew G. Knepley PetscFunctionBegin; 58677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 58777623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 5882abdaa70SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 5892abdaa70SMatthew G. Knepley if (isascii) { 5902abdaa70SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 591ffc59708SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");CHKERRQ(ierr); 5922abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " type: %s\n", part->hdr.type_name);CHKERRQ(ierr); 5932abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 5942abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "edge cut: %D\n", part->edgeCut);CHKERRQ(ierr); 5952abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "balance: %.2g\n", part->balance);CHKERRQ(ierr); 5962abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 5972abdaa70SMatthew G. Knepley } 59877623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 59977623264SMatthew G. Knepley PetscFunctionReturn(0); 60077623264SMatthew G. Knepley } 60177623264SMatthew G. Knepley 602a0058e54SToby Isaac static PetscErrorCode PetscPartitionerGetDefaultType(const char *currentType, const char **defaultType) 603a0058e54SToby Isaac { 604a0058e54SToby Isaac PetscFunctionBegin; 605a0058e54SToby Isaac if (!currentType) { 606a0058e54SToby Isaac #if defined(PETSC_HAVE_CHACO) 607a0058e54SToby Isaac *defaultType = PETSCPARTITIONERCHACO; 608a0058e54SToby Isaac #elif defined(PETSC_HAVE_PARMETIS) 609a0058e54SToby Isaac *defaultType = PETSCPARTITIONERPARMETIS; 610137cd93aSLisandro Dalcin #elif defined(PETSC_HAVE_PTSCOTCH) 611137cd93aSLisandro Dalcin *defaultType = PETSCPARTITIONERPTSCOTCH; 612a0058e54SToby Isaac #else 613a0058e54SToby Isaac *defaultType = PETSCPARTITIONERSIMPLE; 614a0058e54SToby Isaac #endif 615a0058e54SToby Isaac } else { 616a0058e54SToby Isaac *defaultType = currentType; 617a0058e54SToby Isaac } 618a0058e54SToby Isaac PetscFunctionReturn(0); 619a0058e54SToby Isaac } 620a0058e54SToby Isaac 62177623264SMatthew G. Knepley /*@ 62277623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 62377623264SMatthew G. Knepley 62477623264SMatthew G. Knepley Collective on PetscPartitioner 62577623264SMatthew G. Knepley 62677623264SMatthew G. Knepley Input Parameter: 62777623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 62877623264SMatthew G. Knepley 62977623264SMatthew G. Knepley Level: developer 63077623264SMatthew G. Knepley 63177623264SMatthew G. Knepley .seealso: PetscPartitionerView() 63277623264SMatthew G. Knepley @*/ 63377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 63477623264SMatthew G. Knepley { 6356bb9daa8SLisandro Dalcin const char *defaultType; 6366bb9daa8SLisandro Dalcin char name[256]; 6376bb9daa8SLisandro Dalcin PetscBool flg; 63877623264SMatthew G. Knepley PetscErrorCode ierr; 63977623264SMatthew G. Knepley 64077623264SMatthew G. Knepley PetscFunctionBegin; 64177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 6426bb9daa8SLisandro Dalcin ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 6436bb9daa8SLisandro Dalcin ierr = PetscPartitionerGetDefaultType(((PetscObject) part)->type_name,&defaultType);CHKERRQ(ierr); 64477623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 6456bb9daa8SLisandro Dalcin ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, sizeof(name), &flg);CHKERRQ(ierr); 6466bb9daa8SLisandro Dalcin if (flg) { 6476bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 6486bb9daa8SLisandro Dalcin } else if (!((PetscObject) part)->type_name) { 6496bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 6506bb9daa8SLisandro Dalcin } 6516bb9daa8SLisandro Dalcin if (part->ops->setfromoptions) { 6526bb9daa8SLisandro Dalcin ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr); 6536bb9daa8SLisandro Dalcin } 654783e1fb6SStefano Zampini ierr = PetscViewerDestroy(&part->viewerGraph);CHKERRQ(ierr); 6550358368aSMatthew G. Knepley ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, &part->formatGraph, &part->viewGraph);CHKERRQ(ierr); 65677623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 6570633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 65877623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 65977623264SMatthew G. Knepley PetscFunctionReturn(0); 66077623264SMatthew G. Knepley } 66177623264SMatthew G. Knepley 66277623264SMatthew G. Knepley /*@C 66377623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 66477623264SMatthew G. Knepley 66577623264SMatthew G. Knepley Collective on PetscPartitioner 66677623264SMatthew G. Knepley 66777623264SMatthew G. Knepley Input Parameter: 66877623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 66977623264SMatthew G. Knepley 67077623264SMatthew G. Knepley Level: developer 67177623264SMatthew G. Knepley 67277623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 67377623264SMatthew G. Knepley @*/ 67477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 67577623264SMatthew G. Knepley { 67677623264SMatthew G. Knepley PetscErrorCode ierr; 67777623264SMatthew G. Knepley 67877623264SMatthew G. Knepley PetscFunctionBegin; 67977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 68077623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 68177623264SMatthew G. Knepley PetscFunctionReturn(0); 68277623264SMatthew G. Knepley } 68377623264SMatthew G. Knepley 68477623264SMatthew G. Knepley /*@ 68577623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 68677623264SMatthew G. Knepley 68777623264SMatthew G. Knepley Collective on PetscPartitioner 68877623264SMatthew G. Knepley 68977623264SMatthew G. Knepley Input Parameter: 69077623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 69177623264SMatthew G. Knepley 69277623264SMatthew G. Knepley Level: developer 69377623264SMatthew G. Knepley 69477623264SMatthew G. Knepley .seealso: PetscPartitionerView() 69577623264SMatthew G. Knepley @*/ 69677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 69777623264SMatthew G. Knepley { 69877623264SMatthew G. Knepley PetscErrorCode ierr; 69977623264SMatthew G. Knepley 70077623264SMatthew G. Knepley PetscFunctionBegin; 70177623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 70277623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 70377623264SMatthew G. Knepley 70477623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 70577623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 70677623264SMatthew G. Knepley 7070358368aSMatthew G. Knepley ierr = PetscViewerDestroy(&(*part)->viewerGraph);CHKERRQ(ierr); 70877623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 70977623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 71077623264SMatthew G. Knepley PetscFunctionReturn(0); 71177623264SMatthew G. Knepley } 71277623264SMatthew G. Knepley 71377623264SMatthew G. Knepley /*@ 71477623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 71577623264SMatthew G. Knepley 71677623264SMatthew G. Knepley Collective on MPI_Comm 71777623264SMatthew G. Knepley 71877623264SMatthew G. Knepley Input Parameter: 71977623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 72077623264SMatthew G. Knepley 72177623264SMatthew G. Knepley Output Parameter: 72277623264SMatthew G. Knepley . part - The PetscPartitioner object 72377623264SMatthew G. Knepley 72477623264SMatthew G. Knepley Level: beginner 72577623264SMatthew G. Knepley 726dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 72777623264SMatthew G. Knepley @*/ 72877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 72977623264SMatthew G. Knepley { 73077623264SMatthew G. Knepley PetscPartitioner p; 731a0058e54SToby Isaac const char *partitionerType = NULL; 73277623264SMatthew G. Knepley PetscErrorCode ierr; 73377623264SMatthew G. Knepley 73477623264SMatthew G. Knepley PetscFunctionBegin; 73577623264SMatthew G. Knepley PetscValidPointer(part, 2); 73677623264SMatthew G. Knepley *part = NULL; 73783cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 73877623264SMatthew G. Knepley 73973107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 740a0058e54SToby Isaac ierr = PetscPartitionerGetDefaultType(NULL,&partitionerType);CHKERRQ(ierr); 741a0058e54SToby Isaac ierr = PetscPartitionerSetType(p,partitionerType);CHKERRQ(ierr); 74277623264SMatthew G. Knepley 74372379da4SMatthew G. Knepley p->edgeCut = 0; 74472379da4SMatthew G. Knepley p->balance = 0.0; 74572379da4SMatthew G. Knepley 74677623264SMatthew G. Knepley *part = p; 74777623264SMatthew G. Knepley PetscFunctionReturn(0); 74877623264SMatthew G. Knepley } 74977623264SMatthew G. Knepley 75077623264SMatthew G. Knepley /*@ 75177623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 75277623264SMatthew G. Knepley 75377623264SMatthew G. Knepley Collective on DM 75477623264SMatthew G. Knepley 75577623264SMatthew G. Knepley Input Parameters: 75677623264SMatthew G. Knepley + part - The PetscPartitioner 757f8987ae8SMichael Lange - dm - The mesh DM 75877623264SMatthew G. Knepley 75977623264SMatthew G. Knepley Output Parameters: 76077623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 761f8987ae8SMichael Lange - partition - The list of points by partition 76277623264SMatthew G. Knepley 7630358368aSMatthew G. Knepley Options Database: 7640358368aSMatthew G. Knepley . -petscpartitioner_view_graph - View the graph we are partitioning 7650358368aSMatthew G. Knepley 76677623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 76777623264SMatthew G. Knepley 76877623264SMatthew G. Knepley Level: developer 76977623264SMatthew G. Knepley 77077623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 7714b15ede2SMatthew G. Knepley @*/ 772f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 77377623264SMatthew G. Knepley { 77477623264SMatthew G. Knepley PetscMPIInt size; 77577623264SMatthew G. Knepley PetscErrorCode ierr; 77677623264SMatthew G. Knepley 77777623264SMatthew G. Knepley PetscFunctionBegin; 77877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 77977623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 78077623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 78177623264SMatthew G. Knepley PetscValidPointer(partition, 5); 78277623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 78377623264SMatthew G. Knepley if (size == 1) { 78477623264SMatthew G. Knepley PetscInt *points; 78577623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 78677623264SMatthew G. Knepley 78777623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 78877623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 78977623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 79077623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 79177623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 79277623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 79377623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 79477623264SMatthew G. Knepley PetscFunctionReturn(0); 79577623264SMatthew G. Knepley } 79677623264SMatthew G. Knepley if (part->height == 0) { 79777623264SMatthew G. Knepley PetscInt numVertices; 79877623264SMatthew G. Knepley PetscInt *start = NULL; 79977623264SMatthew G. Knepley PetscInt *adjacency = NULL; 8003fa7752dSToby Isaac IS globalNumbering; 80177623264SMatthew G. Knepley 8023fa7752dSToby Isaac ierr = DMPlexCreatePartitionerGraph(dm, 0, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 8030358368aSMatthew G. Knepley if (part->viewGraph) { 8040358368aSMatthew G. Knepley PetscViewer viewer = part->viewerGraph; 8050358368aSMatthew G. Knepley PetscBool isascii; 8060358368aSMatthew G. Knepley PetscInt v, i; 8070358368aSMatthew G. Knepley PetscMPIInt rank; 8080358368aSMatthew G. Knepley 8090358368aSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRQ(ierr); 8100358368aSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 8110358368aSMatthew G. Knepley if (isascii) { 8120358368aSMatthew G. Knepley ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 8130358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);CHKERRQ(ierr); 8140358368aSMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 8150358368aSMatthew G. Knepley const PetscInt s = start[v]; 8160358368aSMatthew G. Knepley const PetscInt e = start[v+1]; 8170358368aSMatthew G. Knepley 8180358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank);CHKERRQ(ierr); 8190358368aSMatthew G. Knepley for (i = s; i < e; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);CHKERRQ(ierr);} 8200358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);CHKERRQ(ierr); 8210358368aSMatthew G. Knepley } 8220358368aSMatthew G. Knepley ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 8230358368aSMatthew G. Knepley ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 8240358368aSMatthew G. Knepley } 8250358368aSMatthew G. Knepley } 82677623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 82777623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 82877623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 82977623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 8303fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 8313fa7752dSToby Isaac const PetscInt *globalNum; 8323fa7752dSToby Isaac const PetscInt *partIdx; 8333fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 8343fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 8353fa7752dSToby Isaac IS newPartition; 8363fa7752dSToby Isaac 8373fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 8383fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 8393fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 8403fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 8413fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 8423fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 8433fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 8443fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 8453fa7752dSToby Isaac } 8463fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 8473fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 8483fa7752dSToby Isaac } 8493fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 8503fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 8513fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 8523fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 8533fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 8543fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 8553fa7752dSToby Isaac *partition = newPartition; 8563fa7752dSToby Isaac } 85777623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 8582abdaa70SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 85977623264SMatthew G. Knepley PetscFunctionReturn(0); 86077623264SMatthew G. Knepley } 86177623264SMatthew G. Knepley 862d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 86377623264SMatthew G. Knepley { 86477623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 86577623264SMatthew G. Knepley PetscErrorCode ierr; 86677623264SMatthew G. Knepley 86777623264SMatthew G. Knepley PetscFunctionBegin; 86877623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 86977623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 87077623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 87177623264SMatthew G. Knepley PetscFunctionReturn(0); 87277623264SMatthew G. Knepley } 87377623264SMatthew G. Knepley 874d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 87577623264SMatthew G. Knepley { 876077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 87777623264SMatthew G. Knepley PetscErrorCode ierr; 87877623264SMatthew G. Knepley 87977623264SMatthew G. Knepley PetscFunctionBegin; 880077101c0SMatthew G. Knepley if (p->random) { 881077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 882077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 883077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 884077101c0SMatthew G. Knepley } 88577623264SMatthew G. Knepley PetscFunctionReturn(0); 88677623264SMatthew G. Knepley } 88777623264SMatthew G. Knepley 888d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 88977623264SMatthew G. Knepley { 89077623264SMatthew G. Knepley PetscBool iascii; 89177623264SMatthew G. Knepley PetscErrorCode ierr; 89277623264SMatthew G. Knepley 89377623264SMatthew G. Knepley PetscFunctionBegin; 89477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 89577623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 89677623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 89777623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 89877623264SMatthew G. Knepley PetscFunctionReturn(0); 89977623264SMatthew G. Knepley } 90077623264SMatthew G. Knepley 901d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 902077101c0SMatthew G. Knepley { 903077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 904077101c0SMatthew G. Knepley PetscErrorCode ierr; 905077101c0SMatthew G. Knepley 906077101c0SMatthew G. Knepley PetscFunctionBegin; 907077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 908077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 909077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 910077101c0SMatthew G. Knepley PetscFunctionReturn(0); 911077101c0SMatthew G. Knepley } 912077101c0SMatthew G. Knepley 913d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 91477623264SMatthew G. Knepley { 91577623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 91677623264SMatthew G. Knepley PetscInt np; 91777623264SMatthew G. Knepley PetscErrorCode ierr; 91877623264SMatthew G. Knepley 91977623264SMatthew G. Knepley PetscFunctionBegin; 920077101c0SMatthew G. Knepley if (p->random) { 921077101c0SMatthew G. Knepley PetscRandom r; 922aa1d5631SMatthew G. Knepley PetscInt *sizes, *points, v, p; 923aa1d5631SMatthew G. Knepley PetscMPIInt rank; 924077101c0SMatthew G. Knepley 925aa1d5631SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 926077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 927c717d290SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 928077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 929077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 930aa1d5631SMatthew G. Knepley for (v = 0; v < numVertices; ++v) {points[v] = v;} 931ac9a96f1SMichael Lange for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 932aa1d5631SMatthew G. Knepley for (v = numVertices-1; v > 0; --v) { 933077101c0SMatthew G. Knepley PetscReal val; 934aa1d5631SMatthew G. Knepley PetscInt w, tmp; 935077101c0SMatthew G. Knepley 936aa1d5631SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 937077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 938aa1d5631SMatthew G. Knepley w = PetscFloorReal(val); 939aa1d5631SMatthew G. Knepley tmp = points[v]; 940aa1d5631SMatthew G. Knepley points[v] = points[w]; 941aa1d5631SMatthew G. Knepley points[w] = tmp; 942077101c0SMatthew G. Knepley } 943077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 944077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 945077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 946077101c0SMatthew G. Knepley } 947c717d290SMatthew G. Knepley if (!p->section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 94877623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 94977623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 95077623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 95177623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 9525680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 95377623264SMatthew G. Knepley *partition = p->partition; 95477623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 95577623264SMatthew G. Knepley PetscFunctionReturn(0); 95677623264SMatthew G. Knepley } 95777623264SMatthew G. Knepley 958d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 95977623264SMatthew G. Knepley { 96077623264SMatthew G. Knepley PetscFunctionBegin; 96177623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 962077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 96377623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 96477623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 96577623264SMatthew G. Knepley PetscFunctionReturn(0); 96677623264SMatthew G. Knepley } 96777623264SMatthew G. Knepley 96877623264SMatthew G. Knepley /*MC 96977623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 97077623264SMatthew G. Knepley 97177623264SMatthew G. Knepley Level: intermediate 97277623264SMatthew G. Knepley 97377623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 97477623264SMatthew G. Knepley M*/ 97577623264SMatthew G. Knepley 97677623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 97777623264SMatthew G. Knepley { 97877623264SMatthew G. Knepley PetscPartitioner_Shell *p; 97977623264SMatthew G. Knepley PetscErrorCode ierr; 98077623264SMatthew G. Knepley 98177623264SMatthew G. Knepley PetscFunctionBegin; 98277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 98377623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 98477623264SMatthew G. Knepley part->data = p; 98577623264SMatthew G. Knepley 98677623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 987077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 98877623264SMatthew G. Knepley PetscFunctionReturn(0); 98977623264SMatthew G. Knepley } 99077623264SMatthew G. Knepley 9915680f57bSMatthew G. Knepley /*@C 9925680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 9935680f57bSMatthew G. Knepley 994077101c0SMatthew G. Knepley Collective on Part 9955680f57bSMatthew G. Knepley 9965680f57bSMatthew G. Knepley Input Parameters: 9975680f57bSMatthew G. Knepley + part - The PetscPartitioner 9989852e123SBarry Smith . size - The number of partitions 9999852e123SBarry Smith . sizes - array of size size (or NULL) providing the number of points in each partition 10009758bf69SToby Isaac - points - array of size sum(sizes) (may be NULL iff sizes is NULL), a permutation of the points that groups those assigned to each partition in order (i.e., partition 0 first, partition 1 next, etc.) 10015680f57bSMatthew G. Knepley 10025680f57bSMatthew G. Knepley Level: developer 10035680f57bSMatthew G. Knepley 1004b7e49471SLawrence Mitchell Notes: 1005b7e49471SLawrence Mitchell 1006b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 1007b7e49471SLawrence Mitchell 10085680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 10095680f57bSMatthew G. Knepley @*/ 10109852e123SBarry Smith PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 10115680f57bSMatthew G. Knepley { 10125680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 10135680f57bSMatthew G. Knepley PetscInt proc, numPoints; 10145680f57bSMatthew G. Knepley PetscErrorCode ierr; 10155680f57bSMatthew G. Knepley 10165680f57bSMatthew G. Knepley PetscFunctionBegin; 10175680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 10185680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 1019c717d290SMatthew G. Knepley if (points) {PetscValidPointer(points, 4);} 10205680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 10215680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 10225680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 10239852e123SBarry Smith ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 10245680f57bSMatthew G. Knepley if (sizes) { 10259852e123SBarry Smith for (proc = 0; proc < size; ++proc) { 10265680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 10275680f57bSMatthew G. Knepley } 10285680f57bSMatthew G. Knepley } 10295680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 10305680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 10315680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 10325680f57bSMatthew G. Knepley PetscFunctionReturn(0); 10335680f57bSMatthew G. Knepley } 10345680f57bSMatthew G. Knepley 1035077101c0SMatthew G. Knepley /*@ 1036077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 1037077101c0SMatthew G. Knepley 1038077101c0SMatthew G. Knepley Collective on Part 1039077101c0SMatthew G. Knepley 1040077101c0SMatthew G. Knepley Input Parameters: 1041077101c0SMatthew G. Knepley + part - The PetscPartitioner 1042077101c0SMatthew G. Knepley - random - The flag to use a random partition 1043077101c0SMatthew G. Knepley 1044077101c0SMatthew G. Knepley Level: intermediate 1045077101c0SMatthew G. Knepley 1046077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 1047077101c0SMatthew G. Knepley @*/ 1048077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 1049077101c0SMatthew G. Knepley { 1050077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1051077101c0SMatthew G. Knepley 1052077101c0SMatthew G. Knepley PetscFunctionBegin; 1053077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1054077101c0SMatthew G. Knepley p->random = random; 1055077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1056077101c0SMatthew G. Knepley } 1057077101c0SMatthew G. Knepley 1058077101c0SMatthew G. Knepley /*@ 1059077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 1060077101c0SMatthew G. Knepley 1061077101c0SMatthew G. Knepley Collective on Part 1062077101c0SMatthew G. Knepley 1063077101c0SMatthew G. Knepley Input Parameter: 1064077101c0SMatthew G. Knepley . part - The PetscPartitioner 1065077101c0SMatthew G. Knepley 1066077101c0SMatthew G. Knepley Output Parameter 1067077101c0SMatthew G. Knepley . random - The flag to use a random partition 1068077101c0SMatthew G. Knepley 1069077101c0SMatthew G. Knepley Level: intermediate 1070077101c0SMatthew G. Knepley 1071077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 1072077101c0SMatthew G. Knepley @*/ 1073077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 1074077101c0SMatthew G. Knepley { 1075077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1076077101c0SMatthew G. Knepley 1077077101c0SMatthew G. Knepley PetscFunctionBegin; 1078077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1079077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 1080077101c0SMatthew G. Knepley *random = p->random; 1081077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1082077101c0SMatthew G. Knepley } 1083077101c0SMatthew G. Knepley 1084d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 1085555a9cf8SMatthew G. Knepley { 1086555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 1087555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1088555a9cf8SMatthew G. Knepley 1089555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1090555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 1091555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1092555a9cf8SMatthew G. Knepley } 1093555a9cf8SMatthew G. Knepley 1094d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 1095555a9cf8SMatthew G. Knepley { 1096555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1097555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1098555a9cf8SMatthew G. Knepley } 1099555a9cf8SMatthew G. Knepley 1100d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 1101555a9cf8SMatthew G. Knepley { 1102555a9cf8SMatthew G. Knepley PetscBool iascii; 1103555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1104555a9cf8SMatthew G. Knepley 1105555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1106555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1107555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1108555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1109555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 1110555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1111555a9cf8SMatthew G. Knepley } 1112555a9cf8SMatthew G. Knepley 1113d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1114555a9cf8SMatthew G. Knepley { 1115cead94edSToby Isaac MPI_Comm comm; 1116555a9cf8SMatthew G. Knepley PetscInt np; 1117cead94edSToby Isaac PetscMPIInt size; 1118555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1119555a9cf8SMatthew G. Knepley 1120555a9cf8SMatthew G. Knepley PetscFunctionBegin; 112104ba2274SStefano Zampini comm = PetscObjectComm((PetscObject)part); 1122cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1123555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1124555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1125cead94edSToby Isaac if (size == 1) { 1126cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 112704ba2274SStefano Zampini } else { 1128cead94edSToby Isaac PetscMPIInt rank; 1129cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 1130cead94edSToby Isaac 1131a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1132cead94edSToby Isaac offsets[0] = 0; 1133cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1134cead94edSToby Isaac for (np = 2; np <= size; np++) { 1135cead94edSToby Isaac offsets[np] += offsets[np-1]; 1136cead94edSToby Isaac } 1137cead94edSToby Isaac nvGlobal = offsets[size]; 1138cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1139cead94edSToby Isaac myFirst = offsets[rank]; 1140cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1141cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1142cead94edSToby Isaac if (numVertices) { 1143cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1144cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1145cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1146cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1147cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1148cead94edSToby Isaac 1149cead94edSToby Isaac 1150cead94edSToby Isaac if (rem) { 1151cead94edSToby Isaac firstLargePart = myFirst / pBig; 1152cead94edSToby Isaac lastLargePart = myLast / pBig; 1153cead94edSToby Isaac 1154cead94edSToby Isaac if (firstLargePart < rem) { 1155cead94edSToby Isaac firstPart = firstLargePart; 115604ba2274SStefano Zampini } else { 1157cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1158cead94edSToby Isaac } 1159cead94edSToby Isaac if (lastLargePart < rem) { 1160cead94edSToby Isaac lastPart = lastLargePart; 116104ba2274SStefano Zampini } else { 1162cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1163cead94edSToby Isaac } 116404ba2274SStefano Zampini } else { 1165cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1166cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1167cead94edSToby Isaac } 1168cead94edSToby Isaac 1169cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1170cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1171cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1172cead94edSToby Isaac 1173cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1174cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1175cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1176cead94edSToby Isaac } 1177cead94edSToby Isaac } 1178cead94edSToby Isaac } 1179cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1180555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1181555a9cf8SMatthew G. Knepley } 1182555a9cf8SMatthew G. Knepley 1183d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1184555a9cf8SMatthew G. Knepley { 1185555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1186555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1187555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1188555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1189555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1190555a9cf8SMatthew G. Knepley } 1191555a9cf8SMatthew G. Knepley 1192555a9cf8SMatthew G. Knepley /*MC 1193555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1194555a9cf8SMatthew G. Knepley 1195555a9cf8SMatthew G. Knepley Level: intermediate 1196555a9cf8SMatthew G. Knepley 1197555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1198555a9cf8SMatthew G. Knepley M*/ 1199555a9cf8SMatthew G. Knepley 1200555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1201555a9cf8SMatthew G. Knepley { 1202555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1203555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1204555a9cf8SMatthew G. Knepley 1205555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1206555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1207555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1208555a9cf8SMatthew G. Knepley part->data = p; 1209555a9cf8SMatthew G. Knepley 1210555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1211555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1212555a9cf8SMatthew G. Knepley } 1213555a9cf8SMatthew G. Knepley 1214d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1215dae52e14SToby Isaac { 1216dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1217dae52e14SToby Isaac PetscErrorCode ierr; 1218dae52e14SToby Isaac 1219dae52e14SToby Isaac PetscFunctionBegin; 1220dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1221dae52e14SToby Isaac PetscFunctionReturn(0); 1222dae52e14SToby Isaac } 1223dae52e14SToby Isaac 1224d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1225dae52e14SToby Isaac { 1226dae52e14SToby Isaac PetscFunctionBegin; 1227dae52e14SToby Isaac PetscFunctionReturn(0); 1228dae52e14SToby Isaac } 1229dae52e14SToby Isaac 1230d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1231dae52e14SToby Isaac { 1232dae52e14SToby Isaac PetscBool iascii; 1233dae52e14SToby Isaac PetscErrorCode ierr; 1234dae52e14SToby Isaac 1235dae52e14SToby Isaac PetscFunctionBegin; 1236dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1237dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1238dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1239dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1240dae52e14SToby Isaac PetscFunctionReturn(0); 1241dae52e14SToby Isaac } 1242dae52e14SToby Isaac 1243d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1244dae52e14SToby Isaac { 1245dae52e14SToby Isaac PetscInt np; 1246dae52e14SToby Isaac PetscErrorCode ierr; 1247dae52e14SToby Isaac 1248dae52e14SToby Isaac PetscFunctionBegin; 1249dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1250dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1251dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1252dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1253dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1254dae52e14SToby Isaac PetscFunctionReturn(0); 1255dae52e14SToby Isaac } 1256dae52e14SToby Isaac 1257d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1258dae52e14SToby Isaac { 1259dae52e14SToby Isaac PetscFunctionBegin; 1260dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1261dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1262dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1263dae52e14SToby Isaac PetscFunctionReturn(0); 1264dae52e14SToby Isaac } 1265dae52e14SToby Isaac 1266dae52e14SToby Isaac /*MC 1267dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1268dae52e14SToby Isaac 1269dae52e14SToby Isaac Level: intermediate 1270dae52e14SToby Isaac 1271dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1272dae52e14SToby Isaac M*/ 1273dae52e14SToby Isaac 1274dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1275dae52e14SToby Isaac { 1276dae52e14SToby Isaac PetscPartitioner_Gather *p; 1277dae52e14SToby Isaac PetscErrorCode ierr; 1278dae52e14SToby Isaac 1279dae52e14SToby Isaac PetscFunctionBegin; 1280dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1281dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1282dae52e14SToby Isaac part->data = p; 1283dae52e14SToby Isaac 1284dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1285dae52e14SToby Isaac PetscFunctionReturn(0); 1286dae52e14SToby Isaac } 1287dae52e14SToby Isaac 1288dae52e14SToby Isaac 1289d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 129077623264SMatthew G. Knepley { 129177623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 129277623264SMatthew G. Knepley PetscErrorCode ierr; 129377623264SMatthew G. Knepley 129477623264SMatthew G. Knepley PetscFunctionBegin; 129577623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 129677623264SMatthew G. Knepley PetscFunctionReturn(0); 129777623264SMatthew G. Knepley } 129877623264SMatthew G. Knepley 1299d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 130077623264SMatthew G. Knepley { 130177623264SMatthew G. Knepley PetscFunctionBegin; 130277623264SMatthew G. Knepley PetscFunctionReturn(0); 130377623264SMatthew G. Knepley } 130477623264SMatthew G. Knepley 1305d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 130677623264SMatthew G. Knepley { 130777623264SMatthew G. Knepley PetscBool iascii; 130877623264SMatthew G. Knepley PetscErrorCode ierr; 130977623264SMatthew G. Knepley 131077623264SMatthew G. Knepley PetscFunctionBegin; 131177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 131277623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 131377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 131477623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 131577623264SMatthew G. Knepley PetscFunctionReturn(0); 131677623264SMatthew G. Knepley } 131777623264SMatthew G. Knepley 131870034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 131970034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 132070034214SMatthew G. Knepley #include <unistd.h> 132170034214SMatthew G. Knepley #endif 132211d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 132311d1e910SBarry Smith #include <chaco.h> 132411d1e910SBarry Smith #else 132511d1e910SBarry Smith /* Older versions of Chaco do not have an include file */ 132670034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 132770034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 132870034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 132970034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 133070034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 133111d1e910SBarry Smith #endif 133270034214SMatthew G. Knepley extern int FREE_GRAPH; 133377623264SMatthew G. Knepley #endif 133470034214SMatthew G. Knepley 1335d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 133670034214SMatthew G. Knepley { 133777623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 133870034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 133970034214SMatthew G. Knepley MPI_Comm comm; 134070034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 134170034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 134270034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 134370034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 134470034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 134570034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 134670034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 134770034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 134870034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 134970034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 135070034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 135170034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 135270034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 135370034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 135470034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 135570034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 135670034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 135711d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 135811d1e910SBarry Smith int *assignment; /* Output partition */ 135911d1e910SBarry Smith #else 136070034214SMatthew G. Knepley short int *assignment; /* Output partition */ 136111d1e910SBarry Smith #endif 136270034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 136370034214SMatthew G. Knepley PetscInt *points; 136470034214SMatthew G. Knepley int i, v, p; 136570034214SMatthew G. Knepley PetscErrorCode ierr; 136670034214SMatthew G. Knepley 136770034214SMatthew G. Knepley PetscFunctionBegin; 136870034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 136907ed3857SLisandro Dalcin #if defined (PETSC_USE_DEBUG) 137007ed3857SLisandro Dalcin { 137107ed3857SLisandro Dalcin int ival,isum; 137207ed3857SLisandro Dalcin PetscBool distributed; 137307ed3857SLisandro Dalcin 137407ed3857SLisandro Dalcin ival = (numVertices > 0); 137507ed3857SLisandro Dalcin ierr = MPI_Allreduce(&ival, &isum, 1, MPI_INT, MPI_SUM, comm);CHKERRQ(ierr); 137607ed3857SLisandro Dalcin distributed = (isum > 1) ? PETSC_TRUE : PETSC_FALSE; 137707ed3857SLisandro Dalcin if (distributed) SETERRQ(comm, PETSC_ERR_SUP, "Chaco cannot partition a distributed graph"); 137807ed3857SLisandro Dalcin } 137907ed3857SLisandro Dalcin #endif 138070034214SMatthew G. Knepley if (!numVertices) { 138177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 138277623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 138370034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 138470034214SMatthew G. Knepley PetscFunctionReturn(0); 138570034214SMatthew G. Knepley } 138670034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 138770034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 138870034214SMatthew G. Knepley 138970034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 139070034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 139170034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 139270034214SMatthew G. Knepley } 139377623264SMatthew G. Knepley mesh_dims[0] = nparts; 139470034214SMatthew G. Knepley mesh_dims[1] = 1; 139570034214SMatthew G. Knepley mesh_dims[2] = 1; 139670034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 139770034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 139870034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 139970034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 140070034214SMatthew G. Knepley { 140170034214SMatthew G. Knepley int piperet; 140270034214SMatthew G. Knepley piperet = pipe(fd_pipe); 140370034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 140470034214SMatthew G. Knepley fd_stdout = dup(1); 140570034214SMatthew G. Knepley close(1); 140670034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 140770034214SMatthew G. Knepley } 140870034214SMatthew G. Knepley #endif 140970034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 141070034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 141170034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 141270034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 141370034214SMatthew G. Knepley { 141470034214SMatthew G. Knepley char msgLog[10000]; 141570034214SMatthew G. Knepley int count; 141670034214SMatthew G. Knepley 141770034214SMatthew G. Knepley fflush(stdout); 141870034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 141970034214SMatthew G. Knepley if (count < 0) count = 0; 142070034214SMatthew G. Knepley msgLog[count] = 0; 142170034214SMatthew G. Knepley close(1); 142270034214SMatthew G. Knepley dup2(fd_stdout, 1); 142370034214SMatthew G. Knepley close(fd_stdout); 142470034214SMatthew G. Knepley close(fd_pipe[0]); 142570034214SMatthew G. Knepley close(fd_pipe[1]); 142670034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 142770034214SMatthew G. Knepley } 142807ed3857SLisandro Dalcin #else 142907ed3857SLisandro Dalcin if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", "error in stdout"); 143070034214SMatthew G. Knepley #endif 143170034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 143277623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 143370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 143477623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 143570034214SMatthew G. Knepley } 143677623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 143770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 143877623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 143970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 144070034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 144170034214SMatthew G. Knepley } 144270034214SMatthew G. Knepley } 144370034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 144470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 144570034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 144670034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 144770034214SMatthew G. Knepley } 144870034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 144970034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 145070034214SMatthew G. Knepley PetscFunctionReturn(0); 145177623264SMatthew G. Knepley #else 145277623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 145370034214SMatthew G. Knepley #endif 145477623264SMatthew G. Knepley } 145577623264SMatthew G. Knepley 1456d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 145777623264SMatthew G. Knepley { 145877623264SMatthew G. Knepley PetscFunctionBegin; 145977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 146077623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 146177623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 146277623264SMatthew G. Knepley PetscFunctionReturn(0); 146377623264SMatthew G. Knepley } 146477623264SMatthew G. Knepley 146577623264SMatthew G. Knepley /*MC 146677623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 146777623264SMatthew G. Knepley 146877623264SMatthew G. Knepley Level: intermediate 146977623264SMatthew G. Knepley 147077623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 147177623264SMatthew G. Knepley M*/ 147277623264SMatthew G. Knepley 147377623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 147477623264SMatthew G. Knepley { 147577623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 147677623264SMatthew G. Knepley PetscErrorCode ierr; 147777623264SMatthew G. Knepley 147877623264SMatthew G. Knepley PetscFunctionBegin; 147977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 148077623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 148177623264SMatthew G. Knepley part->data = p; 148277623264SMatthew G. Knepley 148377623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 148477623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 148577623264SMatthew G. Knepley PetscFunctionReturn(0); 148677623264SMatthew G. Knepley } 148777623264SMatthew G. Knepley 14885b440754SMatthew G. Knepley static const char *ptypes[] = {"kway", "rb"}; 14895b440754SMatthew G. Knepley 1490d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 149177623264SMatthew G. Knepley { 149277623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 149377623264SMatthew G. Knepley PetscErrorCode ierr; 149477623264SMatthew G. Knepley 149577623264SMatthew G. Knepley PetscFunctionBegin; 149677623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 149777623264SMatthew G. Knepley PetscFunctionReturn(0); 149877623264SMatthew G. Knepley } 149977623264SMatthew G. Knepley 1500d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 150177623264SMatthew G. Knepley { 15022abdaa70SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 150377623264SMatthew G. Knepley PetscErrorCode ierr; 150477623264SMatthew G. Knepley 150577623264SMatthew G. Knepley PetscFunctionBegin; 15062abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 15072abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 15082abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 15092abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 15102abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 151177623264SMatthew G. Knepley PetscFunctionReturn(0); 151277623264SMatthew G. Knepley } 151377623264SMatthew G. Knepley 1514d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 151577623264SMatthew G. Knepley { 151677623264SMatthew G. Knepley PetscBool iascii; 151777623264SMatthew G. Knepley PetscErrorCode ierr; 151877623264SMatthew G. Knepley 151977623264SMatthew G. Knepley PetscFunctionBegin; 152077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 152177623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 152277623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 152377623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 152477623264SMatthew G. Knepley PetscFunctionReturn(0); 152577623264SMatthew G. Knepley } 152670034214SMatthew G. Knepley 152744d8be81SLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 152844d8be81SLisandro Dalcin { 152944d8be81SLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 153042678178SLisandro Dalcin PetscInt p_randomSeed = -1; /* TODO: Add this to PetscPartitioner_ParMetis */ 153144d8be81SLisandro Dalcin PetscErrorCode ierr; 153244d8be81SLisandro Dalcin 153344d8be81SLisandro Dalcin PetscFunctionBegin; 153444d8be81SLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 153544d8be81SLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 15365b440754SMatthew G. Knepley ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 15375b440754SMatthew G. Knepley ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 153842678178SLisandro Dalcin ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p_randomSeed, &p_randomSeed, NULL);CHKERRQ(ierr); 153944d8be81SLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 154044d8be81SLisandro Dalcin PetscFunctionReturn(0); 154144d8be81SLisandro Dalcin } 154244d8be81SLisandro Dalcin 154370034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 154470034214SMatthew G. Knepley #include <parmetis.h> 154577623264SMatthew G. Knepley #endif 154670034214SMatthew G. Knepley 1547d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 154870034214SMatthew G. Knepley { 154977623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 15505b440754SMatthew G. Knepley PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 155170034214SMatthew G. Knepley MPI_Comm comm; 1552deea36a5SMatthew G. Knepley PetscSection section; 155370034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 155470034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 155570034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 155670034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 155770034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 155870034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 155970034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 156070034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 156170034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 15625b440754SMatthew G. Knepley PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 1563fb83b9f2SMichael Gegg real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 1564fb83b9f2SMichael Gegg real_t *ubvec; /* The balance intolerance for vertex weights */ 1565b3ce585bSLisandro Dalcin PetscInt options[64]; /* Options */ 156670034214SMatthew G. Knepley /* Outputs */ 1567b3ce585bSLisandro Dalcin PetscInt v, i, *assignment, *points; 1568b3ce585bSLisandro Dalcin PetscMPIInt size, rank, p; 156942678178SLisandro Dalcin PetscInt pm_randomSeed = -1; 157070034214SMatthew G. Knepley PetscErrorCode ierr; 157170034214SMatthew G. Knepley 157270034214SMatthew G. Knepley PetscFunctionBegin; 157342678178SLisandro Dalcin ierr = PetscOptionsGetInt(((PetscObject)part)->options,((PetscObject)part)->prefix,"-petscpartitioner_parmetis_seed", &pm_randomSeed, NULL);CHKERRQ(ierr); 157477623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 1575b3ce585bSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 157670034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 157770034214SMatthew G. Knepley /* Calculate vertex distribution */ 1578b3ce585bSLisandro Dalcin ierr = PetscMalloc5(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment,nvtxs,&vwgt);CHKERRQ(ierr); 157970034214SMatthew G. Knepley vtxdist[0] = 0; 158070034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1581b3ce585bSLisandro Dalcin for (p = 2; p <= size; ++p) { 158270034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 158370034214SMatthew G. Knepley } 158444d8be81SLisandro Dalcin /* Calculate partition weights */ 158570034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 158670034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 158770034214SMatthew G. Knepley } 15885b440754SMatthew G. Knepley ubvec[0] = pm->imbalanceRatio; 1589deea36a5SMatthew G. Knepley /* Weight cells by dofs on cell by default */ 1590e87a4003SBarry Smith ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 1591deea36a5SMatthew G. Knepley if (section) { 1592deea36a5SMatthew G. Knepley PetscInt cStart, cEnd, dof; 159370034214SMatthew G. Knepley 1594deea36a5SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1595deea36a5SMatthew G. Knepley for (v = cStart; v < cEnd; ++v) { 1596deea36a5SMatthew G. Knepley ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 1597925b1076SLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 1598925b1076SLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 1599925b1076SLisandro Dalcin if (v-cStart < numVertices) vwgt[v-cStart] = PetscMax(dof, 1); 1600deea36a5SMatthew G. Knepley } 1601deea36a5SMatthew G. Knepley } else { 1602deea36a5SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1603cd0de0f2SShri } 160444d8be81SLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 1605cd0de0f2SShri 160670034214SMatthew G. Knepley if (nparts == 1) { 16079fc93327SToby Isaac ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 160870034214SMatthew G. Knepley } else { 1609b3ce585bSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 1610b3ce585bSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 1611b3ce585bSLisandro Dalcin if (rank == p) { 161244d8be81SLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 161342678178SLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 161442678178SLisandro Dalcin options[METIS_OPTION_SEED] = pm_randomSeed; 161544d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 161644d8be81SLisandro Dalcin if (metis_ptype == 1) { 161744d8be81SLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 161872379da4SMatthew G. Knepley ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 161944d8be81SLisandro Dalcin PetscStackPop; 162044d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 162144d8be81SLisandro Dalcin } else { 162244d8be81SLisandro Dalcin /* 162344d8be81SLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 162444d8be81SLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 162544d8be81SLisandro Dalcin - If CONTIG is set to 1, METIS will exit with error if the graph is disconnected, despite the manual saying the option is ignored in such case. 162644d8be81SLisandro Dalcin */ 162744d8be81SLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 162844d8be81SLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 162970034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 163072379da4SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 163170034214SMatthew G. Knepley PetscStackPop; 163270034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 163370034214SMatthew G. Knepley } 163444d8be81SLisandro Dalcin } 163570034214SMatthew G. Knepley } else { 163642678178SLisandro Dalcin options[0] = 1; /*use options */ 16375b440754SMatthew G. Knepley options[1] = pm->debugFlag; 163842678178SLisandro Dalcin options[2] = (pm_randomSeed == -1) ? 15 : pm_randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 163970034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 164072379da4SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &comm); 164170034214SMatthew G. Knepley PetscStackPop; 1642c717d290SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 164370034214SMatthew G. Knepley } 164470034214SMatthew G. Knepley } 164570034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 164677623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 164777623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 164877623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 164970034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 165077623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 165170034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 165270034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 165370034214SMatthew G. Knepley } 165470034214SMatthew G. Knepley } 165570034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 165670034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1657cd0de0f2SShri ierr = PetscFree5(vtxdist,tpwgts,ubvec,assignment,vwgt);CHKERRQ(ierr); 16589b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 165970034214SMatthew G. Knepley #else 166077623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 166170034214SMatthew G. Knepley #endif 166270034214SMatthew G. Knepley } 166370034214SMatthew G. Knepley 1664d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 166577623264SMatthew G. Knepley { 166677623264SMatthew G. Knepley PetscFunctionBegin; 166777623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 166844d8be81SLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 166977623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 167077623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 167177623264SMatthew G. Knepley PetscFunctionReturn(0); 167277623264SMatthew G. Knepley } 167377623264SMatthew G. Knepley 167477623264SMatthew G. Knepley /*MC 167577623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 167677623264SMatthew G. Knepley 167777623264SMatthew G. Knepley Level: intermediate 167877623264SMatthew G. Knepley 167977623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 168077623264SMatthew G. Knepley M*/ 168177623264SMatthew G. Knepley 168277623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 168377623264SMatthew G. Knepley { 168477623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 168577623264SMatthew G. Knepley PetscErrorCode ierr; 168677623264SMatthew G. Knepley 168777623264SMatthew G. Knepley PetscFunctionBegin; 168877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 168977623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 169077623264SMatthew G. Knepley part->data = p; 169177623264SMatthew G. Knepley 16925b440754SMatthew G. Knepley p->ptype = 0; 16935b440754SMatthew G. Knepley p->imbalanceRatio = 1.05; 16945b440754SMatthew G. Knepley p->debugFlag = 0; 16955b440754SMatthew G. Knepley 169677623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 169777623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 169870034214SMatthew G. Knepley PetscFunctionReturn(0); 169970034214SMatthew G. Knepley } 170070034214SMatthew G. Knepley 1701137cd93aSLisandro Dalcin 1702137cd93aSLisandro Dalcin PetscBool PTScotchPartitionercite = PETSC_FALSE; 1703137cd93aSLisandro Dalcin const char PTScotchPartitionerCitation[] = 1704137cd93aSLisandro Dalcin "@article{PTSCOTCH,\n" 1705137cd93aSLisandro Dalcin " author = {C. Chevalier and F. Pellegrini},\n" 1706137cd93aSLisandro Dalcin " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 1707137cd93aSLisandro Dalcin " journal = {Parallel Computing},\n" 1708137cd93aSLisandro Dalcin " volume = {34},\n" 1709137cd93aSLisandro Dalcin " number = {6},\n" 1710137cd93aSLisandro Dalcin " pages = {318--331},\n" 1711137cd93aSLisandro Dalcin " year = {2008},\n" 1712137cd93aSLisandro Dalcin " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 1713137cd93aSLisandro Dalcin "}\n"; 1714137cd93aSLisandro Dalcin 1715137cd93aSLisandro Dalcin typedef struct { 1716137cd93aSLisandro Dalcin PetscInt strategy; 1717137cd93aSLisandro Dalcin PetscReal imbalance; 1718137cd93aSLisandro Dalcin } PetscPartitioner_PTScotch; 1719137cd93aSLisandro Dalcin 1720137cd93aSLisandro Dalcin static const char *const 1721137cd93aSLisandro Dalcin PTScotchStrategyList[] = { 1722137cd93aSLisandro Dalcin "DEFAULT", 1723137cd93aSLisandro Dalcin "QUALITY", 1724137cd93aSLisandro Dalcin "SPEED", 1725137cd93aSLisandro Dalcin "BALANCE", 1726137cd93aSLisandro Dalcin "SAFETY", 1727137cd93aSLisandro Dalcin "SCALABILITY", 1728137cd93aSLisandro Dalcin "RECURSIVE", 1729137cd93aSLisandro Dalcin "REMAP" 1730137cd93aSLisandro Dalcin }; 1731137cd93aSLisandro Dalcin 1732137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 1733137cd93aSLisandro Dalcin 1734137cd93aSLisandro Dalcin EXTERN_C_BEGIN 1735137cd93aSLisandro Dalcin #include <ptscotch.h> 1736137cd93aSLisandro Dalcin EXTERN_C_END 1737137cd93aSLisandro Dalcin 1738137cd93aSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 1739137cd93aSLisandro Dalcin 1740137cd93aSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 1741137cd93aSLisandro Dalcin { 1742137cd93aSLisandro Dalcin switch (strategy) { 1743137cd93aSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 1744137cd93aSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 1745137cd93aSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 1746137cd93aSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 1747137cd93aSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 1748137cd93aSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 1749137cd93aSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 1750137cd93aSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 1751137cd93aSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 1752137cd93aSLisandro Dalcin } 1753137cd93aSLisandro Dalcin } 1754137cd93aSLisandro Dalcin 1755137cd93aSLisandro Dalcin 1756137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1757137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[]) 1758137cd93aSLisandro Dalcin { 1759137cd93aSLisandro Dalcin SCOTCH_Graph grafdat; 1760137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1761137cd93aSLisandro Dalcin SCOTCH_Num vertnbr = n; 1762137cd93aSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 1763137cd93aSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 1764137cd93aSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 1765137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1766137cd93aSLisandro Dalcin double kbalval = imbalance; 1767137cd93aSLisandro Dalcin PetscErrorCode ierr; 1768137cd93aSLisandro Dalcin 1769137cd93aSLisandro Dalcin PetscFunctionBegin; 1770d99a0000SVaclav Hapla { 1771d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1772d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1773d99a0000SVaclav Hapla if (!flg) velotab = NULL; 1774d99a0000SVaclav Hapla } 1775137cd93aSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 1776137cd93aSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 1777137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1778137cd93aSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 1779137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1780137cd93aSLisandro Dalcin ierr = SCOTCH_graphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1781137cd93aSLisandro Dalcin #endif 1782137cd93aSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 1783137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 1784137cd93aSLisandro Dalcin SCOTCH_graphExit(&grafdat); 1785137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1786137cd93aSLisandro Dalcin } 1787137cd93aSLisandro Dalcin 1788137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1789137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[], MPI_Comm comm) 1790137cd93aSLisandro Dalcin { 1791137cd93aSLisandro Dalcin PetscMPIInt procglbnbr; 1792137cd93aSLisandro Dalcin PetscMPIInt proclocnum; 1793137cd93aSLisandro Dalcin SCOTCH_Arch archdat; 1794137cd93aSLisandro Dalcin SCOTCH_Dgraph grafdat; 1795137cd93aSLisandro Dalcin SCOTCH_Dmapping mappdat; 1796137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1797137cd93aSLisandro Dalcin SCOTCH_Num vertlocnbr; 1798137cd93aSLisandro Dalcin SCOTCH_Num edgelocnbr; 1799137cd93aSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 1800137cd93aSLisandro Dalcin SCOTCH_Num* edloloctab = adjwgt; 1801137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1802137cd93aSLisandro Dalcin double kbalval = imbalance; 1803137cd93aSLisandro Dalcin PetscErrorCode ierr; 1804137cd93aSLisandro Dalcin 1805137cd93aSLisandro Dalcin PetscFunctionBegin; 1806d99a0000SVaclav Hapla { 1807d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1808d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1809d99a0000SVaclav Hapla if (!flg) veloloctab = NULL; 1810d99a0000SVaclav Hapla } 1811137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 1812137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 1813137cd93aSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 1814137cd93aSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 1815137cd93aSLisandro Dalcin 1816137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 1817137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 1818137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1819137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1820137cd93aSLisandro Dalcin #endif 1821137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1822137cd93aSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 1823137cd93aSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 1824137cd93aSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 1825137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 1826137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 1827137cd93aSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 1828137cd93aSLisandro Dalcin SCOTCH_archExit(&archdat); 1829137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 1830137cd93aSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 1831137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1832137cd93aSLisandro Dalcin } 1833137cd93aSLisandro Dalcin 1834137cd93aSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 1835137cd93aSLisandro Dalcin 1836137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 1837137cd93aSLisandro Dalcin { 1838137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 1839137cd93aSLisandro Dalcin PetscErrorCode ierr; 1840137cd93aSLisandro Dalcin 1841137cd93aSLisandro Dalcin PetscFunctionBegin; 1842137cd93aSLisandro Dalcin ierr = PetscFree(p);CHKERRQ(ierr); 1843137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1844137cd93aSLisandro Dalcin } 1845137cd93aSLisandro Dalcin 1846137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_Ascii(PetscPartitioner part, PetscViewer viewer) 1847137cd93aSLisandro Dalcin { 1848137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 1849137cd93aSLisandro Dalcin PetscErrorCode ierr; 1850137cd93aSLisandro Dalcin 1851137cd93aSLisandro Dalcin PetscFunctionBegin; 1852137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1853137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 1854137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 1855137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1856137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1857137cd93aSLisandro Dalcin } 1858137cd93aSLisandro Dalcin 1859137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 1860137cd93aSLisandro Dalcin { 1861137cd93aSLisandro Dalcin PetscBool iascii; 1862137cd93aSLisandro Dalcin PetscErrorCode ierr; 1863137cd93aSLisandro Dalcin 1864137cd93aSLisandro Dalcin PetscFunctionBegin; 1865137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1866137cd93aSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1867137cd93aSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1868137cd93aSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_Ascii(part, viewer);CHKERRQ(ierr);} 1869137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1870137cd93aSLisandro Dalcin } 1871137cd93aSLisandro Dalcin 1872137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 1873137cd93aSLisandro Dalcin { 1874137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 1875137cd93aSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 1876137cd93aSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 1877137cd93aSLisandro Dalcin PetscBool flag; 1878137cd93aSLisandro Dalcin PetscErrorCode ierr; 1879137cd93aSLisandro Dalcin 1880137cd93aSLisandro Dalcin PetscFunctionBegin; 1881137cd93aSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 1882137cd93aSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 1883137cd93aSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 1884137cd93aSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 1885137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1886137cd93aSLisandro Dalcin } 1887137cd93aSLisandro Dalcin 1888137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1889137cd93aSLisandro Dalcin { 1890137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 1891137cd93aSLisandro Dalcin MPI_Comm comm = PetscObjectComm((PetscObject)part); 1892137cd93aSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 1893137cd93aSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 1894137cd93aSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 1895137cd93aSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 1896137cd93aSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 1897137cd93aSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 1898137cd93aSLisandro Dalcin PetscInt v, i, *assignment, *points; 1899137cd93aSLisandro Dalcin PetscMPIInt size, rank, p; 1900137cd93aSLisandro Dalcin PetscErrorCode ierr; 1901137cd93aSLisandro Dalcin 1902137cd93aSLisandro Dalcin PetscFunctionBegin; 1903137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1904137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 190599b53901SStefano Zampini ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 1906137cd93aSLisandro Dalcin 1907137cd93aSLisandro Dalcin /* Calculate vertex distribution */ 1908137cd93aSLisandro Dalcin vtxdist[0] = 0; 1909137cd93aSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1910137cd93aSLisandro Dalcin for (p = 2; p <= size; ++p) { 1911137cd93aSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 1912137cd93aSLisandro Dalcin } 1913137cd93aSLisandro Dalcin 1914137cd93aSLisandro Dalcin if (nparts == 1) { 1915137cd93aSLisandro Dalcin ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 1916137cd93aSLisandro Dalcin } else { 1917137cd93aSLisandro Dalcin PetscSection section; 1918137cd93aSLisandro Dalcin /* Weight cells by dofs on cell by default */ 1919137cd93aSLisandro Dalcin ierr = PetscMalloc1(PetscMax(nvtxs,1),&vwgt);CHKERRQ(ierr); 1920e87a4003SBarry Smith ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 1921137cd93aSLisandro Dalcin if (section) { 1922137cd93aSLisandro Dalcin PetscInt vStart, vEnd, dof; 1923137cd93aSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1924137cd93aSLisandro Dalcin for (v = vStart; v < vEnd; ++v) { 1925137cd93aSLisandro Dalcin ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 1926137cd93aSLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 1927137cd93aSLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 1928137cd93aSLisandro Dalcin if (v-vStart < numVertices) vwgt[v-vStart] = PetscMax(dof, 1); 1929137cd93aSLisandro Dalcin } 1930137cd93aSLisandro Dalcin } else { 1931137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1932137cd93aSLisandro Dalcin } 1933137cd93aSLisandro Dalcin { 1934137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 1935137cd93aSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 1936137cd93aSLisandro Dalcin double imbal = (double)pts->imbalance; 1937137cd93aSLisandro Dalcin 1938137cd93aSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 1939137cd93aSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 1940137cd93aSLisandro Dalcin if (rank == p) { 1941137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, assignment);CHKERRQ(ierr); 1942137cd93aSLisandro Dalcin } 1943137cd93aSLisandro Dalcin } else { 1944137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, assignment, comm);CHKERRQ(ierr); 1945137cd93aSLisandro Dalcin } 1946137cd93aSLisandro Dalcin } 1947137cd93aSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 1948137cd93aSLisandro Dalcin } 1949137cd93aSLisandro Dalcin 1950137cd93aSLisandro Dalcin /* Convert to PetscSection+IS */ 1951137cd93aSLisandro Dalcin ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1952137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 1953137cd93aSLisandro Dalcin ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1954137cd93aSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 1955137cd93aSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 1956137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 1957137cd93aSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 1958137cd93aSLisandro Dalcin } 1959137cd93aSLisandro Dalcin } 1960137cd93aSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 1961137cd93aSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1962137cd93aSLisandro Dalcin 1963137cd93aSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 1964137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1965137cd93aSLisandro Dalcin #else 1966137cd93aSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 1967137cd93aSLisandro Dalcin #endif 1968137cd93aSLisandro Dalcin } 1969137cd93aSLisandro Dalcin 1970137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 1971137cd93aSLisandro Dalcin { 1972137cd93aSLisandro Dalcin PetscFunctionBegin; 1973137cd93aSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 1974137cd93aSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 1975137cd93aSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 1976137cd93aSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 1977137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1978137cd93aSLisandro Dalcin } 1979137cd93aSLisandro Dalcin 1980137cd93aSLisandro Dalcin /*MC 1981137cd93aSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 1982137cd93aSLisandro Dalcin 1983137cd93aSLisandro Dalcin Level: intermediate 1984137cd93aSLisandro Dalcin 1985137cd93aSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1986137cd93aSLisandro Dalcin M*/ 1987137cd93aSLisandro Dalcin 1988137cd93aSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 1989137cd93aSLisandro Dalcin { 1990137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p; 1991137cd93aSLisandro Dalcin PetscErrorCode ierr; 1992137cd93aSLisandro Dalcin 1993137cd93aSLisandro Dalcin PetscFunctionBegin; 1994137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1995137cd93aSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1996137cd93aSLisandro Dalcin part->data = p; 1997137cd93aSLisandro Dalcin 1998137cd93aSLisandro Dalcin p->strategy = 0; 1999137cd93aSLisandro Dalcin p->imbalance = 0.01; 2000137cd93aSLisandro Dalcin 2001137cd93aSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 2002137cd93aSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionercite);CHKERRQ(ierr); 2003137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2004137cd93aSLisandro Dalcin } 2005137cd93aSLisandro Dalcin 2006137cd93aSLisandro Dalcin 20075680f57bSMatthew G. Knepley /*@ 20085680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 20095680f57bSMatthew G. Knepley 20105680f57bSMatthew G. Knepley Not collective 20115680f57bSMatthew G. Knepley 20125680f57bSMatthew G. Knepley Input Parameter: 20135680f57bSMatthew G. Knepley . dm - The DM 20145680f57bSMatthew G. Knepley 20155680f57bSMatthew G. Knepley Output Parameter: 20165680f57bSMatthew G. Knepley . part - The PetscPartitioner 20175680f57bSMatthew G. Knepley 20185680f57bSMatthew G. Knepley Level: developer 20195680f57bSMatthew G. Knepley 202098599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 202198599a47SLawrence Mitchell 202298599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 20235680f57bSMatthew G. Knepley @*/ 20245680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 20255680f57bSMatthew G. Knepley { 20265680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 20275680f57bSMatthew G. Knepley 20285680f57bSMatthew G. Knepley PetscFunctionBegin; 20295680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20305680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 20315680f57bSMatthew G. Knepley *part = mesh->partitioner; 20325680f57bSMatthew G. Knepley PetscFunctionReturn(0); 20335680f57bSMatthew G. Knepley } 20345680f57bSMatthew G. Knepley 203571bb2955SLawrence Mitchell /*@ 203671bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 203771bb2955SLawrence Mitchell 203871bb2955SLawrence Mitchell logically collective on dm and part 203971bb2955SLawrence Mitchell 204071bb2955SLawrence Mitchell Input Parameters: 204171bb2955SLawrence Mitchell + dm - The DM 204271bb2955SLawrence Mitchell - part - The partitioner 204371bb2955SLawrence Mitchell 204471bb2955SLawrence Mitchell Level: developer 204571bb2955SLawrence Mitchell 204671bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 204771bb2955SLawrence Mitchell 204871bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 204971bb2955SLawrence Mitchell @*/ 205071bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 205171bb2955SLawrence Mitchell { 205271bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 205371bb2955SLawrence Mitchell PetscErrorCode ierr; 205471bb2955SLawrence Mitchell 205571bb2955SLawrence Mitchell PetscFunctionBegin; 205671bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 205771bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 205871bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 205971bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 206071bb2955SLawrence Mitchell mesh->partitioner = part; 206171bb2955SLawrence Mitchell PetscFunctionReturn(0); 206271bb2955SLawrence Mitchell } 206371bb2955SLawrence Mitchell 2064e8f14785SLisandro Dalcin static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 2065270bba0cSToby Isaac { 2066270bba0cSToby Isaac PetscErrorCode ierr; 2067270bba0cSToby Isaac 2068270bba0cSToby Isaac PetscFunctionBegin; 20696a5a2ffdSToby Isaac if (up) { 20706a5a2ffdSToby Isaac PetscInt parent; 20716a5a2ffdSToby Isaac 2072270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 20736a5a2ffdSToby Isaac if (parent != point) { 20746a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 20756a5a2ffdSToby Isaac 2076270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2077270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 2078270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 2079270bba0cSToby Isaac 2080e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 20811b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 2082270bba0cSToby Isaac } 2083270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 20846a5a2ffdSToby Isaac } 20856a5a2ffdSToby Isaac } 20866a5a2ffdSToby Isaac if (down) { 20876a5a2ffdSToby Isaac PetscInt numChildren; 20886a5a2ffdSToby Isaac const PetscInt *children; 20896a5a2ffdSToby Isaac 20906a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 20916a5a2ffdSToby Isaac if (numChildren) { 20926a5a2ffdSToby Isaac PetscInt i; 20936a5a2ffdSToby Isaac 20946a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 20956a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 20966a5a2ffdSToby Isaac 2097e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 20981b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 20996a5a2ffdSToby Isaac } 21006a5a2ffdSToby Isaac } 21016a5a2ffdSToby Isaac } 2102270bba0cSToby Isaac PetscFunctionReturn(0); 2103270bba0cSToby Isaac } 2104270bba0cSToby Isaac 2105825f8a23SLisandro Dalcin PETSC_INTERN PetscErrorCode DMPlexPartitionLabelClosure_Private(DM,DMLabel,PetscInt,PetscInt,const PetscInt[],IS*); 2106825f8a23SLisandro Dalcin 2107825f8a23SLisandro Dalcin PetscErrorCode DMPlexPartitionLabelClosure_Private(DM dm, DMLabel label, PetscInt rank, PetscInt numPoints, const PetscInt points[], IS *closureIS) 2108825f8a23SLisandro Dalcin { 2109825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 2110825f8a23SLisandro Dalcin PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 2111825f8a23SLisandro Dalcin PetscInt *closure = NULL, closureSize, nelems, *elems, off = 0, p, c; 2112825f8a23SLisandro Dalcin PetscHSetI ht; 2113825f8a23SLisandro Dalcin PetscErrorCode ierr; 2114825f8a23SLisandro Dalcin 2115825f8a23SLisandro Dalcin PetscFunctionBegin; 2116825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 2117825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 2118825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 2119825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2120825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 2121825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 2122825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 2123825f8a23SLisandro Dalcin } 2124825f8a23SLisandro Dalcin } 2125825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 2126825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 2127825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 2128825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 2129825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 2130825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 2131825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 2132825f8a23SLisandro Dalcin PetscFunctionReturn(0); 2133825f8a23SLisandro Dalcin } 2134825f8a23SLisandro Dalcin 21355abbe4feSMichael Lange /*@ 21365abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 21375abbe4feSMichael Lange 21385abbe4feSMichael Lange Input Parameters: 21395abbe4feSMichael Lange + dm - The DM 21405abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 21415abbe4feSMichael Lange 21425abbe4feSMichael Lange Level: developer 21435abbe4feSMichael Lange 21445abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 21455abbe4feSMichael Lange @*/ 21465abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 21479ffc88e4SToby Isaac { 2148825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 21495abbe4feSMichael Lange const PetscInt *ranks, *points; 2150825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 21519ffc88e4SToby Isaac PetscErrorCode ierr; 21529ffc88e4SToby Isaac 21539ffc88e4SToby Isaac PetscFunctionBegin; 21545abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 21555abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 21565abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 21575abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 21585abbe4feSMichael Lange const PetscInt rank = ranks[r]; 21595abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 21605abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 21615abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2162825f8a23SLisandro Dalcin ierr = DMPlexPartitionLabelClosure_Private(dm, label, rank, numPoints, points, &closureIS);CHKERRQ(ierr); 21635abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 21645abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2165825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 2166825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 21679ffc88e4SToby Isaac } 21685abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 21695abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 21709ffc88e4SToby Isaac PetscFunctionReturn(0); 21719ffc88e4SToby Isaac } 21729ffc88e4SToby Isaac 217324d039d7SMichael Lange /*@ 217424d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 217524d039d7SMichael Lange 217624d039d7SMichael Lange Input Parameters: 217724d039d7SMichael Lange + dm - The DM 217824d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 217924d039d7SMichael Lange 218024d039d7SMichael Lange Level: developer 218124d039d7SMichael Lange 218224d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 218324d039d7SMichael Lange @*/ 218424d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 218570034214SMatthew G. Knepley { 218624d039d7SMichael Lange IS rankIS, pointIS; 218724d039d7SMichael Lange const PetscInt *ranks, *points; 218824d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 218924d039d7SMichael Lange PetscInt *adj = NULL; 219070034214SMatthew G. Knepley PetscErrorCode ierr; 219170034214SMatthew G. Knepley 219270034214SMatthew G. Knepley PetscFunctionBegin; 219324d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 219424d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 219524d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 219624d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 219724d039d7SMichael Lange const PetscInt rank = ranks[r]; 219870034214SMatthew G. Knepley 219924d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 220024d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 220124d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 220270034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 220324d039d7SMichael Lange adjSize = PETSC_DETERMINE; 220424d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 220524d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 220670034214SMatthew G. Knepley } 220724d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 220824d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 220970034214SMatthew G. Knepley } 221024d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 221124d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 221224d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 221324d039d7SMichael Lange PetscFunctionReturn(0); 221470034214SMatthew G. Knepley } 221570034214SMatthew G. Knepley 2216be200f8dSMichael Lange /*@ 2217be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 2218be200f8dSMichael Lange 2219be200f8dSMichael Lange Input Parameters: 2220be200f8dSMichael Lange + dm - The DM 2221be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 2222be200f8dSMichael Lange 2223be200f8dSMichael Lange Level: developer 2224be200f8dSMichael Lange 2225be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 2226be200f8dSMichael Lange overlap points from non-neighbouring partitions. 2227be200f8dSMichael Lange 2228be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 2229be200f8dSMichael Lange @*/ 2230be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 2231be200f8dSMichael Lange { 2232be200f8dSMichael Lange MPI_Comm comm; 2233be200f8dSMichael Lange PetscMPIInt rank; 2234be200f8dSMichael Lange PetscSF sfPoint; 22355d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 2236be200f8dSMichael Lange IS rankIS, pointIS; 2237be200f8dSMichael Lange const PetscInt *ranks; 2238be200f8dSMichael Lange PetscInt numRanks, r; 2239be200f8dSMichael Lange PetscErrorCode ierr; 2240be200f8dSMichael Lange 2241be200f8dSMichael Lange PetscFunctionBegin; 2242be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2243be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2244be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 22455d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 22465d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 22475d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 22485d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 22495d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 22505d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 22515d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 22525d04f6ebSMichael Lange if (remoteRank == rank) continue; 22535d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 22545d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 22555d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 22565d04f6ebSMichael Lange } 22575d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 22585d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 22595d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 2260be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 2261be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 2262be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 2263be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 2264be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 2265be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 2266be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 2267be200f8dSMichael Lange if (remoteRank == rank) continue; 2268be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 2269be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 2270be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2271be200f8dSMichael Lange } 2272be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 2273be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 2274be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 2275be200f8dSMichael Lange PetscFunctionReturn(0); 2276be200f8dSMichael Lange } 2277be200f8dSMichael Lange 22781fd9873aSMichael Lange /*@ 22791fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 22801fd9873aSMichael Lange 22811fd9873aSMichael Lange Input Parameters: 22821fd9873aSMichael Lange + dm - The DM 22831fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 22841fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 22851fd9873aSMichael Lange 22861fd9873aSMichael Lange Output Parameter: 22871fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 22881fd9873aSMichael Lange 22891fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 22901fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 22911fd9873aSMichael Lange 22921fd9873aSMichael Lange Level: developer 22931fd9873aSMichael Lange 22941fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 22951fd9873aSMichael Lange @*/ 22961fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 22971fd9873aSMichael Lange { 22981fd9873aSMichael Lange MPI_Comm comm; 2299874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 2300874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 23011fd9873aSMichael Lange PetscSF sfPoint; 2302874ddda9SLisandro Dalcin PetscSection rootSection; 23031fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 23041fd9873aSMichael Lange const PetscSFNode *remote; 23051fd9873aSMichael Lange const PetscInt *local, *neighbors; 23061fd9873aSMichael Lange IS valueIS; 2307874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 23081fd9873aSMichael Lange PetscErrorCode ierr; 23091fd9873aSMichael Lange 23101fd9873aSMichael Lange PetscFunctionBegin; 23111fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 23121fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 23139852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 23141fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 23151fd9873aSMichael Lange 23161fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 23171fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 23189852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 23191fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 23201fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 23211fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 23221fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 23231fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 23241fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 23251fd9873aSMichael Lange } 23261fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 2327874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 2328874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 23291fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 23301fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 23311fd9873aSMichael Lange IS pointIS; 23321fd9873aSMichael Lange const PetscInt *points; 23331fd9873aSMichael Lange 23341fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 23351fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 23361fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 23371fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 23381fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 2339f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 2340f8987ae8SMichael Lange else {l = -1;} 23411fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 23421fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 23431fd9873aSMichael Lange } 23441fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 23451fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 23461fd9873aSMichael Lange } 2347874ddda9SLisandro Dalcin 2348874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 2349874ddda9SLisandro Dalcin if (!processSF) { 2350874ddda9SLisandro Dalcin PetscInt64 counter = 0; 2351874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 2352874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 2353874ddda9SLisandro Dalcin 2354874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 2355874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 2356874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 2357874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 2358874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 2359874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2360874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2361874ddda9SLisandro Dalcin #endif 2362874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 2363874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 2364874ddda9SLisandro Dalcin } 2365874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 2366874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 2367874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 2368874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 2369874ddda9SLisandro Dalcin if (!mpiOverflow) { 2370874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 2371874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 2372874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 2373874ddda9SLisandro Dalcin } 2374874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 2375874ddda9SLisandro Dalcin } 2376874ddda9SLisandro Dalcin 2377874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 2378874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 2379874ddda9SLisandro Dalcin PetscSF procSF; 2380874ddda9SLisandro Dalcin PetscSFNode *remote; 2381874ddda9SLisandro Dalcin PetscSection leafSection; 2382874ddda9SLisandro Dalcin 2383874ddda9SLisandro Dalcin if (processSF) { 2384874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 2385874ddda9SLisandro Dalcin procSF = processSF; 2386874ddda9SLisandro Dalcin } else { 2387874ddda9SLisandro Dalcin ierr = PetscMalloc1(size, &remote);CHKERRQ(ierr); 2388874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { remote[r].rank = r; remote[r].index = rank; } 2389874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm, &procSF);CHKERRQ(ierr); 2390874ddda9SLisandro Dalcin ierr = PetscSFSetGraph(procSF, size, size, NULL, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 2391874ddda9SLisandro Dalcin } 2392874ddda9SLisandro Dalcin 2393874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 23941fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 2395874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 2396874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 2397874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 2398874ddda9SLisandro Dalcin } 2399874ddda9SLisandro Dalcin 2400874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 24011fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 24021fd9873aSMichael Lange } 2403874ddda9SLisandro Dalcin 2404874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 2405874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 24061fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 2407874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 24081fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 24091fd9873aSMichael Lange PetscFunctionReturn(0); 24101fd9873aSMichael Lange } 24111fd9873aSMichael Lange 2412aa3148a8SMichael Lange /*@ 2413aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 2414aa3148a8SMichael Lange 2415aa3148a8SMichael Lange Input Parameters: 2416aa3148a8SMichael Lange + dm - The DM 2417aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 2418aa3148a8SMichael Lange 2419aa3148a8SMichael Lange Output Parameter: 2420aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 2421aa3148a8SMichael Lange 2422aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 2423aa3148a8SMichael Lange 2424aa3148a8SMichael Lange Level: developer 2425aa3148a8SMichael Lange 2426aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 2427aa3148a8SMichael Lange @*/ 2428aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 2429aa3148a8SMichael Lange { 24309852e123SBarry Smith PetscMPIInt rank, size; 243143f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 2432aa3148a8SMichael Lange PetscSFNode *remotePoints; 243343f7d02bSMichael Lange IS remoteRootIS; 243443f7d02bSMichael Lange const PetscInt *remoteRoots; 2435aa3148a8SMichael Lange PetscErrorCode ierr; 2436aa3148a8SMichael Lange 2437aa3148a8SMichael Lange PetscFunctionBegin; 243843f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 24399852e123SBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr); 2440aa3148a8SMichael Lange 24419852e123SBarry Smith for (numRemote = 0, n = 0; n < size; ++n) { 2442aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 2443aa3148a8SMichael Lange numRemote += numPoints; 2444aa3148a8SMichael Lange } 2445aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 244643f7d02bSMichael Lange /* Put owned points first */ 244743f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 244843f7d02bSMichael Lange if (numPoints > 0) { 244943f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 245043f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 245143f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 245243f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 245343f7d02bSMichael Lange remotePoints[idx].rank = rank; 245443f7d02bSMichael Lange idx++; 245543f7d02bSMichael Lange } 245643f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 245743f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 245843f7d02bSMichael Lange } 245943f7d02bSMichael Lange /* Now add remote points */ 24609852e123SBarry Smith for (n = 0; n < size; ++n) { 2461aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 246243f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 2463aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 2464aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2465aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 2466aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 2467aa3148a8SMichael Lange remotePoints[idx].rank = n; 2468aa3148a8SMichael Lange idx++; 2469aa3148a8SMichael Lange } 2470aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2471aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 2472aa3148a8SMichael Lange } 2473aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 2474aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2475aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 247670034214SMatthew G. Knepley PetscFunctionReturn(0); 247770034214SMatthew G. Knepley } 2478