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 32bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 33532c4e7dSMichael Lange { 34ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 35389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 368cfe4c1fSMichael Lange IS cellNumbering; 378cfe4c1fSMichael Lange const PetscInt *cellNum; 38532c4e7dSMichael Lange PetscBool useCone, useClosure; 39532c4e7dSMichael Lange PetscSection section; 40532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 418cfe4c1fSMichael Lange PetscSF sfPoint; 428f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 438f4e72b9SMatthew G. Knepley const PetscInt *local; 448f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 45532c4e7dSMichael Lange PetscMPIInt rank; 46532c4e7dSMichael Lange PetscErrorCode ierr; 47532c4e7dSMichael Lange 48532c4e7dSMichael Lange PetscFunctionBegin; 49532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 50ffbd6163SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 51ffbd6163SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 52ffbd6163SMatthew G. Knepley if (dim != depth) { 53ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 54ffbd6163SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 55ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 56ffbd6163SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 57ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 58ffbd6163SMatthew G. Knepley if (!*numVertices) { 59ffbd6163SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 60ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 61ffbd6163SMatthew G. Knepley } 62ffbd6163SMatthew G. Knepley /* Broken in parallel */ 63ffbd6163SMatthew G. Knepley if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 64ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 65ffbd6163SMatthew G. Knepley } 668cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 670134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 68532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 69532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 70532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 71532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 72532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 73b0441da4SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 74b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 750134a67bSLisandro Dalcin ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 763fa7752dSToby Isaac if (globalNumbering) { 773fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 783fa7752dSToby Isaac *globalNumbering = cellNumbering; 793fa7752dSToby Isaac } 808cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 818f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 828f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 838f4e72b9SMatthew G. Knepley */ 840134a67bSLisandro Dalcin ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr); 858f4e72b9SMatthew G. Knepley if (nroots >= 0) { 868f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 878f4e72b9SMatthew G. Knepley 888f4e72b9SMatthew G. Knepley ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr); 890134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 908f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 918f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 928f4e72b9SMatthew G. Knepley const PetscInt *support; 938f4e72b9SMatthew G. Knepley PetscInt supportSize; 948f4e72b9SMatthew G. Knepley 958f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 968f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 970134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 988f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 998f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1000134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 1018f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1020134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1030134a67bSLisandro Dalcin } 1040134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1050134a67bSLisandro Dalcin if (supportSize > 2) { 1060134a67bSLisandro Dalcin PetscInt numChildren, i; 1070134a67bSLisandro Dalcin const PetscInt *children; 1080134a67bSLisandro Dalcin 1090134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr); 1100134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1110134a67bSLisandro Dalcin const PetscInt child = children[i]; 1120134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1130134a67bSLisandro Dalcin ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr); 1140134a67bSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr); 1150134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1160134a67bSLisandro Dalcin else if (supportSize == 2) { 1170134a67bSLisandro Dalcin ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1180134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 1190134a67bSLisandro Dalcin ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1200134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1210134a67bSLisandro Dalcin } 1220134a67bSLisandro Dalcin } 1230134a67bSLisandro Dalcin } 1248f4e72b9SMatthew G. Knepley } 1258f4e72b9SMatthew G. Knepley } 1268f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 1278f4e72b9SMatthew G. Knepley ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1288f4e72b9SMatthew G. Knepley ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1298f4e72b9SMatthew G. Knepley ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1308f4e72b9SMatthew G. Knepley ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1318f4e72b9SMatthew G. Knepley } 1328f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 1338cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 1348cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 1358cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 1368f4e72b9SMatthew G. Knepley /* Add remote cells */ 1378f4e72b9SMatthew G. Knepley if (remoteCells) { 1380134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 1390134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 1400134a67bSLisandro Dalcin const PetscInt *cone, *children; 1410134a67bSLisandro Dalcin 1428f4e72b9SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1438f4e72b9SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1448f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1450134a67bSLisandro Dalcin const PetscInt point = cone[c]; 1460134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 1478f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 1488f4e72b9SMatthew G. Knepley ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1498f4e72b9SMatthew G. Knepley ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1500134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 1510134a67bSLisandro Dalcin } 1520134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1530134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 1540134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1550134a67bSLisandro Dalcin const PetscInt child = children[i]; 1560134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 1570134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 1580134a67bSLisandro Dalcin ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1590134a67bSLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1600134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 1610134a67bSLisandro Dalcin } 1628f4e72b9SMatthew G. Knepley } 1638f4e72b9SMatthew G. Knepley } 1648f4e72b9SMatthew G. Knepley } 1658f4e72b9SMatthew G. Knepley /* Add local cells */ 166532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 167532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 168532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 169532c4e7dSMichael Lange const PetscInt point = adj[a]; 170532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 171532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 172532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 173532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1740134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 175532c4e7dSMichael Lange } 176532c4e7dSMichael Lange } 1778cfe4c1fSMichael Lange (*numVertices)++; 178532c4e7dSMichael Lange } 1794e468a93SLisandro Dalcin ierr = PetscFree(adj);CHKERRQ(ierr); 1808f4e72b9SMatthew G. Knepley ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr); 181b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 1824e468a93SLisandro Dalcin 183532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 184532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 185532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 186389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 18743f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 18843f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 18943f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 19043f7d02bSMichael Lange } 191532c4e7dSMichael Lange vOffsets[*numVertices] = size; 192389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 1934e468a93SLisandro Dalcin 1944e468a93SLisandro Dalcin if (nroots >= 0) { 1954e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 1964e468a93SLisandro Dalcin ierr = PetscSectionReset(section);CHKERRQ(ierr); 1974e468a93SLisandro Dalcin ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr); 1984e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 1994e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2004e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 2014e468a93SLisandro Dalcin ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr); 2024e468a93SLisandro Dalcin ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr); 2034e468a93SLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr); 2044e468a93SLisandro Dalcin ierr = PetscMemcpy(edges, &graph[start], numEdges*sizeof(*edges));CHKERRQ(ierr); 2054e468a93SLisandro Dalcin } 2064e468a93SLisandro Dalcin ierr = PetscFree(vOffsets);CHKERRQ(ierr); 2074e468a93SLisandro Dalcin ierr = PetscFree(graph);CHKERRQ(ierr); 2084e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2094e468a93SLisandro Dalcin ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 2104e468a93SLisandro Dalcin ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2114e468a93SLisandro Dalcin ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 2124e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 2134e468a93SLisandro Dalcin ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 2144e468a93SLisandro Dalcin } 2154e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2164e468a93SLisandro Dalcin ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 2174e468a93SLisandro Dalcin } else { 2184e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2194e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2204e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2214e468a93SLisandro Dalcin ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr); 2224e468a93SLisandro Dalcin } 2234e468a93SLisandro Dalcin } 2244e468a93SLisandro Dalcin 2254e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 226389e55d8SMichael Lange if (adjacency) *adjacency = graph; 2274e468a93SLisandro Dalcin 228532c4e7dSMichael Lange /* Cleanup */ 229532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 230532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 2314e468a93SLisandro Dalcin ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 2324e468a93SLisandro Dalcin ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 233532c4e7dSMichael Lange PetscFunctionReturn(0); 234532c4e7dSMichael Lange } 235532c4e7dSMichael Lange 236bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 237bbbc8e51SStefano Zampini { 238bbbc8e51SStefano Zampini Mat conn, CSR; 239bbbc8e51SStefano Zampini IS fis, cis, cis_own; 240bbbc8e51SStefano Zampini PetscSF sfPoint; 241bbbc8e51SStefano Zampini const char *prefix; 242bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 243bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 244bbbc8e51SStefano Zampini PetscInt dim, depth, floc, cloc, i, M, N, c, m, cStart, cEnd, fStart, fEnd; 245bbbc8e51SStefano Zampini PetscMPIInt rank; 246bbbc8e51SStefano Zampini PetscBool flg; 247bbbc8e51SStefano Zampini PetscErrorCode ierr; 248bbbc8e51SStefano Zampini 249bbbc8e51SStefano Zampini PetscFunctionBegin; 250bbbc8e51SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 251bbbc8e51SStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 252bbbc8e51SStefano Zampini ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 253bbbc8e51SStefano Zampini if (dim != depth) { 254bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 255bbbc8e51SStefano Zampini ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 256bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 257bbbc8e51SStefano Zampini if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 258bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 259bbbc8e51SStefano Zampini if (!*numVertices) { 260bbbc8e51SStefano Zampini ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 261bbbc8e51SStefano Zampini (*offsets)[0] = 0; 262bbbc8e51SStefano Zampini } 263bbbc8e51SStefano Zampini /* Broken in parallel */ 264bbbc8e51SStefano Zampini if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 265bbbc8e51SStefano Zampini PetscFunctionReturn(0); 266bbbc8e51SStefano Zampini } 267bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 268bbbc8e51SStefano Zampini ierr = DMGetOptionsPrefix(dm, &prefix);CHKERRQ(ierr); 269bbbc8e51SStefano Zampini 270bbbc8e51SStefano Zampini /* numbering */ 271bbbc8e51SStefano Zampini ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 272bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr); 273bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 274bbbc8e51SStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr); 275bbbc8e51SStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr); 276bbbc8e51SStefano Zampini if (globalNumbering) { 277bbbc8e51SStefano Zampini ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr); 278bbbc8e51SStefano Zampini } 279bbbc8e51SStefano Zampini 280bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 281bbbc8e51SStefano Zampini ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr); 282bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 283bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 284bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 285bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 286bbbc8e51SStefano Zampini 287bbbc8e51SStefano Zampini if (p < 0) { 288bbbc8e51SStefano Zampini idxs[i] = -(p+1); 289bbbc8e51SStefano Zampini } else { 290bbbc8e51SStefano Zampini idxs[i] = p; 291bbbc8e51SStefano Zampini floc += 1; 292bbbc8e51SStefano Zampini } 293bbbc8e51SStefano Zampini } 294bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 295bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 296bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 297bbbc8e51SStefano Zampini 298bbbc8e51SStefano Zampini ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr); 299bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 300bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 301bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr); 302bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 303bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 304bbbc8e51SStefano Zampini 305bbbc8e51SStefano Zampini if (p < 0) { 306bbbc8e51SStefano Zampini idxs[i] = -(p+1); 307bbbc8e51SStefano Zampini } else { 308bbbc8e51SStefano Zampini idxs[i] = p; 309bbbc8e51SStefano Zampini idxs2[cloc++] = p; 310bbbc8e51SStefano Zampini } 311bbbc8e51SStefano Zampini } 312bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 313bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 314bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 315bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr); 316bbbc8e51SStefano Zampini 317bbbc8e51SStefano Zampini ierr = PetscObjectSetName((PetscObject)cis, "Local cells");CHKERRQ(ierr); 318bbbc8e51SStefano Zampini ierr = PetscObjectSetName((PetscObject)cis_own, "Owned local cells");CHKERRQ(ierr); 319bbbc8e51SStefano Zampini ierr = PetscObjectSetOptionsPrefix((PetscObject)cis, prefix);CHKERRQ(ierr); 320bbbc8e51SStefano Zampini ierr = PetscObjectSetOptionsPrefix((PetscObject)cis_own, prefix);CHKERRQ(ierr); 321bbbc8e51SStefano Zampini ierr = ISViewFromOptions(cis, NULL, "-dm_plex_csr_is_view");CHKERRQ(ierr); 322bbbc8e51SStefano Zampini ierr = ISViewFromOptions(cis_own, NULL, "-dm_plex_csr_is_view");CHKERRQ(ierr); 323bbbc8e51SStefano Zampini 324bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 325bbbc8e51SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr); 326bbbc8e51SStefano Zampini ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr); 327bbbc8e51SStefano Zampini ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr); 328bbbc8e51SStefano Zampini ierr = DMPlexGetMaxSizes(dm, NULL, &m);CHKERRQ(ierr); 329bbbc8e51SStefano Zampini ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr); 330bbbc8e51SStefano Zampini 331bbbc8e51SStefano Zampini /* Assemble matrix */ 332bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 333bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 334bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 335bbbc8e51SStefano Zampini const PetscInt *cone; 336bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 337bbbc8e51SStefano Zampini 338bbbc8e51SStefano Zampini col = cols[c-cStart]; 339bbbc8e51SStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 340bbbc8e51SStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 341bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 342bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 343bbbc8e51SStefano Zampini const PetscInt *children; 344bbbc8e51SStefano Zampini PetscInt numChildren, ch; 345bbbc8e51SStefano Zampini 346bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 347bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 348bbbc8e51SStefano Zampini 349bbbc8e51SStefano Zampini /* non-conforming meshes */ 350bbbc8e51SStefano Zampini ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr); 351bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 352bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 353bbbc8e51SStefano Zampini 354bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 355bbbc8e51SStefano Zampini row = rows[child-fStart]; 356bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 357bbbc8e51SStefano Zampini } 358bbbc8e51SStefano Zampini } 359bbbc8e51SStefano Zampini } 360bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 361bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 362bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 363bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 364bbbc8e51SStefano Zampini ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 365bbbc8e51SStefano Zampini ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 366bbbc8e51SStefano Zampini 367bbbc8e51SStefano Zampini ierr = PetscObjectSetName((PetscObject)conn, "F-C connectivity");CHKERRQ(ierr); 368bbbc8e51SStefano Zampini ierr = MatSetOptionsPrefix(conn, prefix);CHKERRQ(ierr); 369bbbc8e51SStefano Zampini ierr = MatViewFromOptions(conn, NULL, "-dm_plex_csr_conn_view");CHKERRQ(ierr); 370bbbc8e51SStefano Zampini 371bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 372bbbc8e51SStefano Zampini ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr); 373bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 374bbbc8e51SStefano Zampini 375bbbc8e51SStefano Zampini ierr = PetscObjectSetName((PetscObject)CSR, "Connectivity");CHKERRQ(ierr); 376bbbc8e51SStefano Zampini ierr = MatSetOptionsPrefix(CSR, prefix);CHKERRQ(ierr); 377bbbc8e51SStefano Zampini ierr = DMViewFromOptions(dm, NULL, "-dm_plex_csr_dm_view");CHKERRQ(ierr); 378bbbc8e51SStefano Zampini ierr = MatViewFromOptions(CSR, NULL, "-dm_plex_csr_mat_view");CHKERRQ(ierr); 379bbbc8e51SStefano Zampini 380bbbc8e51SStefano Zampini /* extract local part of the CSR */ 381bbbc8e51SStefano Zampini ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr); 382bbbc8e51SStefano Zampini ierr = MatDestroy(&CSR);CHKERRQ(ierr); 383bbbc8e51SStefano Zampini ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 384bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 385bbbc8e51SStefano Zampini 386bbbc8e51SStefano Zampini /* get back requested output */ 387bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 388bbbc8e51SStefano Zampini if (offsets) { 389bbbc8e51SStefano Zampini ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr); 390bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 391bbbc8e51SStefano Zampini *offsets = idxs; 392bbbc8e51SStefano Zampini } 393bbbc8e51SStefano Zampini if (adjacency) { 394bbbc8e51SStefano Zampini ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr); 395bbbc8e51SStefano Zampini ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr); 396bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 397bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 398bbbc8e51SStefano Zampini 399bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 400bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 401bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 402bbbc8e51SStefano Zampini } 403bbbc8e51SStefano Zampini } 404bbbc8e51SStefano Zampini if (c != ii[m] - m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 405bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr); 406bbbc8e51SStefano Zampini *adjacency = idxs; 407bbbc8e51SStefano Zampini } 408bbbc8e51SStefano Zampini 409bbbc8e51SStefano Zampini /* cleanup */ 410bbbc8e51SStefano Zampini ierr = ISDestroy(&cis_own);CHKERRQ(ierr); 411bbbc8e51SStefano Zampini ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 412bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 413bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 414bbbc8e51SStefano Zampini PetscFunctionReturn(0); 415bbbc8e51SStefano Zampini } 416bbbc8e51SStefano Zampini 417bbbc8e51SStefano Zampini /*@C 418bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 419bbbc8e51SStefano Zampini 420bbbc8e51SStefano Zampini Input Parameters: 421bbbc8e51SStefano Zampini + dm - The mesh DM dm 422bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 423bbbc8e51SStefano Zampini 424bbbc8e51SStefano Zampini Output Parameter: 425bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 426bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 427bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 428bbbc8e51SStefano Zampini - globalNumbering - A map from the local cell numbering to the global numbering used in "adjacency". Negative indicates that the cell is a duplicate from another process. 429bbbc8e51SStefano Zampini 430bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 431bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 432bbbc8e51SStefano Zampini 433bbbc8e51SStefano Zampini Level: developer 434bbbc8e51SStefano Zampini 435bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 436bbbc8e51SStefano Zampini @*/ 437bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 438bbbc8e51SStefano Zampini { 439bbbc8e51SStefano Zampini PetscErrorCode ierr; 440bbbc8e51SStefano Zampini PetscBool usemat = PETSC_FALSE; 441bbbc8e51SStefano Zampini 442bbbc8e51SStefano Zampini PetscFunctionBegin; 443bbbc8e51SStefano Zampini ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_via_mat", &usemat, NULL);CHKERRQ(ierr); 444bbbc8e51SStefano Zampini if (usemat) { 445bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 446bbbc8e51SStefano Zampini } else { 447bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 448bbbc8e51SStefano Zampini } 449bbbc8e51SStefano Zampini PetscFunctionReturn(0); 450bbbc8e51SStefano Zampini } 451bbbc8e51SStefano Zampini 452d5577e40SMatthew G. Knepley /*@C 453d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 454d5577e40SMatthew G. Knepley 455d5577e40SMatthew G. Knepley Collective 456d5577e40SMatthew G. Knepley 457d5577e40SMatthew G. Knepley Input Arguments: 458d5577e40SMatthew G. Knepley + dm - The DMPlex 459d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 460d5577e40SMatthew G. Knepley 461d5577e40SMatthew G. Knepley Output Arguments: 462d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 463d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 464d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 465d5577e40SMatthew G. Knepley 466d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 467d5577e40SMatthew G. Knepley 468d5577e40SMatthew G. Knepley Level: advanced 469d5577e40SMatthew G. Knepley 470d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 471d5577e40SMatthew G. Knepley @*/ 47270034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 47370034214SMatthew G. Knepley { 47470034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 47570034214SMatthew G. Knepley PetscInt numFaceCases = 0; 47670034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 47770034214SMatthew G. Knepley PetscInt *off, *adj; 47870034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 47970034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 48070034214SMatthew G. Knepley PetscErrorCode ierr; 48170034214SMatthew G. Knepley 48270034214SMatthew G. Knepley PetscFunctionBegin; 48370034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 484c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 48570034214SMatthew G. Knepley cellDim = dim - cellHeight; 48670034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 48770034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 48870034214SMatthew G. Knepley if (cEnd - cStart == 0) { 48970034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 49070034214SMatthew G. Knepley if (offsets) *offsets = NULL; 49170034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 49270034214SMatthew G. Knepley PetscFunctionReturn(0); 49370034214SMatthew G. Knepley } 49470034214SMatthew G. Knepley numCells = cEnd - cStart; 49570034214SMatthew G. Knepley faceDepth = depth - cellHeight; 49670034214SMatthew G. Knepley if (dim == depth) { 49770034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 49870034214SMatthew G. Knepley 49970034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 50070034214SMatthew G. Knepley /* Count neighboring cells */ 50170034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 50270034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 50370034214SMatthew G. Knepley const PetscInt *support; 50470034214SMatthew G. Knepley PetscInt supportSize; 50570034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 50670034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 50770034214SMatthew G. Knepley if (supportSize == 2) { 5089ffc88e4SToby Isaac PetscInt numChildren; 5099ffc88e4SToby Isaac 5109ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5119ffc88e4SToby Isaac if (!numChildren) { 51270034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 51370034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 51470034214SMatthew G. Knepley } 51570034214SMatthew G. Knepley } 5169ffc88e4SToby Isaac } 51770034214SMatthew G. Knepley /* Prefix sum */ 51870034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 51970034214SMatthew G. Knepley if (adjacency) { 52070034214SMatthew G. Knepley PetscInt *tmp; 52170034214SMatthew G. Knepley 52270034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 523854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 52470034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 52570034214SMatthew G. Knepley /* Get neighboring cells */ 52670034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 52770034214SMatthew G. Knepley const PetscInt *support; 52870034214SMatthew G. Knepley PetscInt supportSize; 52970034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 53070034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 53170034214SMatthew G. Knepley if (supportSize == 2) { 5329ffc88e4SToby Isaac PetscInt numChildren; 5339ffc88e4SToby Isaac 5349ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5359ffc88e4SToby Isaac if (!numChildren) { 53670034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 53770034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 53870034214SMatthew G. Knepley } 53970034214SMatthew G. Knepley } 5409ffc88e4SToby Isaac } 54170034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 54270034214SMatthew 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); 54370034214SMatthew G. Knepley #endif 54470034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 54570034214SMatthew G. Knepley } 54670034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 54770034214SMatthew G. Knepley if (offsets) *offsets = off; 54870034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 54970034214SMatthew G. Knepley PetscFunctionReturn(0); 55070034214SMatthew G. Knepley } 55170034214SMatthew G. Knepley /* Setup face recognition */ 55270034214SMatthew G. Knepley if (faceDepth == 1) { 55370034214SMatthew 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 */ 55470034214SMatthew G. Knepley 55570034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 55670034214SMatthew G. Knepley PetscInt corners; 55770034214SMatthew G. Knepley 55870034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 55970034214SMatthew G. Knepley if (!cornersSeen[corners]) { 56070034214SMatthew G. Knepley PetscInt nFV; 56170034214SMatthew G. Knepley 56270034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 56370034214SMatthew G. Knepley cornersSeen[corners] = 1; 56470034214SMatthew G. Knepley 56570034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 56670034214SMatthew G. Knepley 56770034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 56870034214SMatthew G. Knepley } 56970034214SMatthew G. Knepley } 57070034214SMatthew G. Knepley } 57170034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 57270034214SMatthew G. Knepley /* Count neighboring cells */ 57370034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 57470034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 57570034214SMatthew G. Knepley 5768b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 57770034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 57870034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 57970034214SMatthew G. Knepley PetscInt cellPair[2]; 58070034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 58170034214SMatthew G. Knepley PetscInt meetSize = 0; 58270034214SMatthew G. Knepley const PetscInt *meet = NULL; 58370034214SMatthew G. Knepley 58470034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 58570034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 58670034214SMatthew G. Knepley if (!found) { 58770034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 58870034214SMatthew G. Knepley if (meetSize) { 58970034214SMatthew G. Knepley PetscInt f; 59070034214SMatthew G. Knepley 59170034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 59270034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 59370034214SMatthew G. Knepley found = PETSC_TRUE; 59470034214SMatthew G. Knepley break; 59570034214SMatthew G. Knepley } 59670034214SMatthew G. Knepley } 59770034214SMatthew G. Knepley } 59870034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 59970034214SMatthew G. Knepley } 60070034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 60170034214SMatthew G. Knepley } 60270034214SMatthew G. Knepley } 60370034214SMatthew G. Knepley /* Prefix sum */ 60470034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 60570034214SMatthew G. Knepley 60670034214SMatthew G. Knepley if (adjacency) { 60770034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 60870034214SMatthew G. Knepley /* Get neighboring cells */ 60970034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 61070034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 61170034214SMatthew G. Knepley PetscInt cellOffset = 0; 61270034214SMatthew G. Knepley 6138b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 61470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 61570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 61670034214SMatthew G. Knepley PetscInt cellPair[2]; 61770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 61870034214SMatthew G. Knepley PetscInt meetSize = 0; 61970034214SMatthew G. Knepley const PetscInt *meet = NULL; 62070034214SMatthew G. Knepley 62170034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 62270034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 62370034214SMatthew G. Knepley if (!found) { 62470034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 62570034214SMatthew G. Knepley if (meetSize) { 62670034214SMatthew G. Knepley PetscInt f; 62770034214SMatthew G. Knepley 62870034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 62970034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 63070034214SMatthew G. Knepley found = PETSC_TRUE; 63170034214SMatthew G. Knepley break; 63270034214SMatthew G. Knepley } 63370034214SMatthew G. Knepley } 63470034214SMatthew G. Knepley } 63570034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 63670034214SMatthew G. Knepley } 63770034214SMatthew G. Knepley if (found) { 63870034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 63970034214SMatthew G. Knepley ++cellOffset; 64070034214SMatthew G. Knepley } 64170034214SMatthew G. Knepley } 64270034214SMatthew G. Knepley } 64370034214SMatthew G. Knepley } 64470034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 64570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 64670034214SMatthew G. Knepley if (offsets) *offsets = off; 64770034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 64870034214SMatthew G. Knepley PetscFunctionReturn(0); 64970034214SMatthew G. Knepley } 65070034214SMatthew G. Knepley 65177623264SMatthew G. Knepley /*@C 65277623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 65377623264SMatthew G. Knepley 65477623264SMatthew G. Knepley Not Collective 65577623264SMatthew G. Knepley 65677623264SMatthew G. Knepley Input Parameters: 65777623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 65877623264SMatthew G. Knepley - create_func - The creation routine itself 65977623264SMatthew G. Knepley 66077623264SMatthew G. Knepley Notes: 66177623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 66277623264SMatthew G. Knepley 66377623264SMatthew G. Knepley Sample usage: 66477623264SMatthew G. Knepley .vb 66577623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 66677623264SMatthew G. Knepley .ve 66777623264SMatthew G. Knepley 66877623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 66977623264SMatthew G. Knepley .vb 67077623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 67177623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 67277623264SMatthew G. Knepley .ve 67377623264SMatthew G. Knepley or at runtime via the option 67477623264SMatthew G. Knepley .vb 67577623264SMatthew G. Knepley -petscpartitioner_type my_part 67677623264SMatthew G. Knepley .ve 67777623264SMatthew G. Knepley 67877623264SMatthew G. Knepley Level: advanced 67977623264SMatthew G. Knepley 68077623264SMatthew G. Knepley .keywords: PetscPartitioner, register 68177623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 68277623264SMatthew G. Knepley 68377623264SMatthew G. Knepley @*/ 68477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 68577623264SMatthew G. Knepley { 68677623264SMatthew G. Knepley PetscErrorCode ierr; 68777623264SMatthew G. Knepley 68877623264SMatthew G. Knepley PetscFunctionBegin; 68977623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 69077623264SMatthew G. Knepley PetscFunctionReturn(0); 69177623264SMatthew G. Knepley } 69277623264SMatthew G. Knepley 69377623264SMatthew G. Knepley /*@C 69477623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 69577623264SMatthew G. Knepley 69677623264SMatthew G. Knepley Collective on PetscPartitioner 69777623264SMatthew G. Knepley 69877623264SMatthew G. Knepley Input Parameters: 69977623264SMatthew G. Knepley + part - The PetscPartitioner object 70077623264SMatthew G. Knepley - name - The kind of partitioner 70177623264SMatthew G. Knepley 70277623264SMatthew G. Knepley Options Database Key: 70377623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 70477623264SMatthew G. Knepley 70577623264SMatthew G. Knepley Level: intermediate 70677623264SMatthew G. Knepley 70777623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 70877623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 70977623264SMatthew G. Knepley @*/ 71077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 71177623264SMatthew G. Knepley { 71277623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 71377623264SMatthew G. Knepley PetscBool match; 71477623264SMatthew G. Knepley PetscErrorCode ierr; 71577623264SMatthew G. Knepley 71677623264SMatthew G. Knepley PetscFunctionBegin; 71777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 71877623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 71977623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 72077623264SMatthew G. Knepley 7210f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 72277623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 72377623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 72477623264SMatthew G. Knepley 72577623264SMatthew G. Knepley if (part->ops->destroy) { 72677623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 72777623264SMatthew G. Knepley } 728074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 72909161815SVaclav Hapla ierr = PetscMemzero(part->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 73077623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 73177623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 73277623264SMatthew G. Knepley PetscFunctionReturn(0); 73377623264SMatthew G. Knepley } 73477623264SMatthew G. Knepley 73577623264SMatthew G. Knepley /*@C 73677623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 73777623264SMatthew G. Knepley 73877623264SMatthew G. Knepley Not Collective 73977623264SMatthew G. Knepley 74077623264SMatthew G. Knepley Input Parameter: 74177623264SMatthew G. Knepley . part - The PetscPartitioner 74277623264SMatthew G. Knepley 74377623264SMatthew G. Knepley Output Parameter: 74477623264SMatthew G. Knepley . name - The PetscPartitioner type name 74577623264SMatthew G. Knepley 74677623264SMatthew G. Knepley Level: intermediate 74777623264SMatthew G. Knepley 74877623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 74977623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 75077623264SMatthew G. Knepley @*/ 75177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 75277623264SMatthew G. Knepley { 75377623264SMatthew G. Knepley PetscErrorCode ierr; 75477623264SMatthew G. Knepley 75577623264SMatthew G. Knepley PetscFunctionBegin; 75677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 75777623264SMatthew G. Knepley PetscValidPointer(name, 2); 7580f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 75977623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 76077623264SMatthew G. Knepley PetscFunctionReturn(0); 76177623264SMatthew G. Knepley } 76277623264SMatthew G. Knepley 76377623264SMatthew G. Knepley /*@C 76477623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 76577623264SMatthew G. Knepley 76677623264SMatthew G. Knepley Collective on PetscPartitioner 76777623264SMatthew G. Knepley 76877623264SMatthew G. Knepley Input Parameter: 76977623264SMatthew G. Knepley + part - the PetscPartitioner object to view 77077623264SMatthew G. Knepley - v - the viewer 77177623264SMatthew G. Knepley 77277623264SMatthew G. Knepley Level: developer 77377623264SMatthew G. Knepley 77477623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 77577623264SMatthew G. Knepley @*/ 77677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 77777623264SMatthew G. Knepley { 778ffc59708SMatthew G. Knepley PetscMPIInt size; 7792abdaa70SMatthew G. Knepley PetscBool isascii; 78077623264SMatthew G. Knepley PetscErrorCode ierr; 78177623264SMatthew G. Knepley 78277623264SMatthew G. Knepley PetscFunctionBegin; 78377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 78477623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 7852abdaa70SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 7862abdaa70SMatthew G. Knepley if (isascii) { 7872abdaa70SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 788ffc59708SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");CHKERRQ(ierr); 7892abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " type: %s\n", part->hdr.type_name);CHKERRQ(ierr); 7902abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 7912abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "edge cut: %D\n", part->edgeCut);CHKERRQ(ierr); 7922abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "balance: %.2g\n", part->balance);CHKERRQ(ierr); 7932abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 7942abdaa70SMatthew G. Knepley } 79577623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 79677623264SMatthew G. Knepley PetscFunctionReturn(0); 79777623264SMatthew G. Knepley } 79877623264SMatthew G. Knepley 799a0058e54SToby Isaac static PetscErrorCode PetscPartitionerGetDefaultType(const char *currentType, const char **defaultType) 800a0058e54SToby Isaac { 801a0058e54SToby Isaac PetscFunctionBegin; 802a0058e54SToby Isaac if (!currentType) { 803a0058e54SToby Isaac #if defined(PETSC_HAVE_CHACO) 804a0058e54SToby Isaac *defaultType = PETSCPARTITIONERCHACO; 805a0058e54SToby Isaac #elif defined(PETSC_HAVE_PARMETIS) 806a0058e54SToby Isaac *defaultType = PETSCPARTITIONERPARMETIS; 807137cd93aSLisandro Dalcin #elif defined(PETSC_HAVE_PTSCOTCH) 808137cd93aSLisandro Dalcin *defaultType = PETSCPARTITIONERPTSCOTCH; 809a0058e54SToby Isaac #else 810a0058e54SToby Isaac *defaultType = PETSCPARTITIONERSIMPLE; 811a0058e54SToby Isaac #endif 812a0058e54SToby Isaac } else { 813a0058e54SToby Isaac *defaultType = currentType; 814a0058e54SToby Isaac } 815a0058e54SToby Isaac PetscFunctionReturn(0); 816a0058e54SToby Isaac } 817a0058e54SToby Isaac 81877623264SMatthew G. Knepley /*@ 81977623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 82077623264SMatthew G. Knepley 82177623264SMatthew G. Knepley Collective on PetscPartitioner 82277623264SMatthew G. Knepley 82377623264SMatthew G. Knepley Input Parameter: 82477623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 82577623264SMatthew G. Knepley 82677623264SMatthew G. Knepley Level: developer 82777623264SMatthew G. Knepley 82877623264SMatthew G. Knepley .seealso: PetscPartitionerView() 82977623264SMatthew G. Knepley @*/ 83077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 83177623264SMatthew G. Knepley { 8326bb9daa8SLisandro Dalcin const char *defaultType; 8336bb9daa8SLisandro Dalcin char name[256]; 8346bb9daa8SLisandro Dalcin PetscBool flg; 83577623264SMatthew G. Knepley PetscErrorCode ierr; 83677623264SMatthew G. Knepley 83777623264SMatthew G. Knepley PetscFunctionBegin; 83877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8396bb9daa8SLisandro Dalcin ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 8406bb9daa8SLisandro Dalcin ierr = PetscPartitionerGetDefaultType(((PetscObject) part)->type_name,&defaultType);CHKERRQ(ierr); 84177623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 8426bb9daa8SLisandro Dalcin ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, sizeof(name), &flg);CHKERRQ(ierr); 8436bb9daa8SLisandro Dalcin if (flg) { 8446bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 8456bb9daa8SLisandro Dalcin } else if (!((PetscObject) part)->type_name) { 8466bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 8476bb9daa8SLisandro Dalcin } 8486bb9daa8SLisandro Dalcin if (part->ops->setfromoptions) { 8496bb9daa8SLisandro Dalcin ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr); 8506bb9daa8SLisandro Dalcin } 851783e1fb6SStefano Zampini ierr = PetscViewerDestroy(&part->viewerGraph);CHKERRQ(ierr); 8520358368aSMatthew G. Knepley ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, &part->formatGraph, &part->viewGraph);CHKERRQ(ierr); 85377623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 8540633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 85577623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 85677623264SMatthew G. Knepley PetscFunctionReturn(0); 85777623264SMatthew G. Knepley } 85877623264SMatthew G. Knepley 85977623264SMatthew G. Knepley /*@C 86077623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 86177623264SMatthew G. Knepley 86277623264SMatthew G. Knepley Collective on PetscPartitioner 86377623264SMatthew G. Knepley 86477623264SMatthew G. Knepley Input Parameter: 86577623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 86677623264SMatthew G. Knepley 86777623264SMatthew G. Knepley Level: developer 86877623264SMatthew G. Knepley 86977623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 87077623264SMatthew G. Knepley @*/ 87177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 87277623264SMatthew G. Knepley { 87377623264SMatthew G. Knepley PetscErrorCode ierr; 87477623264SMatthew G. Knepley 87577623264SMatthew G. Knepley PetscFunctionBegin; 87677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 87777623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 87877623264SMatthew G. Knepley PetscFunctionReturn(0); 87977623264SMatthew G. Knepley } 88077623264SMatthew G. Knepley 88177623264SMatthew G. Knepley /*@ 88277623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 88377623264SMatthew G. Knepley 88477623264SMatthew G. Knepley Collective on PetscPartitioner 88577623264SMatthew G. Knepley 88677623264SMatthew G. Knepley Input Parameter: 88777623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 88877623264SMatthew G. Knepley 88977623264SMatthew G. Knepley Level: developer 89077623264SMatthew G. Knepley 89177623264SMatthew G. Knepley .seealso: PetscPartitionerView() 89277623264SMatthew G. Knepley @*/ 89377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 89477623264SMatthew G. Knepley { 89577623264SMatthew G. Knepley PetscErrorCode ierr; 89677623264SMatthew G. Knepley 89777623264SMatthew G. Knepley PetscFunctionBegin; 89877623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 89977623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 90077623264SMatthew G. Knepley 90177623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 90277623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 90377623264SMatthew G. Knepley 9040358368aSMatthew G. Knepley ierr = PetscViewerDestroy(&(*part)->viewerGraph);CHKERRQ(ierr); 90577623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 90677623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 90777623264SMatthew G. Knepley PetscFunctionReturn(0); 90877623264SMatthew G. Knepley } 90977623264SMatthew G. Knepley 91077623264SMatthew G. Knepley /*@ 91177623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 91277623264SMatthew G. Knepley 91377623264SMatthew G. Knepley Collective on MPI_Comm 91477623264SMatthew G. Knepley 91577623264SMatthew G. Knepley Input Parameter: 91677623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 91777623264SMatthew G. Knepley 91877623264SMatthew G. Knepley Output Parameter: 91977623264SMatthew G. Knepley . part - The PetscPartitioner object 92077623264SMatthew G. Knepley 92177623264SMatthew G. Knepley Level: beginner 92277623264SMatthew G. Knepley 923dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 92477623264SMatthew G. Knepley @*/ 92577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 92677623264SMatthew G. Knepley { 92777623264SMatthew G. Knepley PetscPartitioner p; 928a0058e54SToby Isaac const char *partitionerType = NULL; 92977623264SMatthew G. Knepley PetscErrorCode ierr; 93077623264SMatthew G. Knepley 93177623264SMatthew G. Knepley PetscFunctionBegin; 93277623264SMatthew G. Knepley PetscValidPointer(part, 2); 93377623264SMatthew G. Knepley *part = NULL; 93483cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 93577623264SMatthew G. Knepley 93673107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 937a0058e54SToby Isaac ierr = PetscPartitionerGetDefaultType(NULL,&partitionerType);CHKERRQ(ierr); 938a0058e54SToby Isaac ierr = PetscPartitionerSetType(p,partitionerType);CHKERRQ(ierr); 93977623264SMatthew G. Knepley 94072379da4SMatthew G. Knepley p->edgeCut = 0; 94172379da4SMatthew G. Knepley p->balance = 0.0; 94272379da4SMatthew G. Knepley 94377623264SMatthew G. Knepley *part = p; 94477623264SMatthew G. Knepley PetscFunctionReturn(0); 94577623264SMatthew G. Knepley } 94677623264SMatthew G. Knepley 94777623264SMatthew G. Knepley /*@ 94877623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 94977623264SMatthew G. Knepley 95077623264SMatthew G. Knepley Collective on DM 95177623264SMatthew G. Knepley 95277623264SMatthew G. Knepley Input Parameters: 95377623264SMatthew G. Knepley + part - The PetscPartitioner 954f8987ae8SMichael Lange - dm - The mesh DM 95577623264SMatthew G. Knepley 95677623264SMatthew G. Knepley Output Parameters: 95777623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 958f8987ae8SMichael Lange - partition - The list of points by partition 95977623264SMatthew G. Knepley 9600358368aSMatthew G. Knepley Options Database: 9610358368aSMatthew G. Knepley . -petscpartitioner_view_graph - View the graph we are partitioning 9620358368aSMatthew G. Knepley 96377623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 96477623264SMatthew G. Knepley 96577623264SMatthew G. Knepley Level: developer 96677623264SMatthew G. Knepley 96777623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 9684b15ede2SMatthew G. Knepley @*/ 969f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 97077623264SMatthew G. Knepley { 97177623264SMatthew G. Knepley PetscMPIInt size; 97277623264SMatthew G. Knepley PetscErrorCode ierr; 97377623264SMatthew G. Knepley 97477623264SMatthew G. Knepley PetscFunctionBegin; 97577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 97677623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 97777623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 97877623264SMatthew G. Knepley PetscValidPointer(partition, 5); 97977623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 98077623264SMatthew G. Knepley if (size == 1) { 98177623264SMatthew G. Knepley PetscInt *points; 98277623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 98377623264SMatthew G. Knepley 98477623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 98577623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 98677623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 98777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 98877623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 98977623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 99077623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 99177623264SMatthew G. Knepley PetscFunctionReturn(0); 99277623264SMatthew G. Knepley } 99377623264SMatthew G. Knepley if (part->height == 0) { 994074d466cSStefano Zampini PetscInt numVertices = 0; 99577623264SMatthew G. Knepley PetscInt *start = NULL; 99677623264SMatthew G. Knepley PetscInt *adjacency = NULL; 9973fa7752dSToby Isaac IS globalNumbering; 99877623264SMatthew G. Knepley 999074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 1000074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 1001074d466cSStefano Zampini } else { 1002074d466cSStefano Zampini const PetscInt *idxs; 1003074d466cSStefano Zampini PetscInt p, pStart, pEnd; 1004074d466cSStefano Zampini 1005074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 1006074d466cSStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 1007074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 1008074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 1009074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 1010074d466cSStefano Zampini } 10110358368aSMatthew G. Knepley if (part->viewGraph) { 10120358368aSMatthew G. Knepley PetscViewer viewer = part->viewerGraph; 10130358368aSMatthew G. Knepley PetscBool isascii; 10140358368aSMatthew G. Knepley PetscInt v, i; 10150358368aSMatthew G. Knepley PetscMPIInt rank; 10160358368aSMatthew G. Knepley 10170358368aSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRQ(ierr); 10180358368aSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 10190358368aSMatthew G. Knepley if (isascii) { 10200358368aSMatthew G. Knepley ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 10210358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);CHKERRQ(ierr); 10220358368aSMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 10230358368aSMatthew G. Knepley const PetscInt s = start[v]; 10240358368aSMatthew G. Knepley const PetscInt e = start[v+1]; 10250358368aSMatthew G. Knepley 10260358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank);CHKERRQ(ierr); 10270358368aSMatthew G. Knepley for (i = s; i < e; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);CHKERRQ(ierr);} 10280358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);CHKERRQ(ierr); 10290358368aSMatthew G. Knepley } 10300358368aSMatthew G. Knepley ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 10310358368aSMatthew G. Knepley ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 10320358368aSMatthew G. Knepley } 10330358368aSMatthew G. Knepley } 1034bbbc8e51SStefano Zampini if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no partitioning method"); 103577623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 103677623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 103777623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 10383fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 10393fa7752dSToby Isaac const PetscInt *globalNum; 10403fa7752dSToby Isaac const PetscInt *partIdx; 10413fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 10423fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 10433fa7752dSToby Isaac IS newPartition; 10443fa7752dSToby Isaac 10453fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 10463fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 10473fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10483fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 10493fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 10503fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 10513fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 10523fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 10533fa7752dSToby Isaac } 10543fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 10553fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 10563fa7752dSToby Isaac } 10573fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 10583fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 10593fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10603fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 10613fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 10623fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 10633fa7752dSToby Isaac *partition = newPartition; 10643fa7752dSToby Isaac } 106577623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 10662abdaa70SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 106777623264SMatthew G. Knepley PetscFunctionReturn(0); 106877623264SMatthew G. Knepley } 106977623264SMatthew G. Knepley 1070d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 107177623264SMatthew G. Knepley { 107277623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 107377623264SMatthew G. Knepley PetscErrorCode ierr; 107477623264SMatthew G. Knepley 107577623264SMatthew G. Knepley PetscFunctionBegin; 107677623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 107777623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 107877623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 107977623264SMatthew G. Knepley PetscFunctionReturn(0); 108077623264SMatthew G. Knepley } 108177623264SMatthew G. Knepley 1082d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 108377623264SMatthew G. Knepley { 1084077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 108577623264SMatthew G. Knepley PetscErrorCode ierr; 108677623264SMatthew G. Knepley 108777623264SMatthew G. Knepley PetscFunctionBegin; 1088077101c0SMatthew G. Knepley if (p->random) { 1089077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1090077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 1091077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1092077101c0SMatthew G. Knepley } 109377623264SMatthew G. Knepley PetscFunctionReturn(0); 109477623264SMatthew G. Knepley } 109577623264SMatthew G. Knepley 1096d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 109777623264SMatthew G. Knepley { 109877623264SMatthew G. Knepley PetscBool iascii; 109977623264SMatthew G. Knepley PetscErrorCode ierr; 110077623264SMatthew G. Knepley 110177623264SMatthew G. Knepley PetscFunctionBegin; 110277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 110377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 110477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 110577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 110677623264SMatthew G. Knepley PetscFunctionReturn(0); 110777623264SMatthew G. Knepley } 110877623264SMatthew G. Knepley 1109d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 1110077101c0SMatthew G. Knepley { 1111077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1112077101c0SMatthew G. Knepley PetscErrorCode ierr; 1113077101c0SMatthew G. Knepley 1114077101c0SMatthew G. Knepley PetscFunctionBegin; 1115077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 1116077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 1117077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1118077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1119077101c0SMatthew G. Knepley } 1120077101c0SMatthew G. Knepley 1121d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 112277623264SMatthew G. Knepley { 112377623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 112477623264SMatthew G. Knepley PetscInt np; 112577623264SMatthew G. Knepley PetscErrorCode ierr; 112677623264SMatthew G. Knepley 112777623264SMatthew G. Knepley PetscFunctionBegin; 1128077101c0SMatthew G. Knepley if (p->random) { 1129077101c0SMatthew G. Knepley PetscRandom r; 1130aa1d5631SMatthew G. Knepley PetscInt *sizes, *points, v, p; 1131aa1d5631SMatthew G. Knepley PetscMPIInt rank; 1132077101c0SMatthew G. Knepley 1133aa1d5631SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1134077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 1135c717d290SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 1136077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 1137077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 1138aa1d5631SMatthew G. Knepley for (v = 0; v < numVertices; ++v) {points[v] = v;} 1139ac9a96f1SMichael Lange for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 1140aa1d5631SMatthew G. Knepley for (v = numVertices-1; v > 0; --v) { 1141077101c0SMatthew G. Knepley PetscReal val; 1142aa1d5631SMatthew G. Knepley PetscInt w, tmp; 1143077101c0SMatthew G. Knepley 1144aa1d5631SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 1145077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 1146aa1d5631SMatthew G. Knepley w = PetscFloorReal(val); 1147aa1d5631SMatthew G. Knepley tmp = points[v]; 1148aa1d5631SMatthew G. Knepley points[v] = points[w]; 1149aa1d5631SMatthew G. Knepley points[w] = tmp; 1150077101c0SMatthew G. Knepley } 1151077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 1152077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 1153077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 1154077101c0SMatthew G. Knepley } 1155c717d290SMatthew G. Knepley if (!p->section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 115677623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 115777623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 115877623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 115977623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 11605680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 116177623264SMatthew G. Knepley *partition = p->partition; 116277623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 116377623264SMatthew G. Knepley PetscFunctionReturn(0); 116477623264SMatthew G. Knepley } 116577623264SMatthew G. Knepley 1166d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 116777623264SMatthew G. Knepley { 116877623264SMatthew G. Knepley PetscFunctionBegin; 1169074d466cSStefano Zampini part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 117077623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 1171077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 117277623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 117377623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 117477623264SMatthew G. Knepley PetscFunctionReturn(0); 117577623264SMatthew G. Knepley } 117677623264SMatthew G. Knepley 117777623264SMatthew G. Knepley /*MC 117877623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 117977623264SMatthew G. Knepley 118077623264SMatthew G. Knepley Level: intermediate 118177623264SMatthew G. Knepley 118277623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 118377623264SMatthew G. Knepley M*/ 118477623264SMatthew G. Knepley 118577623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 118677623264SMatthew G. Knepley { 118777623264SMatthew G. Knepley PetscPartitioner_Shell *p; 118877623264SMatthew G. Knepley PetscErrorCode ierr; 118977623264SMatthew G. Knepley 119077623264SMatthew G. Knepley PetscFunctionBegin; 119177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 119277623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 119377623264SMatthew G. Knepley part->data = p; 119477623264SMatthew G. Knepley 119577623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 1196077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 119777623264SMatthew G. Knepley PetscFunctionReturn(0); 119877623264SMatthew G. Knepley } 119977623264SMatthew G. Knepley 12005680f57bSMatthew G. Knepley /*@C 12015680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 12025680f57bSMatthew G. Knepley 1203077101c0SMatthew G. Knepley Collective on Part 12045680f57bSMatthew G. Knepley 12055680f57bSMatthew G. Knepley Input Parameters: 12065680f57bSMatthew G. Knepley + part - The PetscPartitioner 12079852e123SBarry Smith . size - The number of partitions 12089852e123SBarry Smith . sizes - array of size size (or NULL) providing the number of points in each partition 12099758bf69SToby 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.) 12105680f57bSMatthew G. Knepley 12115680f57bSMatthew G. Knepley Level: developer 12125680f57bSMatthew G. Knepley 1213b7e49471SLawrence Mitchell Notes: 1214b7e49471SLawrence Mitchell 1215b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 1216b7e49471SLawrence Mitchell 12175680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 12185680f57bSMatthew G. Knepley @*/ 12199852e123SBarry Smith PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 12205680f57bSMatthew G. Knepley { 12215680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 12225680f57bSMatthew G. Knepley PetscInt proc, numPoints; 12235680f57bSMatthew G. Knepley PetscErrorCode ierr; 12245680f57bSMatthew G. Knepley 12255680f57bSMatthew G. Knepley PetscFunctionBegin; 12265680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 12275680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 1228c717d290SMatthew G. Knepley if (points) {PetscValidPointer(points, 4);} 12295680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 12305680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 12315680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 12329852e123SBarry Smith ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 12335680f57bSMatthew G. Knepley if (sizes) { 12349852e123SBarry Smith for (proc = 0; proc < size; ++proc) { 12355680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 12365680f57bSMatthew G. Knepley } 12375680f57bSMatthew G. Knepley } 12385680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 12395680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 12405680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 12415680f57bSMatthew G. Knepley PetscFunctionReturn(0); 12425680f57bSMatthew G. Knepley } 12435680f57bSMatthew G. Knepley 1244077101c0SMatthew G. Knepley /*@ 1245077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 1246077101c0SMatthew G. Knepley 1247077101c0SMatthew G. Knepley Collective on Part 1248077101c0SMatthew G. Knepley 1249077101c0SMatthew G. Knepley Input Parameters: 1250077101c0SMatthew G. Knepley + part - The PetscPartitioner 1251077101c0SMatthew G. Knepley - random - The flag to use a random partition 1252077101c0SMatthew G. Knepley 1253077101c0SMatthew G. Knepley Level: intermediate 1254077101c0SMatthew G. Knepley 1255077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 1256077101c0SMatthew G. Knepley @*/ 1257077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 1258077101c0SMatthew G. Knepley { 1259077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1260077101c0SMatthew G. Knepley 1261077101c0SMatthew G. Knepley PetscFunctionBegin; 1262077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1263077101c0SMatthew G. Knepley p->random = random; 1264077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1265077101c0SMatthew G. Knepley } 1266077101c0SMatthew G. Knepley 1267077101c0SMatthew G. Knepley /*@ 1268077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 1269077101c0SMatthew G. Knepley 1270077101c0SMatthew G. Knepley Collective on Part 1271077101c0SMatthew G. Knepley 1272077101c0SMatthew G. Knepley Input Parameter: 1273077101c0SMatthew G. Knepley . part - The PetscPartitioner 1274077101c0SMatthew G. Knepley 1275077101c0SMatthew G. Knepley Output Parameter 1276077101c0SMatthew G. Knepley . random - The flag to use a random partition 1277077101c0SMatthew G. Knepley 1278077101c0SMatthew G. Knepley Level: intermediate 1279077101c0SMatthew G. Knepley 1280077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 1281077101c0SMatthew G. Knepley @*/ 1282077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 1283077101c0SMatthew G. Knepley { 1284077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1285077101c0SMatthew G. Knepley 1286077101c0SMatthew G. Knepley PetscFunctionBegin; 1287077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1288077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 1289077101c0SMatthew G. Knepley *random = p->random; 1290077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1291077101c0SMatthew G. Knepley } 1292077101c0SMatthew G. Knepley 1293d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 1294555a9cf8SMatthew G. Knepley { 1295555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 1296555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1297555a9cf8SMatthew G. Knepley 1298555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1299555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 1300555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1301555a9cf8SMatthew G. Knepley } 1302555a9cf8SMatthew G. Knepley 1303d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 1304555a9cf8SMatthew G. Knepley { 1305555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1306555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1307555a9cf8SMatthew G. Knepley } 1308555a9cf8SMatthew G. Knepley 1309d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 1310555a9cf8SMatthew G. Knepley { 1311555a9cf8SMatthew G. Knepley PetscBool iascii; 1312555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1313555a9cf8SMatthew G. Knepley 1314555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1315555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1316555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1317555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1318555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 1319555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1320555a9cf8SMatthew G. Knepley } 1321555a9cf8SMatthew G. Knepley 1322d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1323555a9cf8SMatthew G. Knepley { 1324cead94edSToby Isaac MPI_Comm comm; 1325555a9cf8SMatthew G. Knepley PetscInt np; 1326cead94edSToby Isaac PetscMPIInt size; 1327555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1328555a9cf8SMatthew G. Knepley 1329555a9cf8SMatthew G. Knepley PetscFunctionBegin; 133004ba2274SStefano Zampini comm = PetscObjectComm((PetscObject)part); 1331cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1332555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1333555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1334cead94edSToby Isaac if (size == 1) { 1335cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 133604ba2274SStefano Zampini } else { 1337cead94edSToby Isaac PetscMPIInt rank; 1338cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 1339cead94edSToby Isaac 1340a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1341cead94edSToby Isaac offsets[0] = 0; 1342cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1343cead94edSToby Isaac for (np = 2; np <= size; np++) { 1344cead94edSToby Isaac offsets[np] += offsets[np-1]; 1345cead94edSToby Isaac } 1346cead94edSToby Isaac nvGlobal = offsets[size]; 1347cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1348cead94edSToby Isaac myFirst = offsets[rank]; 1349cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1350cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1351cead94edSToby Isaac if (numVertices) { 1352cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1353cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1354cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1355cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1356cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1357cead94edSToby Isaac 1358cead94edSToby Isaac 1359cead94edSToby Isaac if (rem) { 1360cead94edSToby Isaac firstLargePart = myFirst / pBig; 1361cead94edSToby Isaac lastLargePart = myLast / pBig; 1362cead94edSToby Isaac 1363cead94edSToby Isaac if (firstLargePart < rem) { 1364cead94edSToby Isaac firstPart = firstLargePart; 136504ba2274SStefano Zampini } else { 1366cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1367cead94edSToby Isaac } 1368cead94edSToby Isaac if (lastLargePart < rem) { 1369cead94edSToby Isaac lastPart = lastLargePart; 137004ba2274SStefano Zampini } else { 1371cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1372cead94edSToby Isaac } 137304ba2274SStefano Zampini } else { 1374cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1375cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1376cead94edSToby Isaac } 1377cead94edSToby Isaac 1378cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1379cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1380cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1381cead94edSToby Isaac 1382cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1383cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1384cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1385cead94edSToby Isaac } 1386cead94edSToby Isaac } 1387cead94edSToby Isaac } 1388cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1389555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1390555a9cf8SMatthew G. Knepley } 1391555a9cf8SMatthew G. Knepley 1392d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1393555a9cf8SMatthew G. Knepley { 1394555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1395074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1396555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1397555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1398555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1399555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1400555a9cf8SMatthew G. Knepley } 1401555a9cf8SMatthew G. Knepley 1402555a9cf8SMatthew G. Knepley /*MC 1403555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1404555a9cf8SMatthew G. Knepley 1405555a9cf8SMatthew G. Knepley Level: intermediate 1406555a9cf8SMatthew G. Knepley 1407555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1408555a9cf8SMatthew G. Knepley M*/ 1409555a9cf8SMatthew G. Knepley 1410555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1411555a9cf8SMatthew G. Knepley { 1412555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1413555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1414555a9cf8SMatthew G. Knepley 1415555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1416555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1417555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1418555a9cf8SMatthew G. Knepley part->data = p; 1419555a9cf8SMatthew G. Knepley 1420555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1421555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1422555a9cf8SMatthew G. Knepley } 1423555a9cf8SMatthew G. Knepley 1424d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1425dae52e14SToby Isaac { 1426dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1427dae52e14SToby Isaac PetscErrorCode ierr; 1428dae52e14SToby Isaac 1429dae52e14SToby Isaac PetscFunctionBegin; 1430dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1431dae52e14SToby Isaac PetscFunctionReturn(0); 1432dae52e14SToby Isaac } 1433dae52e14SToby Isaac 1434d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1435dae52e14SToby Isaac { 1436dae52e14SToby Isaac PetscFunctionBegin; 1437dae52e14SToby Isaac PetscFunctionReturn(0); 1438dae52e14SToby Isaac } 1439dae52e14SToby Isaac 1440d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1441dae52e14SToby Isaac { 1442dae52e14SToby Isaac PetscBool iascii; 1443dae52e14SToby Isaac PetscErrorCode ierr; 1444dae52e14SToby Isaac 1445dae52e14SToby Isaac PetscFunctionBegin; 1446dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1447dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1448dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1449dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1450dae52e14SToby Isaac PetscFunctionReturn(0); 1451dae52e14SToby Isaac } 1452dae52e14SToby Isaac 1453d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1454dae52e14SToby Isaac { 1455dae52e14SToby Isaac PetscInt np; 1456dae52e14SToby Isaac PetscErrorCode ierr; 1457dae52e14SToby Isaac 1458dae52e14SToby Isaac PetscFunctionBegin; 1459dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1460dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1461dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1462dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1463dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1464dae52e14SToby Isaac PetscFunctionReturn(0); 1465dae52e14SToby Isaac } 1466dae52e14SToby Isaac 1467d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1468dae52e14SToby Isaac { 1469dae52e14SToby Isaac PetscFunctionBegin; 1470074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1471dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1472dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1473dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1474dae52e14SToby Isaac PetscFunctionReturn(0); 1475dae52e14SToby Isaac } 1476dae52e14SToby Isaac 1477dae52e14SToby Isaac /*MC 1478dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1479dae52e14SToby Isaac 1480dae52e14SToby Isaac Level: intermediate 1481dae52e14SToby Isaac 1482dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1483dae52e14SToby Isaac M*/ 1484dae52e14SToby Isaac 1485dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1486dae52e14SToby Isaac { 1487dae52e14SToby Isaac PetscPartitioner_Gather *p; 1488dae52e14SToby Isaac PetscErrorCode ierr; 1489dae52e14SToby Isaac 1490dae52e14SToby Isaac PetscFunctionBegin; 1491dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1492dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1493dae52e14SToby Isaac part->data = p; 1494dae52e14SToby Isaac 1495dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1496dae52e14SToby Isaac PetscFunctionReturn(0); 1497dae52e14SToby Isaac } 1498dae52e14SToby Isaac 1499dae52e14SToby Isaac 1500d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 150177623264SMatthew G. Knepley { 150277623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 150377623264SMatthew G. Knepley PetscErrorCode ierr; 150477623264SMatthew G. Knepley 150577623264SMatthew G. Knepley PetscFunctionBegin; 150677623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 150777623264SMatthew G. Knepley PetscFunctionReturn(0); 150877623264SMatthew G. Knepley } 150977623264SMatthew G. Knepley 1510d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 151177623264SMatthew G. Knepley { 151277623264SMatthew G. Knepley PetscFunctionBegin; 151377623264SMatthew G. Knepley PetscFunctionReturn(0); 151477623264SMatthew G. Knepley } 151577623264SMatthew G. Knepley 1516d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 151777623264SMatthew G. Knepley { 151877623264SMatthew G. Knepley PetscBool iascii; 151977623264SMatthew G. Knepley PetscErrorCode ierr; 152077623264SMatthew G. Knepley 152177623264SMatthew G. Knepley PetscFunctionBegin; 152277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 152377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 152477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 152577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 152677623264SMatthew G. Knepley PetscFunctionReturn(0); 152777623264SMatthew G. Knepley } 152877623264SMatthew G. Knepley 152970034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 153070034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 153170034214SMatthew G. Knepley #include <unistd.h> 153270034214SMatthew G. Knepley #endif 153311d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 153411d1e910SBarry Smith #include <chaco.h> 153511d1e910SBarry Smith #else 153611d1e910SBarry Smith /* Older versions of Chaco do not have an include file */ 153770034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 153870034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 153970034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 154070034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 154170034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 154211d1e910SBarry Smith #endif 154370034214SMatthew G. Knepley extern int FREE_GRAPH; 154477623264SMatthew G. Knepley #endif 154570034214SMatthew G. Knepley 1546d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 154770034214SMatthew G. Knepley { 154877623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 154970034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 155070034214SMatthew G. Knepley MPI_Comm comm; 155170034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 155270034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 155370034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 155470034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 155570034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 155670034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 155770034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 155870034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 155970034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 156070034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 156170034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 156270034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 156370034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 156470034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 156570034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 156670034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 156770034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 156811d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 156911d1e910SBarry Smith int *assignment; /* Output partition */ 157011d1e910SBarry Smith #else 157170034214SMatthew G. Knepley short int *assignment; /* Output partition */ 157211d1e910SBarry Smith #endif 157370034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 157470034214SMatthew G. Knepley PetscInt *points; 157570034214SMatthew G. Knepley int i, v, p; 157670034214SMatthew G. Knepley PetscErrorCode ierr; 157770034214SMatthew G. Knepley 157870034214SMatthew G. Knepley PetscFunctionBegin; 157970034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 158007ed3857SLisandro Dalcin #if defined (PETSC_USE_DEBUG) 158107ed3857SLisandro Dalcin { 158207ed3857SLisandro Dalcin int ival,isum; 158307ed3857SLisandro Dalcin PetscBool distributed; 158407ed3857SLisandro Dalcin 158507ed3857SLisandro Dalcin ival = (numVertices > 0); 158607ed3857SLisandro Dalcin ierr = MPI_Allreduce(&ival, &isum, 1, MPI_INT, MPI_SUM, comm);CHKERRQ(ierr); 158707ed3857SLisandro Dalcin distributed = (isum > 1) ? PETSC_TRUE : PETSC_FALSE; 158807ed3857SLisandro Dalcin if (distributed) SETERRQ(comm, PETSC_ERR_SUP, "Chaco cannot partition a distributed graph"); 158907ed3857SLisandro Dalcin } 159007ed3857SLisandro Dalcin #endif 159170034214SMatthew G. Knepley if (!numVertices) { 159277623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 159377623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 159470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 159570034214SMatthew G. Knepley PetscFunctionReturn(0); 159670034214SMatthew G. Knepley } 159770034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 159870034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 159970034214SMatthew G. Knepley 160070034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 160170034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 160270034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 160370034214SMatthew G. Knepley } 160477623264SMatthew G. Knepley mesh_dims[0] = nparts; 160570034214SMatthew G. Knepley mesh_dims[1] = 1; 160670034214SMatthew G. Knepley mesh_dims[2] = 1; 160770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 160870034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 160970034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 161070034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 161170034214SMatthew G. Knepley { 161270034214SMatthew G. Knepley int piperet; 161370034214SMatthew G. Knepley piperet = pipe(fd_pipe); 161470034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 161570034214SMatthew G. Knepley fd_stdout = dup(1); 161670034214SMatthew G. Knepley close(1); 161770034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 161870034214SMatthew G. Knepley } 161970034214SMatthew G. Knepley #endif 162070034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 162170034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 162270034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 162370034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 162470034214SMatthew G. Knepley { 162570034214SMatthew G. Knepley char msgLog[10000]; 162670034214SMatthew G. Knepley int count; 162770034214SMatthew G. Knepley 162870034214SMatthew G. Knepley fflush(stdout); 162970034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 163070034214SMatthew G. Knepley if (count < 0) count = 0; 163170034214SMatthew G. Knepley msgLog[count] = 0; 163270034214SMatthew G. Knepley close(1); 163370034214SMatthew G. Knepley dup2(fd_stdout, 1); 163470034214SMatthew G. Knepley close(fd_stdout); 163570034214SMatthew G. Knepley close(fd_pipe[0]); 163670034214SMatthew G. Knepley close(fd_pipe[1]); 163770034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 163870034214SMatthew G. Knepley } 163907ed3857SLisandro Dalcin #else 164007ed3857SLisandro Dalcin if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", "error in stdout"); 164170034214SMatthew G. Knepley #endif 164270034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 164377623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 164470034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 164577623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 164670034214SMatthew G. Knepley } 164777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 164870034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 164977623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 165070034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 165170034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 165270034214SMatthew G. Knepley } 165370034214SMatthew G. Knepley } 165470034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 165570034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 165670034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 165770034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 165870034214SMatthew G. Knepley } 165970034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 166070034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 166170034214SMatthew G. Knepley PetscFunctionReturn(0); 166277623264SMatthew G. Knepley #else 166377623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 166470034214SMatthew G. Knepley #endif 166577623264SMatthew G. Knepley } 166677623264SMatthew G. Knepley 1667d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 166877623264SMatthew G. Knepley { 166977623264SMatthew G. Knepley PetscFunctionBegin; 1670074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 167177623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 167277623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 167377623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 167477623264SMatthew G. Knepley PetscFunctionReturn(0); 167577623264SMatthew G. Knepley } 167677623264SMatthew G. Knepley 167777623264SMatthew G. Knepley /*MC 167877623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 167977623264SMatthew G. Knepley 168077623264SMatthew G. Knepley Level: intermediate 168177623264SMatthew G. Knepley 168277623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 168377623264SMatthew G. Knepley M*/ 168477623264SMatthew G. Knepley 168577623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 168677623264SMatthew G. Knepley { 168777623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 168877623264SMatthew G. Knepley PetscErrorCode ierr; 168977623264SMatthew G. Knepley 169077623264SMatthew G. Knepley PetscFunctionBegin; 169177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 169277623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 169377623264SMatthew G. Knepley part->data = p; 169477623264SMatthew G. Knepley 169577623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 169677623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 169777623264SMatthew G. Knepley PetscFunctionReturn(0); 169877623264SMatthew G. Knepley } 169977623264SMatthew G. Knepley 17005b440754SMatthew G. Knepley static const char *ptypes[] = {"kway", "rb"}; 17015b440754SMatthew G. Knepley 1702d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 170377623264SMatthew G. Knepley { 170477623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 170577623264SMatthew G. Knepley PetscErrorCode ierr; 170677623264SMatthew G. Knepley 170777623264SMatthew G. Knepley PetscFunctionBegin; 170877623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 170977623264SMatthew G. Knepley PetscFunctionReturn(0); 171077623264SMatthew G. Knepley } 171177623264SMatthew G. Knepley 1712d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 171377623264SMatthew G. Knepley { 17142abdaa70SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 171577623264SMatthew G. Knepley PetscErrorCode ierr; 171677623264SMatthew G. Knepley 171777623264SMatthew G. Knepley PetscFunctionBegin; 17182abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 17192abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 17202abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 17212abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 17222abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 172377623264SMatthew G. Knepley PetscFunctionReturn(0); 172477623264SMatthew G. Knepley } 172577623264SMatthew G. Knepley 1726d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 172777623264SMatthew G. Knepley { 172877623264SMatthew G. Knepley PetscBool iascii; 172977623264SMatthew G. Knepley PetscErrorCode ierr; 173077623264SMatthew G. Knepley 173177623264SMatthew G. Knepley PetscFunctionBegin; 173277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 173377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 173477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 173577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 173677623264SMatthew G. Knepley PetscFunctionReturn(0); 173777623264SMatthew G. Knepley } 173870034214SMatthew G. Knepley 173944d8be81SLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 174044d8be81SLisandro Dalcin { 174144d8be81SLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 174242678178SLisandro Dalcin PetscInt p_randomSeed = -1; /* TODO: Add this to PetscPartitioner_ParMetis */ 174344d8be81SLisandro Dalcin PetscErrorCode ierr; 174444d8be81SLisandro Dalcin 174544d8be81SLisandro Dalcin PetscFunctionBegin; 174644d8be81SLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 174744d8be81SLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 17485b440754SMatthew G. Knepley ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 17495b440754SMatthew G. Knepley ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 175042678178SLisandro Dalcin ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p_randomSeed, &p_randomSeed, NULL);CHKERRQ(ierr); 175144d8be81SLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 175244d8be81SLisandro Dalcin PetscFunctionReturn(0); 175344d8be81SLisandro Dalcin } 175444d8be81SLisandro Dalcin 175570034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 175670034214SMatthew G. Knepley #include <parmetis.h> 175777623264SMatthew G. Knepley #endif 175870034214SMatthew G. Knepley 1759d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 176070034214SMatthew G. Knepley { 176177623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 17625b440754SMatthew G. Knepley PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 176370034214SMatthew G. Knepley MPI_Comm comm; 1764deea36a5SMatthew G. Knepley PetscSection section; 176570034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 176670034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 176770034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 176870034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 176970034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 177070034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 177170034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 177270034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 177370034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 17745b440754SMatthew G. Knepley PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 1775fb83b9f2SMichael Gegg real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 1776fb83b9f2SMichael Gegg real_t *ubvec; /* The balance intolerance for vertex weights */ 1777b3ce585bSLisandro Dalcin PetscInt options[64]; /* Options */ 177870034214SMatthew G. Knepley /* Outputs */ 1779b3ce585bSLisandro Dalcin PetscInt v, i, *assignment, *points; 1780b3ce585bSLisandro Dalcin PetscMPIInt size, rank, p; 178142678178SLisandro Dalcin PetscInt pm_randomSeed = -1; 178270034214SMatthew G. Knepley PetscErrorCode ierr; 178370034214SMatthew G. Knepley 178470034214SMatthew G. Knepley PetscFunctionBegin; 178542678178SLisandro Dalcin ierr = PetscOptionsGetInt(((PetscObject)part)->options,((PetscObject)part)->prefix,"-petscpartitioner_parmetis_seed", &pm_randomSeed, NULL);CHKERRQ(ierr); 178677623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 1787b3ce585bSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 178870034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 178970034214SMatthew G. Knepley /* Calculate vertex distribution */ 1790b3ce585bSLisandro Dalcin ierr = PetscMalloc5(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment,nvtxs,&vwgt);CHKERRQ(ierr); 179170034214SMatthew G. Knepley vtxdist[0] = 0; 179270034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1793b3ce585bSLisandro Dalcin for (p = 2; p <= size; ++p) { 179470034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 179570034214SMatthew G. Knepley } 179644d8be81SLisandro Dalcin /* Calculate partition weights */ 179770034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 179870034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 179970034214SMatthew G. Knepley } 18005b440754SMatthew G. Knepley ubvec[0] = pm->imbalanceRatio; 1801deea36a5SMatthew G. Knepley /* Weight cells by dofs on cell by default */ 1802e87a4003SBarry Smith ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 1803*8ef05d33SStefano Zampini for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1804deea36a5SMatthew G. Knepley if (section) { 1805deea36a5SMatthew G. Knepley PetscInt cStart, cEnd, dof; 180670034214SMatthew G. Knepley 1807925b1076SLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 1808925b1076SLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 1809*8ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 1810*8ef05d33SStefano Zampini for (v = cStart; v < cStart + numVertices; ++v) { 1811*8ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 1812*8ef05d33SStefano Zampini vwgt[v-cStart] = PetscMax(dof, 1); 1813deea36a5SMatthew G. Knepley } 1814cd0de0f2SShri } 181544d8be81SLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 1816cd0de0f2SShri 181770034214SMatthew G. Knepley if (nparts == 1) { 18189fc93327SToby Isaac ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 181970034214SMatthew G. Knepley } else { 1820b3ce585bSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 1821b3ce585bSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 1822b3ce585bSLisandro Dalcin if (rank == p) { 182344d8be81SLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 182442678178SLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 182542678178SLisandro Dalcin options[METIS_OPTION_SEED] = pm_randomSeed; 182644d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 182744d8be81SLisandro Dalcin if (metis_ptype == 1) { 182844d8be81SLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 182972379da4SMatthew G. Knepley ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 183044d8be81SLisandro Dalcin PetscStackPop; 183144d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 183244d8be81SLisandro Dalcin } else { 183344d8be81SLisandro Dalcin /* 183444d8be81SLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 183544d8be81SLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 183644d8be81SLisandro 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. 183744d8be81SLisandro Dalcin */ 183844d8be81SLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 183944d8be81SLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 184070034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 184172379da4SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 184270034214SMatthew G. Knepley PetscStackPop; 184370034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 184470034214SMatthew G. Knepley } 184544d8be81SLisandro Dalcin } 184670034214SMatthew G. Knepley } else { 184742678178SLisandro Dalcin options[0] = 1; /*use options */ 18485b440754SMatthew G. Knepley options[1] = pm->debugFlag; 184942678178SLisandro Dalcin options[2] = (pm_randomSeed == -1) ? 15 : pm_randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 185070034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 185172379da4SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &comm); 185270034214SMatthew G. Knepley PetscStackPop; 1853c717d290SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 185470034214SMatthew G. Knepley } 185570034214SMatthew G. Knepley } 185670034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 185777623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 185877623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 185977623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 186070034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 186177623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 186270034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 186370034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 186470034214SMatthew G. Knepley } 186570034214SMatthew G. Knepley } 186670034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 186770034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1868cd0de0f2SShri ierr = PetscFree5(vtxdist,tpwgts,ubvec,assignment,vwgt);CHKERRQ(ierr); 18699b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 187070034214SMatthew G. Knepley #else 187177623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 187270034214SMatthew G. Knepley #endif 187370034214SMatthew G. Knepley } 187470034214SMatthew G. Knepley 1875d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 187677623264SMatthew G. Knepley { 187777623264SMatthew G. Knepley PetscFunctionBegin; 1878074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 187977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 188044d8be81SLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 188177623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 188277623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 188377623264SMatthew G. Knepley PetscFunctionReturn(0); 188477623264SMatthew G. Knepley } 188577623264SMatthew G. Knepley 188677623264SMatthew G. Knepley /*MC 188777623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 188877623264SMatthew G. Knepley 188977623264SMatthew G. Knepley Level: intermediate 189077623264SMatthew G. Knepley 189177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 189277623264SMatthew G. Knepley M*/ 189377623264SMatthew G. Knepley 189477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 189577623264SMatthew G. Knepley { 189677623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 189777623264SMatthew G. Knepley PetscErrorCode ierr; 189877623264SMatthew G. Knepley 189977623264SMatthew G. Knepley PetscFunctionBegin; 190077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 190177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 190277623264SMatthew G. Knepley part->data = p; 190377623264SMatthew G. Knepley 19045b440754SMatthew G. Knepley p->ptype = 0; 19055b440754SMatthew G. Knepley p->imbalanceRatio = 1.05; 19065b440754SMatthew G. Knepley p->debugFlag = 0; 19075b440754SMatthew G. Knepley 190877623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 190977623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 191070034214SMatthew G. Knepley PetscFunctionReturn(0); 191170034214SMatthew G. Knepley } 191270034214SMatthew G. Knepley 1913137cd93aSLisandro Dalcin PetscBool PTScotchPartitionercite = PETSC_FALSE; 1914137cd93aSLisandro Dalcin const char PTScotchPartitionerCitation[] = 1915137cd93aSLisandro Dalcin "@article{PTSCOTCH,\n" 1916137cd93aSLisandro Dalcin " author = {C. Chevalier and F. Pellegrini},\n" 1917137cd93aSLisandro Dalcin " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 1918137cd93aSLisandro Dalcin " journal = {Parallel Computing},\n" 1919137cd93aSLisandro Dalcin " volume = {34},\n" 1920137cd93aSLisandro Dalcin " number = {6},\n" 1921137cd93aSLisandro Dalcin " pages = {318--331},\n" 1922137cd93aSLisandro Dalcin " year = {2008},\n" 1923137cd93aSLisandro Dalcin " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 1924137cd93aSLisandro Dalcin "}\n"; 1925137cd93aSLisandro Dalcin 1926137cd93aSLisandro Dalcin typedef struct { 1927137cd93aSLisandro Dalcin PetscInt strategy; 1928137cd93aSLisandro Dalcin PetscReal imbalance; 1929137cd93aSLisandro Dalcin } PetscPartitioner_PTScotch; 1930137cd93aSLisandro Dalcin 1931137cd93aSLisandro Dalcin static const char *const 1932137cd93aSLisandro Dalcin PTScotchStrategyList[] = { 1933137cd93aSLisandro Dalcin "DEFAULT", 1934137cd93aSLisandro Dalcin "QUALITY", 1935137cd93aSLisandro Dalcin "SPEED", 1936137cd93aSLisandro Dalcin "BALANCE", 1937137cd93aSLisandro Dalcin "SAFETY", 1938137cd93aSLisandro Dalcin "SCALABILITY", 1939137cd93aSLisandro Dalcin "RECURSIVE", 1940137cd93aSLisandro Dalcin "REMAP" 1941137cd93aSLisandro Dalcin }; 1942137cd93aSLisandro Dalcin 1943137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 1944137cd93aSLisandro Dalcin 1945137cd93aSLisandro Dalcin EXTERN_C_BEGIN 1946137cd93aSLisandro Dalcin #include <ptscotch.h> 1947137cd93aSLisandro Dalcin EXTERN_C_END 1948137cd93aSLisandro Dalcin 1949137cd93aSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 1950137cd93aSLisandro Dalcin 1951137cd93aSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 1952137cd93aSLisandro Dalcin { 1953137cd93aSLisandro Dalcin switch (strategy) { 1954137cd93aSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 1955137cd93aSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 1956137cd93aSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 1957137cd93aSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 1958137cd93aSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 1959137cd93aSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 1960137cd93aSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 1961137cd93aSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 1962137cd93aSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 1963137cd93aSLisandro Dalcin } 1964137cd93aSLisandro Dalcin } 1965137cd93aSLisandro Dalcin 1966137cd93aSLisandro Dalcin 1967137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1968137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[]) 1969137cd93aSLisandro Dalcin { 1970137cd93aSLisandro Dalcin SCOTCH_Graph grafdat; 1971137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1972137cd93aSLisandro Dalcin SCOTCH_Num vertnbr = n; 1973137cd93aSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 1974137cd93aSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 1975137cd93aSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 1976137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1977137cd93aSLisandro Dalcin double kbalval = imbalance; 1978137cd93aSLisandro Dalcin PetscErrorCode ierr; 1979137cd93aSLisandro Dalcin 1980137cd93aSLisandro Dalcin PetscFunctionBegin; 1981d99a0000SVaclav Hapla { 1982d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1983d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1984d99a0000SVaclav Hapla if (!flg) velotab = NULL; 1985d99a0000SVaclav Hapla } 1986137cd93aSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 1987137cd93aSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 1988137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1989137cd93aSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 1990137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1991137cd93aSLisandro Dalcin ierr = SCOTCH_graphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1992137cd93aSLisandro Dalcin #endif 1993137cd93aSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 1994137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 1995137cd93aSLisandro Dalcin SCOTCH_graphExit(&grafdat); 1996137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1997137cd93aSLisandro Dalcin } 1998137cd93aSLisandro Dalcin 1999137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 2000137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[], MPI_Comm comm) 2001137cd93aSLisandro Dalcin { 2002137cd93aSLisandro Dalcin PetscMPIInt procglbnbr; 2003137cd93aSLisandro Dalcin PetscMPIInt proclocnum; 2004137cd93aSLisandro Dalcin SCOTCH_Arch archdat; 2005137cd93aSLisandro Dalcin SCOTCH_Dgraph grafdat; 2006137cd93aSLisandro Dalcin SCOTCH_Dmapping mappdat; 2007137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 2008137cd93aSLisandro Dalcin SCOTCH_Num vertlocnbr; 2009137cd93aSLisandro Dalcin SCOTCH_Num edgelocnbr; 2010137cd93aSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 2011137cd93aSLisandro Dalcin SCOTCH_Num* edloloctab = adjwgt; 2012137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 2013137cd93aSLisandro Dalcin double kbalval = imbalance; 2014137cd93aSLisandro Dalcin PetscErrorCode ierr; 2015137cd93aSLisandro Dalcin 2016137cd93aSLisandro Dalcin PetscFunctionBegin; 2017d99a0000SVaclav Hapla { 2018d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 2019d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 2020d99a0000SVaclav Hapla if (!flg) veloloctab = NULL; 2021d99a0000SVaclav Hapla } 2022137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 2023137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 2024137cd93aSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 2025137cd93aSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 2026137cd93aSLisandro Dalcin 2027137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 2028137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 2029137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 2030137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 2031137cd93aSLisandro Dalcin #endif 2032137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 2033137cd93aSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 2034137cd93aSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 2035137cd93aSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 2036137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 2037cb87ef4cSFlorian Wechsung 2038137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 2039137cd93aSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 2040137cd93aSLisandro Dalcin SCOTCH_archExit(&archdat); 2041137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 2042137cd93aSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 2043137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2044137cd93aSLisandro Dalcin } 2045137cd93aSLisandro Dalcin 2046137cd93aSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 2047137cd93aSLisandro Dalcin 2048137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 2049137cd93aSLisandro Dalcin { 2050137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2051137cd93aSLisandro Dalcin PetscErrorCode ierr; 2052137cd93aSLisandro Dalcin 2053137cd93aSLisandro Dalcin PetscFunctionBegin; 2054137cd93aSLisandro Dalcin ierr = PetscFree(p);CHKERRQ(ierr); 2055137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2056137cd93aSLisandro Dalcin } 2057137cd93aSLisandro Dalcin 2058137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_Ascii(PetscPartitioner part, PetscViewer viewer) 2059137cd93aSLisandro Dalcin { 2060137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2061137cd93aSLisandro Dalcin PetscErrorCode ierr; 2062137cd93aSLisandro Dalcin 2063137cd93aSLisandro Dalcin PetscFunctionBegin; 2064137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2065137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 2066137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 2067137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2068137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2069137cd93aSLisandro Dalcin } 2070137cd93aSLisandro Dalcin 2071137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 2072137cd93aSLisandro Dalcin { 2073137cd93aSLisandro Dalcin PetscBool iascii; 2074137cd93aSLisandro Dalcin PetscErrorCode ierr; 2075137cd93aSLisandro Dalcin 2076137cd93aSLisandro Dalcin PetscFunctionBegin; 2077137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2078137cd93aSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2079137cd93aSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 2080137cd93aSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_Ascii(part, viewer);CHKERRQ(ierr);} 2081137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2082137cd93aSLisandro Dalcin } 2083137cd93aSLisandro Dalcin 2084137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 2085137cd93aSLisandro Dalcin { 2086137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2087137cd93aSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 2088137cd93aSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 2089137cd93aSLisandro Dalcin PetscBool flag; 2090137cd93aSLisandro Dalcin PetscErrorCode ierr; 2091137cd93aSLisandro Dalcin 2092137cd93aSLisandro Dalcin PetscFunctionBegin; 2093137cd93aSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 2094137cd93aSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 2095137cd93aSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 2096137cd93aSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 2097137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2098137cd93aSLisandro Dalcin } 2099137cd93aSLisandro Dalcin 2100137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 2101137cd93aSLisandro Dalcin { 2102137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 2103137cd93aSLisandro Dalcin MPI_Comm comm = PetscObjectComm((PetscObject)part); 2104137cd93aSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 2105137cd93aSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 2106137cd93aSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 2107137cd93aSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 2108137cd93aSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 2109137cd93aSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 2110137cd93aSLisandro Dalcin PetscInt v, i, *assignment, *points; 2111137cd93aSLisandro Dalcin PetscMPIInt size, rank, p; 2112137cd93aSLisandro Dalcin PetscErrorCode ierr; 2113137cd93aSLisandro Dalcin 2114137cd93aSLisandro Dalcin PetscFunctionBegin; 2115137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2116137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 211799b53901SStefano Zampini ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 2118137cd93aSLisandro Dalcin 2119137cd93aSLisandro Dalcin /* Calculate vertex distribution */ 2120137cd93aSLisandro Dalcin vtxdist[0] = 0; 2121137cd93aSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2122137cd93aSLisandro Dalcin for (p = 2; p <= size; ++p) { 2123137cd93aSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 2124137cd93aSLisandro Dalcin } 2125137cd93aSLisandro Dalcin 2126137cd93aSLisandro Dalcin if (nparts == 1) { 2127137cd93aSLisandro Dalcin ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 2128*8ef05d33SStefano Zampini } else { /* Weight cells by dofs on cell by default */ 2129137cd93aSLisandro Dalcin PetscSection section; 2130*8ef05d33SStefano Zampini 2131137cd93aSLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 2132137cd93aSLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 2133*8ef05d33SStefano Zampini ierr = PetscMalloc1(PetscMax(nvtxs,1),&vwgt);CHKERRQ(ierr); 2134*8ef05d33SStefano Zampini for (v = 0; v < PetscMax(nvtxs,1); ++v) vwgt[v] = 1; 2135*8ef05d33SStefano Zampini ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 2136*8ef05d33SStefano Zampini if (section) { 2137*8ef05d33SStefano Zampini PetscInt vStart, vEnd, dof; 2138*8ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &vStart, &vEnd);CHKERRQ(ierr); 2139*8ef05d33SStefano Zampini for (v = vStart; v < vStart + numVertices; ++v) { 2140*8ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 2141*8ef05d33SStefano Zampini vwgt[v-vStart] = PetscMax(dof, 1); 2142137cd93aSLisandro Dalcin } 2143137cd93aSLisandro Dalcin } 2144137cd93aSLisandro Dalcin { 2145137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 2146137cd93aSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 2147137cd93aSLisandro Dalcin double imbal = (double)pts->imbalance; 2148137cd93aSLisandro Dalcin 2149137cd93aSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 2150137cd93aSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 2151137cd93aSLisandro Dalcin if (rank == p) { 2152137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, assignment);CHKERRQ(ierr); 2153137cd93aSLisandro Dalcin } 2154137cd93aSLisandro Dalcin } else { 2155137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, assignment, comm);CHKERRQ(ierr); 2156137cd93aSLisandro Dalcin } 2157137cd93aSLisandro Dalcin } 2158137cd93aSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 2159137cd93aSLisandro Dalcin } 2160137cd93aSLisandro Dalcin 2161137cd93aSLisandro Dalcin /* Convert to PetscSection+IS */ 2162137cd93aSLisandro Dalcin ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 2163137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 2164137cd93aSLisandro Dalcin ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 2165137cd93aSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 2166137cd93aSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 2167137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 2168137cd93aSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 2169137cd93aSLisandro Dalcin } 2170137cd93aSLisandro Dalcin } 2171137cd93aSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2172137cd93aSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2173137cd93aSLisandro Dalcin 2174137cd93aSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 2175137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2176137cd93aSLisandro Dalcin #else 2177137cd93aSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 2178137cd93aSLisandro Dalcin #endif 2179137cd93aSLisandro Dalcin } 2180137cd93aSLisandro Dalcin 2181137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 2182137cd93aSLisandro Dalcin { 2183137cd93aSLisandro Dalcin PetscFunctionBegin; 2184074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 2185137cd93aSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 2186137cd93aSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 2187137cd93aSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 2188137cd93aSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 2189137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2190137cd93aSLisandro Dalcin } 2191137cd93aSLisandro Dalcin 2192137cd93aSLisandro Dalcin /*MC 2193137cd93aSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 2194137cd93aSLisandro Dalcin 2195137cd93aSLisandro Dalcin Level: intermediate 2196137cd93aSLisandro Dalcin 2197137cd93aSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 2198137cd93aSLisandro Dalcin M*/ 2199137cd93aSLisandro Dalcin 2200137cd93aSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 2201137cd93aSLisandro Dalcin { 2202137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p; 2203137cd93aSLisandro Dalcin PetscErrorCode ierr; 2204137cd93aSLisandro Dalcin 2205137cd93aSLisandro Dalcin PetscFunctionBegin; 2206137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2207137cd93aSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 2208137cd93aSLisandro Dalcin part->data = p; 2209137cd93aSLisandro Dalcin 2210137cd93aSLisandro Dalcin p->strategy = 0; 2211137cd93aSLisandro Dalcin p->imbalance = 0.01; 2212137cd93aSLisandro Dalcin 2213137cd93aSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 2214137cd93aSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionercite);CHKERRQ(ierr); 2215137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2216137cd93aSLisandro Dalcin } 2217137cd93aSLisandro Dalcin 2218137cd93aSLisandro Dalcin 22195680f57bSMatthew G. Knepley /*@ 22205680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 22215680f57bSMatthew G. Knepley 22225680f57bSMatthew G. Knepley Not collective 22235680f57bSMatthew G. Knepley 22245680f57bSMatthew G. Knepley Input Parameter: 22255680f57bSMatthew G. Knepley . dm - The DM 22265680f57bSMatthew G. Knepley 22275680f57bSMatthew G. Knepley Output Parameter: 22285680f57bSMatthew G. Knepley . part - The PetscPartitioner 22295680f57bSMatthew G. Knepley 22305680f57bSMatthew G. Knepley Level: developer 22315680f57bSMatthew G. Knepley 223298599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 223398599a47SLawrence Mitchell 223498599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 22355680f57bSMatthew G. Knepley @*/ 22365680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 22375680f57bSMatthew G. Knepley { 22385680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 22395680f57bSMatthew G. Knepley 22405680f57bSMatthew G. Knepley PetscFunctionBegin; 22415680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22425680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 22435680f57bSMatthew G. Knepley *part = mesh->partitioner; 22445680f57bSMatthew G. Knepley PetscFunctionReturn(0); 22455680f57bSMatthew G. Knepley } 22465680f57bSMatthew G. Knepley 224771bb2955SLawrence Mitchell /*@ 224871bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 224971bb2955SLawrence Mitchell 225071bb2955SLawrence Mitchell logically collective on dm and part 225171bb2955SLawrence Mitchell 225271bb2955SLawrence Mitchell Input Parameters: 225371bb2955SLawrence Mitchell + dm - The DM 225471bb2955SLawrence Mitchell - part - The partitioner 225571bb2955SLawrence Mitchell 225671bb2955SLawrence Mitchell Level: developer 225771bb2955SLawrence Mitchell 225871bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 225971bb2955SLawrence Mitchell 226071bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 226171bb2955SLawrence Mitchell @*/ 226271bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 226371bb2955SLawrence Mitchell { 226471bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 226571bb2955SLawrence Mitchell PetscErrorCode ierr; 226671bb2955SLawrence Mitchell 226771bb2955SLawrence Mitchell PetscFunctionBegin; 226871bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 226971bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 227071bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 227171bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 227271bb2955SLawrence Mitchell mesh->partitioner = part; 227371bb2955SLawrence Mitchell PetscFunctionReturn(0); 227471bb2955SLawrence Mitchell } 227571bb2955SLawrence Mitchell 2276e8f14785SLisandro Dalcin static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 2277270bba0cSToby Isaac { 2278270bba0cSToby Isaac PetscErrorCode ierr; 2279270bba0cSToby Isaac 2280270bba0cSToby Isaac PetscFunctionBegin; 22816a5a2ffdSToby Isaac if (up) { 22826a5a2ffdSToby Isaac PetscInt parent; 22836a5a2ffdSToby Isaac 2284270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 22856a5a2ffdSToby Isaac if (parent != point) { 22866a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 22876a5a2ffdSToby Isaac 2288270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2289270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 2290270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 2291270bba0cSToby Isaac 2292e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 22931b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 2294270bba0cSToby Isaac } 2295270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 22966a5a2ffdSToby Isaac } 22976a5a2ffdSToby Isaac } 22986a5a2ffdSToby Isaac if (down) { 22996a5a2ffdSToby Isaac PetscInt numChildren; 23006a5a2ffdSToby Isaac const PetscInt *children; 23016a5a2ffdSToby Isaac 23026a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 23036a5a2ffdSToby Isaac if (numChildren) { 23046a5a2ffdSToby Isaac PetscInt i; 23056a5a2ffdSToby Isaac 23066a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 23076a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 23086a5a2ffdSToby Isaac 2309e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 23101b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 23116a5a2ffdSToby Isaac } 23126a5a2ffdSToby Isaac } 23136a5a2ffdSToby Isaac } 2314270bba0cSToby Isaac PetscFunctionReturn(0); 2315270bba0cSToby Isaac } 2316270bba0cSToby Isaac 2317825f8a23SLisandro Dalcin PETSC_INTERN PetscErrorCode DMPlexPartitionLabelClosure_Private(DM,DMLabel,PetscInt,PetscInt,const PetscInt[],IS*); 2318825f8a23SLisandro Dalcin 2319825f8a23SLisandro Dalcin PetscErrorCode DMPlexPartitionLabelClosure_Private(DM dm, DMLabel label, PetscInt rank, PetscInt numPoints, const PetscInt points[], IS *closureIS) 2320825f8a23SLisandro Dalcin { 2321825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 2322825f8a23SLisandro Dalcin PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 2323825f8a23SLisandro Dalcin PetscInt *closure = NULL, closureSize, nelems, *elems, off = 0, p, c; 2324825f8a23SLisandro Dalcin PetscHSetI ht; 2325825f8a23SLisandro Dalcin PetscErrorCode ierr; 2326825f8a23SLisandro Dalcin 2327825f8a23SLisandro Dalcin PetscFunctionBegin; 2328825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 2329825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 2330825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 2331825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2332825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 2333825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 2334825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 2335825f8a23SLisandro Dalcin } 2336825f8a23SLisandro Dalcin } 2337825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 2338825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 2339825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 2340825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 2341825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 2342825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 2343825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 2344825f8a23SLisandro Dalcin PetscFunctionReturn(0); 2345825f8a23SLisandro Dalcin } 2346825f8a23SLisandro Dalcin 23475abbe4feSMichael Lange /*@ 23485abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 23495abbe4feSMichael Lange 23505abbe4feSMichael Lange Input Parameters: 23515abbe4feSMichael Lange + dm - The DM 23525abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 23535abbe4feSMichael Lange 23545abbe4feSMichael Lange Level: developer 23555abbe4feSMichael Lange 23565abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 23575abbe4feSMichael Lange @*/ 23585abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 23599ffc88e4SToby Isaac { 2360825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 23615abbe4feSMichael Lange const PetscInt *ranks, *points; 2362825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 23639ffc88e4SToby Isaac PetscErrorCode ierr; 23649ffc88e4SToby Isaac 23659ffc88e4SToby Isaac PetscFunctionBegin; 23665abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 23675abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 23685abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 23695abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 23705abbe4feSMichael Lange const PetscInt rank = ranks[r]; 23715abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 23725abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 23735abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2374825f8a23SLisandro Dalcin ierr = DMPlexPartitionLabelClosure_Private(dm, label, rank, numPoints, points, &closureIS);CHKERRQ(ierr); 23755abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 23765abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2377825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 2378825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 23799ffc88e4SToby Isaac } 23805abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 23815abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 23829ffc88e4SToby Isaac PetscFunctionReturn(0); 23839ffc88e4SToby Isaac } 23849ffc88e4SToby Isaac 238524d039d7SMichael Lange /*@ 238624d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 238724d039d7SMichael Lange 238824d039d7SMichael Lange Input Parameters: 238924d039d7SMichael Lange + dm - The DM 239024d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 239124d039d7SMichael Lange 239224d039d7SMichael Lange Level: developer 239324d039d7SMichael Lange 239424d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 239524d039d7SMichael Lange @*/ 239624d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 239770034214SMatthew G. Knepley { 239824d039d7SMichael Lange IS rankIS, pointIS; 239924d039d7SMichael Lange const PetscInt *ranks, *points; 240024d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 240124d039d7SMichael Lange PetscInt *adj = NULL; 240270034214SMatthew G. Knepley PetscErrorCode ierr; 240370034214SMatthew G. Knepley 240470034214SMatthew G. Knepley PetscFunctionBegin; 240524d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 240624d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 240724d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 240824d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 240924d039d7SMichael Lange const PetscInt rank = ranks[r]; 241070034214SMatthew G. Knepley 241124d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 241224d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 241324d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 241470034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 241524d039d7SMichael Lange adjSize = PETSC_DETERMINE; 241624d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 241724d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 241870034214SMatthew G. Knepley } 241924d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 242024d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 242170034214SMatthew G. Knepley } 242224d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 242324d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 242424d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 242524d039d7SMichael Lange PetscFunctionReturn(0); 242670034214SMatthew G. Knepley } 242770034214SMatthew G. Knepley 2428be200f8dSMichael Lange /*@ 2429be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 2430be200f8dSMichael Lange 2431be200f8dSMichael Lange Input Parameters: 2432be200f8dSMichael Lange + dm - The DM 2433be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 2434be200f8dSMichael Lange 2435be200f8dSMichael Lange Level: developer 2436be200f8dSMichael Lange 2437be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 2438be200f8dSMichael Lange overlap points from non-neighbouring partitions. 2439be200f8dSMichael Lange 2440be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 2441be200f8dSMichael Lange @*/ 2442be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 2443be200f8dSMichael Lange { 2444be200f8dSMichael Lange MPI_Comm comm; 2445be200f8dSMichael Lange PetscMPIInt rank; 2446be200f8dSMichael Lange PetscSF sfPoint; 24475d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 2448be200f8dSMichael Lange IS rankIS, pointIS; 2449be200f8dSMichael Lange const PetscInt *ranks; 2450be200f8dSMichael Lange PetscInt numRanks, r; 2451be200f8dSMichael Lange PetscErrorCode ierr; 2452be200f8dSMichael Lange 2453be200f8dSMichael Lange PetscFunctionBegin; 2454be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2455be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2456be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 24575d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 24585d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 24595d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 24605d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 24615d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 24625d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 24635d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 24645d04f6ebSMichael Lange if (remoteRank == rank) continue; 24655d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 24665d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 24675d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 24685d04f6ebSMichael Lange } 24695d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 24705d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 24715d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 2472be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 2473be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 2474be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 2475be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 2476be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 2477be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 2478be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 2479be200f8dSMichael Lange if (remoteRank == rank) continue; 2480be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 2481be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 2482be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2483be200f8dSMichael Lange } 2484be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 2485be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 2486be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 2487be200f8dSMichael Lange PetscFunctionReturn(0); 2488be200f8dSMichael Lange } 2489be200f8dSMichael Lange 24901fd9873aSMichael Lange /*@ 24911fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 24921fd9873aSMichael Lange 24931fd9873aSMichael Lange Input Parameters: 24941fd9873aSMichael Lange + dm - The DM 24951fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 24961fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 24971fd9873aSMichael Lange 24981fd9873aSMichael Lange Output Parameter: 24991fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 25001fd9873aSMichael Lange 25011fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 25021fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 25031fd9873aSMichael Lange 25041fd9873aSMichael Lange Level: developer 25051fd9873aSMichael Lange 25061fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 25071fd9873aSMichael Lange @*/ 25081fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 25091fd9873aSMichael Lange { 25101fd9873aSMichael Lange MPI_Comm comm; 2511874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 2512874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 25131fd9873aSMichael Lange PetscSF sfPoint; 2514874ddda9SLisandro Dalcin PetscSection rootSection; 25151fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 25161fd9873aSMichael Lange const PetscSFNode *remote; 25171fd9873aSMichael Lange const PetscInt *local, *neighbors; 25181fd9873aSMichael Lange IS valueIS; 2519874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 25201fd9873aSMichael Lange PetscErrorCode ierr; 25211fd9873aSMichael Lange 25221fd9873aSMichael Lange PetscFunctionBegin; 25231fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 25241fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 25259852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 25261fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 25271fd9873aSMichael Lange 25281fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 25291fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 25309852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 25311fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 25321fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 25331fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 25341fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 25351fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 25361fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 25371fd9873aSMichael Lange } 25381fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 2539874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 2540874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 25411fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 25421fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 25431fd9873aSMichael Lange IS pointIS; 25441fd9873aSMichael Lange const PetscInt *points; 25451fd9873aSMichael Lange 25461fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 25471fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 25481fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 25491fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 25501fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 2551f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 2552f8987ae8SMichael Lange else {l = -1;} 25531fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 25541fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 25551fd9873aSMichael Lange } 25561fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 25571fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 25581fd9873aSMichael Lange } 2559874ddda9SLisandro Dalcin 2560874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 2561874ddda9SLisandro Dalcin if (!processSF) { 2562874ddda9SLisandro Dalcin PetscInt64 counter = 0; 2563874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 2564874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 2565874ddda9SLisandro Dalcin 2566874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 2567874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 2568874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 2569874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 2570874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 2571874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2572874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2573874ddda9SLisandro Dalcin #endif 2574874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 2575874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 2576874ddda9SLisandro Dalcin } 2577874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 2578874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 2579874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 2580874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 2581874ddda9SLisandro Dalcin if (!mpiOverflow) { 2582874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 2583874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 2584874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 2585874ddda9SLisandro Dalcin } 2586874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 2587874ddda9SLisandro Dalcin } 2588874ddda9SLisandro Dalcin 2589874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 2590874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 2591874ddda9SLisandro Dalcin PetscSF procSF; 2592874ddda9SLisandro Dalcin PetscSFNode *remote; 2593874ddda9SLisandro Dalcin PetscSection leafSection; 2594874ddda9SLisandro Dalcin 2595874ddda9SLisandro Dalcin if (processSF) { 2596874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 2597874ddda9SLisandro Dalcin procSF = processSF; 2598874ddda9SLisandro Dalcin } else { 2599874ddda9SLisandro Dalcin ierr = PetscMalloc1(size, &remote);CHKERRQ(ierr); 2600874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { remote[r].rank = r; remote[r].index = rank; } 2601874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm, &procSF);CHKERRQ(ierr); 2602874ddda9SLisandro Dalcin ierr = PetscSFSetGraph(procSF, size, size, NULL, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 2603874ddda9SLisandro Dalcin } 2604874ddda9SLisandro Dalcin 2605874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 26061fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 2607874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 2608874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 2609874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 2610874ddda9SLisandro Dalcin } 2611874ddda9SLisandro Dalcin 2612874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 26131fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 26141fd9873aSMichael Lange } 2615874ddda9SLisandro Dalcin 2616874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 2617874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 26181fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 2619874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 26201fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 26211fd9873aSMichael Lange PetscFunctionReturn(0); 26221fd9873aSMichael Lange } 26231fd9873aSMichael Lange 2624aa3148a8SMichael Lange /*@ 2625aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 2626aa3148a8SMichael Lange 2627aa3148a8SMichael Lange Input Parameters: 2628aa3148a8SMichael Lange + dm - The DM 2629aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 2630aa3148a8SMichael Lange 2631aa3148a8SMichael Lange Output Parameter: 2632aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 2633aa3148a8SMichael Lange 2634aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 2635aa3148a8SMichael Lange 2636aa3148a8SMichael Lange Level: developer 2637aa3148a8SMichael Lange 2638aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 2639aa3148a8SMichael Lange @*/ 2640aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 2641aa3148a8SMichael Lange { 26429852e123SBarry Smith PetscMPIInt rank, size; 264343f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 2644aa3148a8SMichael Lange PetscSFNode *remotePoints; 264543f7d02bSMichael Lange IS remoteRootIS; 264643f7d02bSMichael Lange const PetscInt *remoteRoots; 2647aa3148a8SMichael Lange PetscErrorCode ierr; 2648aa3148a8SMichael Lange 2649aa3148a8SMichael Lange PetscFunctionBegin; 265043f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 26519852e123SBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr); 2652aa3148a8SMichael Lange 26539852e123SBarry Smith for (numRemote = 0, n = 0; n < size; ++n) { 2654aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 2655aa3148a8SMichael Lange numRemote += numPoints; 2656aa3148a8SMichael Lange } 2657aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 265843f7d02bSMichael Lange /* Put owned points first */ 265943f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 266043f7d02bSMichael Lange if (numPoints > 0) { 266143f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 266243f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 266343f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 266443f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 266543f7d02bSMichael Lange remotePoints[idx].rank = rank; 266643f7d02bSMichael Lange idx++; 266743f7d02bSMichael Lange } 266843f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 266943f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 267043f7d02bSMichael Lange } 267143f7d02bSMichael Lange /* Now add remote points */ 26729852e123SBarry Smith for (n = 0; n < size; ++n) { 2673aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 267443f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 2675aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 2676aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2677aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 2678aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 2679aa3148a8SMichael Lange remotePoints[idx].rank = n; 2680aa3148a8SMichael Lange idx++; 2681aa3148a8SMichael Lange } 2682aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2683aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 2684aa3148a8SMichael Lange } 2685aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 2686aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2687aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 268870034214SMatthew G. Knepley PetscFunctionReturn(0); 268970034214SMatthew G. Knepley } 2690cb87ef4cSFlorian Wechsung 26916a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 26926a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 26936a3739e5SFlorian Wechsung * them out in that case. */ 26946a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 26957a82c785SFlorian Wechsung /*@C 26967f57c1a4SFlorian Wechsung 26977f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 26987f57c1a4SFlorian Wechsung 26997f57c1a4SFlorian Wechsung Input parameters: 27007f57c1a4SFlorian Wechsung + dm - The DMPlex object. 27017f57c1a4SFlorian Wechsung + n - The number of points. 27027f57c1a4SFlorian Wechsung + pointsToRewrite - The points in the SF whose ownership will change. 27037f57c1a4SFlorian Wechsung + targetOwners - New owner for each element in pointsToRewrite. 27047f57c1a4SFlorian Wechsung + degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 27057f57c1a4SFlorian Wechsung 27067f57c1a4SFlorian Wechsung Level: developer 27077f57c1a4SFlorian Wechsung 27087f57c1a4SFlorian Wechsung @*/ 27097f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 27107f57c1a4SFlorian Wechsung { 27117f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 27127f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 27137f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 27147f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 27157f57c1a4SFlorian Wechsung const PetscInt *ilocal; 27167f57c1a4SFlorian Wechsung PetscBool *isLeaf; 27177f57c1a4SFlorian Wechsung PetscSF sf; 27187f57c1a4SFlorian Wechsung MPI_Comm comm; 27195a30b08bSFlorian Wechsung PetscMPIInt rank, size; 27207f57c1a4SFlorian Wechsung 27217f57c1a4SFlorian Wechsung PetscFunctionBegin; 27227f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 27237f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 27247f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 27257f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 27267f57c1a4SFlorian Wechsung 27277f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 27287f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 27297f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 27307f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27317f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 27327f57c1a4SFlorian Wechsung } 27337f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 27347f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 27357f57c1a4SFlorian Wechsung } 27367f57c1a4SFlorian Wechsung 27377f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 27387f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 27397f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 27407f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 27417f57c1a4SFlorian Wechsung } 27427f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 27437f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 27447f57c1a4SFlorian Wechsung 27457f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 27467f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 27477f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27487f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 27497f57c1a4SFlorian Wechsung } 27507f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 27517f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 27527f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 27537f57c1a4SFlorian Wechsung 27547f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 27557f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 27567f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 27577f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27587f57c1a4SFlorian Wechsung points[i] = pStart+i; 27597f57c1a4SFlorian Wechsung } 27607f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 27617f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 27627f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 27637f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 27647f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 27657f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 27667f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27677f57c1a4SFlorian Wechsung newOwners[i] = -1; 27687f57c1a4SFlorian Wechsung newNumbers[i] = -1; 27697f57c1a4SFlorian Wechsung } 27707f57c1a4SFlorian Wechsung { 27717f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 27727f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 27737f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 27747f57c1a4SFlorian Wechsung newNumber = -1; 27757f57c1a4SFlorian Wechsung oldOwner = rank; 27767f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 27777f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 27787f57c1a4SFlorian Wechsung newNumber = oldNumber; 27797f57c1a4SFlorian Wechsung } else { 27807f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 27817f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 27827f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 27837f57c1a4SFlorian Wechsung break; 27847f57c1a4SFlorian Wechsung } 27857f57c1a4SFlorian Wechsung } 27867f57c1a4SFlorian Wechsung } 27877f57c1a4SFlorian Wechsung if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 27887f57c1a4SFlorian Wechsung 27897f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 27907f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 27917f57c1a4SFlorian Wechsung } 27927f57c1a4SFlorian Wechsung } 27937f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 27947f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 27957f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 27967f57c1a4SFlorian Wechsung 27977f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 27987f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 27997f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 28007f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 28017f57c1a4SFlorian Wechsung 28027f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 28037f57c1a4SFlorian Wechsung leafCounter=0; 28047f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28057f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 28067f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 28077f57c1a4SFlorian Wechsung leafCounter++; 28087f57c1a4SFlorian Wechsung } 28097f57c1a4SFlorian Wechsung } else { 28107f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28117f57c1a4SFlorian Wechsung leafCounter++; 28127f57c1a4SFlorian Wechsung } 28137f57c1a4SFlorian Wechsung } 28147f57c1a4SFlorian Wechsung } 28157f57c1a4SFlorian Wechsung 28167f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 28177f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 28187f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 28197f57c1a4SFlorian Wechsung 28207f57c1a4SFlorian Wechsung leafCounter = 0; 28217f57c1a4SFlorian Wechsung counter = 0; 28227f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28237f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 28247f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 28257f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 28267f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 28277f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 28287f57c1a4SFlorian Wechsung leafCounter++; 28297f57c1a4SFlorian Wechsung } 28307f57c1a4SFlorian Wechsung } else { 28317f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28327f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 28337f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 28347f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 28357f57c1a4SFlorian Wechsung leafCounter++; 28367f57c1a4SFlorian Wechsung } 28377f57c1a4SFlorian Wechsung } 28387f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28397f57c1a4SFlorian Wechsung counter++; 28407f57c1a4SFlorian Wechsung } 28417f57c1a4SFlorian Wechsung } 28427f57c1a4SFlorian Wechsung 28437f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 28447f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 28457f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 28467f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 28477f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 28487f57c1a4SFlorian Wechsung } 28497f57c1a4SFlorian Wechsung 2850125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 2851125d2a8fSFlorian Wechsung { 28525a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 28535a30b08bSFlorian Wechsung PetscMPIInt rank, size; 2854125d2a8fSFlorian Wechsung PetscFunctionBegin; 2855125d2a8fSFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2856125d2a8fSFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2857125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 2858125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 2859125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 2860125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 2861125d2a8fSFlorian Wechsung } 2862125d2a8fSFlorian Wechsung ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 2863125d2a8fSFlorian Wechsung min = distribution[0]; 2864125d2a8fSFlorian Wechsung max = distribution[0]; 2865125d2a8fSFlorian Wechsung sum = distribution[0]; 2866125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 2867125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 2868125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 2869125d2a8fSFlorian Wechsung sum += distribution[i]; 2870125d2a8fSFlorian Wechsung } 2871125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 2872125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 2873125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 2874125d2a8fSFlorian Wechsung } 2875125d2a8fSFlorian Wechsung 28766a3739e5SFlorian Wechsung #endif 28776a3739e5SFlorian Wechsung 2878cb87ef4cSFlorian Wechsung /*@ 28795dc86ac1SFlorian Wechsung DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace. 2880cb87ef4cSFlorian Wechsung 2881cb87ef4cSFlorian Wechsung Input parameters: 2882ed44d270SFlorian Wechsung + dm - The DMPlex object. 28837f57c1a4SFlorian Wechsung + entityDepth - depth of the entity to balance (0 -> balance vertices). 28847f57c1a4SFlorian Wechsung + useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 28857f57c1a4SFlorian Wechsung + parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 2886cb87ef4cSFlorian Wechsung 28878b879b41SFlorian Wechsung Output parameters: 28888b879b41SFlorian Wechsung + success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 28898b879b41SFlorian Wechsung 2890cb87ef4cSFlorian Wechsung Level: user 2891cb87ef4cSFlorian Wechsung 2892cb87ef4cSFlorian Wechsung @*/ 2893cb87ef4cSFlorian Wechsung 28948b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 2895cb87ef4cSFlorian Wechsung { 289641525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 2897cb87ef4cSFlorian Wechsung PetscSF sf; 28980faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 28997f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 29007f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 29017f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 2902cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 2903cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 2904cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 29057f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 29065dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 2907cb87ef4cSFlorian Wechsung PetscInt offset, counter; 29087f57c1a4SFlorian Wechsung PetscInt lenadjncy; 2909cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 2910cb87ef4cSFlorian Wechsung PetscInt lenxadj; 2911cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 2912cb87ef4cSFlorian Wechsung PetscInt *part, *options; 2913cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 2914cb87ef4cSFlorian Wechsung real_t *ubvec; 2915cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 2916cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 2917cb87ef4cSFlorian Wechsung MPI_Comm comm; 29184baf1206SFlorian Wechsung Mat A, Apre; 291912617df9SFlorian Wechsung const char *prefix = NULL; 29207d197802SFlorian Wechsung PetscViewer viewer; 29217d197802SFlorian Wechsung PetscViewerFormat format; 29225a30b08bSFlorian Wechsung PetscLayout layout; 292312617df9SFlorian Wechsung 292412617df9SFlorian Wechsung PetscFunctionBegin; 29258b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 29267f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 29277f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 29287f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 29297f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 29307f57c1a4SFlorian Wechsung 293141525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 293241525646SFlorian Wechsung 29335a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 29345dc86ac1SFlorian Wechsung if (viewer) { 29355a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 29367d197802SFlorian Wechsung } 29377d197802SFlorian Wechsung 2938ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 2939d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 2940cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2941cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 2942cf818975SFlorian Wechsung 2943cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 29445a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 2945cb87ef4cSFlorian Wechsung } 2946cb87ef4cSFlorian Wechsung 2947cf818975SFlorian Wechsung /* There are three types of points: 2948cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 2949cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 2950cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 2951cf818975SFlorian Wechsung */ 2952cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 2953cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 2954cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 2955cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 2956cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 2957cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2958cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 2959cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 2960cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 2961cb87ef4cSFlorian Wechsung } 2962cf818975SFlorian Wechsung 2963cf818975SFlorian Wechsung /* start by marking all the leafs */ 2964cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 2965cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 2966cb87ef4cSFlorian Wechsung } 2967cb87ef4cSFlorian Wechsung 2968cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 2969cf818975SFlorian Wechsung * not by calculating its degree */ 29707f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 29717f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 2972cf818975SFlorian Wechsung 2973cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 2974cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 2975cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2976cb87ef4cSFlorian Wechsung if (toBalance[i]) { 29777f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 2978cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 2979cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 2980cb87ef4cSFlorian Wechsung } else { 2981cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 2982cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 2983cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 2984cb87ef4cSFlorian Wechsung } 2985cb87ef4cSFlorian Wechsung } 2986cb87ef4cSFlorian Wechsung } 2987cb87ef4cSFlorian Wechsung } 2988cb87ef4cSFlorian Wechsung 2989cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 2990cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 2991cf818975SFlorian Wechsung * point. */ 2992cb87ef4cSFlorian Wechsung 29935dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 29945dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 29955dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 29965dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 29975dc86ac1SFlorian Wechsung 2998cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 2999cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 3000cb87ef4cSFlorian Wechsung counter = 0; 3001cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3002cb87ef4cSFlorian Wechsung if (toBalance[i]) { 30037f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 3004cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 3005cb87ef4cSFlorian Wechsung counter++; 3006cb87ef4cSFlorian Wechsung } 3007cb87ef4cSFlorian Wechsung } 3008cb87ef4cSFlorian Wechsung } 3009cb87ef4cSFlorian Wechsung 3010cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 3011cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 3012cb87ef4cSFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3013cb87ef4cSFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3014cb87ef4cSFlorian Wechsung 30150faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 3016cb87ef4cSFlorian Wechsung 30174baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 30184baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 30194baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 30204baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 30218c9a1619SFlorian Wechsung 30228c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 30238c9a1619SFlorian Wechsung if (toBalance[i]) { 30240faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 30250faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 30260faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 30270faf6628SFlorian Wechsung else continue; 30280faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 30290faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 30304baf1206SFlorian Wechsung } 30314baf1206SFlorian Wechsung } 30324baf1206SFlorian Wechsung 30334baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30344baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30354baf1206SFlorian Wechsung 30364baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 30374baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 30384baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 30394baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 30404baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 30414baf1206SFlorian Wechsung 30424baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 30434baf1206SFlorian Wechsung if (toBalance[i]) { 30440faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 30450faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 30460faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 30470faf6628SFlorian Wechsung else continue; 30480faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 30490faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 30500941debbSFlorian Wechsung } 30510941debbSFlorian Wechsung } 30528c9a1619SFlorian Wechsung 30538c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30548c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30554baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 30564baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 30574baf1206SFlorian Wechsung 305841525646SFlorian Wechsung nparts = size; 305941525646SFlorian Wechsung wgtflag = 2; 306041525646SFlorian Wechsung numflag = 0; 306141525646SFlorian Wechsung ncon = 2; 306241525646SFlorian Wechsung real_t *tpwgts; 306341525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 306441525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 306541525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 306641525646SFlorian Wechsung } 306741525646SFlorian Wechsung 306841525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 306941525646SFlorian Wechsung ubvec[0] = 1.01; 30705a30b08bSFlorian Wechsung ubvec[1] = 1.01; 30718c9a1619SFlorian Wechsung lenadjncy = 0; 30728c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 30738c9a1619SFlorian Wechsung PetscInt temp=0; 30748c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 30758c9a1619SFlorian Wechsung lenadjncy += temp; 30768c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 30778c9a1619SFlorian Wechsung } 30788c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 30797407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 30800941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 30810941debbSFlorian Wechsung xadj[0] = 0; 30828c9a1619SFlorian Wechsung counter = 0; 30838c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 30842953a68cSFlorian Wechsung PetscInt temp=0; 30852953a68cSFlorian Wechsung const PetscInt *cols; 30868c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 3087694ea26eSFlorian Wechsung ierr = PetscMemcpy(&adjncy[counter], cols, temp*sizeof(PetscInt));CHKERRQ(ierr); 30888c9a1619SFlorian Wechsung counter += temp; 30890941debbSFlorian Wechsung xadj[i+1] = counter; 30908c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 30918c9a1619SFlorian Wechsung } 30928c9a1619SFlorian Wechsung 3093cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 309441525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 309541525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 309641525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 309741525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 309841525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 309941525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 310041525646SFlorian Wechsung } 31018c9a1619SFlorian Wechsung 31025dc86ac1SFlorian Wechsung if (viewer) { 31037d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 31047d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 310512617df9SFlorian Wechsung } 310641525646SFlorian Wechsung if (parallel) { 31075a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 31085a30b08bSFlorian Wechsung options[0] = 1; 31095a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 31105a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 31115a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 31125dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 31138c9a1619SFlorian Wechsung if (useInitialGuess) { 31145dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 31158c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 31165dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 311706b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 31188c9a1619SFlorian Wechsung PetscStackPop; 31198c9a1619SFlorian Wechsung } else { 31208c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 31215dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 31228c9a1619SFlorian Wechsung PetscStackPop; 312306b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 31248c9a1619SFlorian Wechsung } 3125ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 312641525646SFlorian Wechsung } else { 31275dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 312841525646SFlorian Wechsung Mat As; 312941525646SFlorian Wechsung PetscInt numRows; 313041525646SFlorian Wechsung PetscInt *partGlobal; 313141525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 3132cb87ef4cSFlorian Wechsung 313341525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 313441525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 313541525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 31362953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRQ(ierr); 3137cb87ef4cSFlorian Wechsung 313841525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 313941525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 31405dc86ac1SFlorian Wechsung if (!rank) { 314141525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 314241525646SFlorian Wechsung lenadjncy = 0; 314341525646SFlorian Wechsung 314441525646SFlorian Wechsung for (i=0; i<numRows; i++) { 314541525646SFlorian Wechsung PetscInt temp=0; 314641525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 314741525646SFlorian Wechsung lenadjncy += temp; 314841525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 314941525646SFlorian Wechsung } 315041525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 315141525646SFlorian Wechsung lenxadj = 1 + numRows; 315241525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 315341525646SFlorian Wechsung xadj_g[0] = 0; 315441525646SFlorian Wechsung counter = 0; 315541525646SFlorian Wechsung for (i=0; i<numRows; i++) { 31562953a68cSFlorian Wechsung PetscInt temp=0; 31572953a68cSFlorian Wechsung const PetscInt *cols; 315841525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 3159694ea26eSFlorian Wechsung ierr = PetscMemcpy(&adjncy_g[counter], cols, temp*sizeof(PetscInt));CHKERRQ(ierr); 316041525646SFlorian Wechsung counter += temp; 316141525646SFlorian Wechsung xadj_g[i+1] = counter; 316241525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 316341525646SFlorian Wechsung } 316441525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 316541525646SFlorian Wechsung for (i=0; i<size; i++){ 316641525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 316741525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 316841525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 316941525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 317041525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 317141525646SFlorian Wechsung } 317241525646SFlorian Wechsung } 317341525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 317441525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 317506b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 317641525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 317741525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 317806b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 317941525646SFlorian Wechsung PetscStackPop; 318006b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 3181ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 318241525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 318341525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 318441525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 318541525646SFlorian Wechsung } 318641525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 318741525646SFlorian Wechsung 31885dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 31895dc86ac1SFlorian Wechsung { 319081a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 31915dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 319281a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 31935dc86ac1SFlorian Wechsung for(i=0; i<size; i++) { 319481a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 319541525646SFlorian Wechsung } 319681a13b52SFlorian Wechsung for(i=0; i<=size; i++) { 319781a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 319881a13b52SFlorian Wechsung } 319981a13b52SFlorian Wechsung ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRQ(ierr); 32005dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 320181a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 32025dc86ac1SFlorian Wechsung } 32035dc86ac1SFlorian Wechsung 320441525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 32052953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 320641525646SFlorian Wechsung } 3207cb87ef4cSFlorian Wechsung 32082953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 3209cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 3210cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 3211cb87ef4cSFlorian Wechsung 3212cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 3213cb87ef4cSFlorian Wechsung 3214cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 3215cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 3216cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 32172953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRQ(ierr); 3218cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 3219cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 3220cb87ef4cSFlorian Wechsung } 3221cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 3222cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 3223cb87ef4cSFlorian Wechsung } 3224cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 3225cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 32262953a68cSFlorian Wechsung ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 3227cb87ef4cSFlorian Wechsung 32287f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 32297f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 32307f57c1a4SFlorian Wechsung 3231cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 32327f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 32337f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 32347f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 32357f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 32367f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 32377f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 32387f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 32397f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 32407f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 32417f57c1a4SFlorian Wechsung if (viewer) { 324206b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 324306b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 32447f57c1a4SFlorian Wechsung } 32457f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 32468b879b41SFlorian Wechsung PetscFunctionReturn(0); 3247cb87ef4cSFlorian Wechsung } 3248cb87ef4cSFlorian Wechsung 32497407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 32505dc86ac1SFlorian Wechsung if (viewer) { 32517d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth);CHKERRQ(ierr); 3252125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 3253125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 3254125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 3255125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 32567407ba93SFlorian Wechsung } 32577407ba93SFlorian Wechsung 3258cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 325941525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 3260cb87ef4cSFlorian Wechsung PetscInt loc = 0; 326141525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 32627407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 3263cb87ef4cSFlorian Wechsung if (loc<0) { 326441525646SFlorian Wechsung part[i] = rank; 3265cb87ef4cSFlorian Wechsung } 3266cb87ef4cSFlorian Wechsung } 3267cb87ef4cSFlorian Wechsung 32687407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 32695dc86ac1SFlorian Wechsung if (viewer) { 3270125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 3271125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 32727407ba93SFlorian Wechsung } 32737407ba93SFlorian Wechsung 32745dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3275cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 3276cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 327741525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 3278cb87ef4cSFlorian Wechsung 32797f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 3280cf818975SFlorian Wechsung { 32817f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 328206b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 32837f57c1a4SFlorian Wechsung counter = 0; 3284cb87ef4cSFlorian Wechsung for(i=0; i<pEnd-pStart; i++) { 3285cb87ef4cSFlorian Wechsung if (toBalance[i]) { 3286cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 32877f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 3288cb87ef4cSFlorian Wechsung counter++; 3289cb87ef4cSFlorian Wechsung } 3290cb87ef4cSFlorian Wechsung } 3291cb87ef4cSFlorian Wechsung } 32927f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 32937f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 3294cf818975SFlorian Wechsung } 3295cb87ef4cSFlorian Wechsung 3296cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 3297cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 3298cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 3299cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 33007f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 33015dc86ac1SFlorian Wechsung if (viewer) { 330206b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 330306b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 33047d197802SFlorian Wechsung } 33058b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 330641525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 3307240408d3SFlorian Wechsung #else 33085f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 330941525646SFlorian Wechsung #endif 3310cb87ef4cSFlorian Wechsung PetscFunctionReturn(0); 3311cb87ef4cSFlorian Wechsung } 3312