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 PetscInt *rows, *cols, *ii, *jj; 242bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 243bbbc8e51SStefano Zampini PetscInt dim, depth, floc, cloc, i, M, N, c, m, cStart, cEnd, fStart, fEnd; 244bbbc8e51SStefano Zampini PetscMPIInt rank; 245bbbc8e51SStefano Zampini PetscBool flg; 246bbbc8e51SStefano Zampini PetscErrorCode ierr; 247bbbc8e51SStefano Zampini 248bbbc8e51SStefano Zampini PetscFunctionBegin; 249bbbc8e51SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 250bbbc8e51SStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 251bbbc8e51SStefano Zampini ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 252bbbc8e51SStefano Zampini if (dim != depth) { 253bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 254bbbc8e51SStefano Zampini ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 255bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 256bbbc8e51SStefano Zampini if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 257bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 258bbbc8e51SStefano Zampini if (!*numVertices) { 259bbbc8e51SStefano Zampini ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 260bbbc8e51SStefano Zampini (*offsets)[0] = 0; 261bbbc8e51SStefano Zampini } 262bbbc8e51SStefano Zampini /* Broken in parallel */ 263bbbc8e51SStefano Zampini if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 264bbbc8e51SStefano Zampini PetscFunctionReturn(0); 265bbbc8e51SStefano Zampini } 266bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 267bbbc8e51SStefano Zampini 268bbbc8e51SStefano Zampini /* numbering */ 269bbbc8e51SStefano Zampini ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 270bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr); 271bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 272bbbc8e51SStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr); 273bbbc8e51SStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr); 274bbbc8e51SStefano Zampini if (globalNumbering) { 275bbbc8e51SStefano Zampini ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr); 276bbbc8e51SStefano Zampini } 277bbbc8e51SStefano Zampini 278bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 279bbbc8e51SStefano Zampini ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr); 280bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 281bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 282bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 283bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 284bbbc8e51SStefano Zampini 285bbbc8e51SStefano Zampini if (p < 0) { 286bbbc8e51SStefano Zampini idxs[i] = -(p+1); 287bbbc8e51SStefano Zampini } else { 288bbbc8e51SStefano Zampini idxs[i] = p; 289bbbc8e51SStefano Zampini floc += 1; 290bbbc8e51SStefano Zampini } 291bbbc8e51SStefano Zampini } 292bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 293bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 294bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 295bbbc8e51SStefano Zampini 296bbbc8e51SStefano Zampini ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr); 297bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 298bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 299bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr); 300bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 301bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 302bbbc8e51SStefano Zampini 303bbbc8e51SStefano Zampini if (p < 0) { 304bbbc8e51SStefano Zampini idxs[i] = -(p+1); 305bbbc8e51SStefano Zampini } else { 306bbbc8e51SStefano Zampini idxs[i] = p; 307bbbc8e51SStefano Zampini idxs2[cloc++] = p; 308bbbc8e51SStefano Zampini } 309bbbc8e51SStefano Zampini } 310bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 311bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 312bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 313bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr); 314bbbc8e51SStefano Zampini 315bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 316bbbc8e51SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr); 317bbbc8e51SStefano Zampini ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr); 318bbbc8e51SStefano Zampini ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr); 319bbbc8e51SStefano Zampini ierr = DMPlexGetMaxSizes(dm, NULL, &m);CHKERRQ(ierr); 320bbbc8e51SStefano Zampini ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr); 321bbbc8e51SStefano Zampini 322bbbc8e51SStefano Zampini /* Assemble matrix */ 323bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 324bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 325bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 326bbbc8e51SStefano Zampini const PetscInt *cone; 327bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 328bbbc8e51SStefano Zampini 329bbbc8e51SStefano Zampini col = cols[c-cStart]; 330bbbc8e51SStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 331bbbc8e51SStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 332bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 333bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 334bbbc8e51SStefano Zampini const PetscInt *children; 335bbbc8e51SStefano Zampini PetscInt numChildren, ch; 336bbbc8e51SStefano Zampini 337bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 338bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 339bbbc8e51SStefano Zampini 340bbbc8e51SStefano Zampini /* non-conforming meshes */ 341bbbc8e51SStefano Zampini ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr); 342bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 343bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 344bbbc8e51SStefano Zampini 345bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 346bbbc8e51SStefano Zampini row = rows[child-fStart]; 347bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 348bbbc8e51SStefano Zampini } 349bbbc8e51SStefano Zampini } 350bbbc8e51SStefano Zampini } 351bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 352bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 353bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 354bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 355bbbc8e51SStefano Zampini ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 356bbbc8e51SStefano Zampini ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 357bbbc8e51SStefano Zampini 358bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 359bbbc8e51SStefano Zampini ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr); 360bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 361bbbc8e51SStefano Zampini 362bbbc8e51SStefano Zampini /* extract local part of the CSR */ 363bbbc8e51SStefano Zampini ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr); 364bbbc8e51SStefano Zampini ierr = MatDestroy(&CSR);CHKERRQ(ierr); 365bbbc8e51SStefano Zampini ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 366bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 367bbbc8e51SStefano Zampini 368bbbc8e51SStefano Zampini /* get back requested output */ 369bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 370bbbc8e51SStefano Zampini if (offsets) { 371bbbc8e51SStefano Zampini ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr); 372bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 373bbbc8e51SStefano Zampini *offsets = idxs; 374bbbc8e51SStefano Zampini } 375bbbc8e51SStefano Zampini if (adjacency) { 376bbbc8e51SStefano Zampini ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr); 377bbbc8e51SStefano Zampini ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr); 378bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 379bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 380bbbc8e51SStefano Zampini 381bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 382bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 383bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 384bbbc8e51SStefano Zampini } 385bbbc8e51SStefano Zampini } 386bbbc8e51SStefano Zampini if (c != ii[m] - m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 387bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr); 388bbbc8e51SStefano Zampini *adjacency = idxs; 389bbbc8e51SStefano Zampini } 390bbbc8e51SStefano Zampini 391bbbc8e51SStefano Zampini /* cleanup */ 392bbbc8e51SStefano Zampini ierr = ISDestroy(&cis_own);CHKERRQ(ierr); 393bbbc8e51SStefano Zampini ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 394bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 395bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 396bbbc8e51SStefano Zampini PetscFunctionReturn(0); 397bbbc8e51SStefano Zampini } 398bbbc8e51SStefano Zampini 399bbbc8e51SStefano Zampini /*@C 400bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 401bbbc8e51SStefano Zampini 402bbbc8e51SStefano Zampini Input Parameters: 403bbbc8e51SStefano Zampini + dm - The mesh DM dm 404bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 405bbbc8e51SStefano Zampini 406bbbc8e51SStefano Zampini Output Parameter: 407bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 408bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 409bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 410bbbc8e51SStefano 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. 411bbbc8e51SStefano Zampini 412bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 413bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 414bbbc8e51SStefano Zampini 415bbbc8e51SStefano Zampini Level: developer 416bbbc8e51SStefano Zampini 417bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 418bbbc8e51SStefano Zampini @*/ 419bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 420bbbc8e51SStefano Zampini { 421bbbc8e51SStefano Zampini PetscErrorCode ierr; 422bbbc8e51SStefano Zampini PetscBool usemat = PETSC_FALSE; 423bbbc8e51SStefano Zampini 424bbbc8e51SStefano Zampini PetscFunctionBegin; 425bbbc8e51SStefano Zampini ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_via_mat", &usemat, NULL);CHKERRQ(ierr); 426bbbc8e51SStefano Zampini if (usemat) { 427bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 428bbbc8e51SStefano Zampini } else { 429bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 430bbbc8e51SStefano Zampini } 431bbbc8e51SStefano Zampini PetscFunctionReturn(0); 432bbbc8e51SStefano Zampini } 433bbbc8e51SStefano Zampini 434d5577e40SMatthew G. Knepley /*@C 435d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 436d5577e40SMatthew G. Knepley 437d5577e40SMatthew G. Knepley Collective 438d5577e40SMatthew G. Knepley 439d5577e40SMatthew G. Knepley Input Arguments: 440d5577e40SMatthew G. Knepley + dm - The DMPlex 441d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 442d5577e40SMatthew G. Knepley 443d5577e40SMatthew G. Knepley Output Arguments: 444d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 445d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 446d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 447d5577e40SMatthew G. Knepley 448d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 449d5577e40SMatthew G. Knepley 450d5577e40SMatthew G. Knepley Level: advanced 451d5577e40SMatthew G. Knepley 452d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 453d5577e40SMatthew G. Knepley @*/ 45470034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 45570034214SMatthew G. Knepley { 45670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 45770034214SMatthew G. Knepley PetscInt numFaceCases = 0; 45870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 45970034214SMatthew G. Knepley PetscInt *off, *adj; 46070034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 46170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 46270034214SMatthew G. Knepley PetscErrorCode ierr; 46370034214SMatthew G. Knepley 46470034214SMatthew G. Knepley PetscFunctionBegin; 46570034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 466c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 46770034214SMatthew G. Knepley cellDim = dim - cellHeight; 46870034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 46970034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 47070034214SMatthew G. Knepley if (cEnd - cStart == 0) { 47170034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 47270034214SMatthew G. Knepley if (offsets) *offsets = NULL; 47370034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 47470034214SMatthew G. Knepley PetscFunctionReturn(0); 47570034214SMatthew G. Knepley } 47670034214SMatthew G. Knepley numCells = cEnd - cStart; 47770034214SMatthew G. Knepley faceDepth = depth - cellHeight; 47870034214SMatthew G. Knepley if (dim == depth) { 47970034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 48070034214SMatthew G. Knepley 48170034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 48270034214SMatthew G. Knepley /* Count neighboring cells */ 48370034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 48470034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 48570034214SMatthew G. Knepley const PetscInt *support; 48670034214SMatthew G. Knepley PetscInt supportSize; 48770034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 48870034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 48970034214SMatthew G. Knepley if (supportSize == 2) { 4909ffc88e4SToby Isaac PetscInt numChildren; 4919ffc88e4SToby Isaac 4929ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 4939ffc88e4SToby Isaac if (!numChildren) { 49470034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 49570034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 49670034214SMatthew G. Knepley } 49770034214SMatthew G. Knepley } 4989ffc88e4SToby Isaac } 49970034214SMatthew G. Knepley /* Prefix sum */ 50070034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 50170034214SMatthew G. Knepley if (adjacency) { 50270034214SMatthew G. Knepley PetscInt *tmp; 50370034214SMatthew G. Knepley 50470034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 505854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 50670034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 50770034214SMatthew G. Knepley /* Get neighboring cells */ 50870034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 50970034214SMatthew G. Knepley const PetscInt *support; 51070034214SMatthew G. Knepley PetscInt supportSize; 51170034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 51270034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 51370034214SMatthew G. Knepley if (supportSize == 2) { 5149ffc88e4SToby Isaac PetscInt numChildren; 5159ffc88e4SToby Isaac 5169ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5179ffc88e4SToby Isaac if (!numChildren) { 51870034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 51970034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 52070034214SMatthew G. Knepley } 52170034214SMatthew G. Knepley } 5229ffc88e4SToby Isaac } 52370034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 52470034214SMatthew 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); 52570034214SMatthew G. Knepley #endif 52670034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 52770034214SMatthew G. Knepley } 52870034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 52970034214SMatthew G. Knepley if (offsets) *offsets = off; 53070034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 53170034214SMatthew G. Knepley PetscFunctionReturn(0); 53270034214SMatthew G. Knepley } 53370034214SMatthew G. Knepley /* Setup face recognition */ 53470034214SMatthew G. Knepley if (faceDepth == 1) { 53570034214SMatthew 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 */ 53670034214SMatthew G. Knepley 53770034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 53870034214SMatthew G. Knepley PetscInt corners; 53970034214SMatthew G. Knepley 54070034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 54170034214SMatthew G. Knepley if (!cornersSeen[corners]) { 54270034214SMatthew G. Knepley PetscInt nFV; 54370034214SMatthew G. Knepley 54470034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 54570034214SMatthew G. Knepley cornersSeen[corners] = 1; 54670034214SMatthew G. Knepley 54770034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 54870034214SMatthew G. Knepley 54970034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 55070034214SMatthew G. Knepley } 55170034214SMatthew G. Knepley } 55270034214SMatthew G. Knepley } 55370034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 55470034214SMatthew G. Knepley /* Count neighboring cells */ 55570034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 55670034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 55770034214SMatthew G. Knepley 5588b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 55970034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 56070034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 56170034214SMatthew G. Knepley PetscInt cellPair[2]; 56270034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 56370034214SMatthew G. Knepley PetscInt meetSize = 0; 56470034214SMatthew G. Knepley const PetscInt *meet = NULL; 56570034214SMatthew G. Knepley 56670034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 56770034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 56870034214SMatthew G. Knepley if (!found) { 56970034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 57070034214SMatthew G. Knepley if (meetSize) { 57170034214SMatthew G. Knepley PetscInt f; 57270034214SMatthew G. Knepley 57370034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 57470034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 57570034214SMatthew G. Knepley found = PETSC_TRUE; 57670034214SMatthew G. Knepley break; 57770034214SMatthew G. Knepley } 57870034214SMatthew G. Knepley } 57970034214SMatthew G. Knepley } 58070034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 58170034214SMatthew G. Knepley } 58270034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 58370034214SMatthew G. Knepley } 58470034214SMatthew G. Knepley } 58570034214SMatthew G. Knepley /* Prefix sum */ 58670034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 58770034214SMatthew G. Knepley 58870034214SMatthew G. Knepley if (adjacency) { 58970034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 59070034214SMatthew G. Knepley /* Get neighboring cells */ 59170034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 59270034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 59370034214SMatthew G. Knepley PetscInt cellOffset = 0; 59470034214SMatthew G. Knepley 5958b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 59670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 59770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 59870034214SMatthew G. Knepley PetscInt cellPair[2]; 59970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 60070034214SMatthew G. Knepley PetscInt meetSize = 0; 60170034214SMatthew G. Knepley const PetscInt *meet = NULL; 60270034214SMatthew G. Knepley 60370034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 60470034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 60570034214SMatthew G. Knepley if (!found) { 60670034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 60770034214SMatthew G. Knepley if (meetSize) { 60870034214SMatthew G. Knepley PetscInt f; 60970034214SMatthew G. Knepley 61070034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 61170034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 61270034214SMatthew G. Knepley found = PETSC_TRUE; 61370034214SMatthew G. Knepley break; 61470034214SMatthew G. Knepley } 61570034214SMatthew G. Knepley } 61670034214SMatthew G. Knepley } 61770034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 61870034214SMatthew G. Knepley } 61970034214SMatthew G. Knepley if (found) { 62070034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 62170034214SMatthew G. Knepley ++cellOffset; 62270034214SMatthew G. Knepley } 62370034214SMatthew G. Knepley } 62470034214SMatthew G. Knepley } 62570034214SMatthew G. Knepley } 62670034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 62770034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 62870034214SMatthew G. Knepley if (offsets) *offsets = off; 62970034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 63070034214SMatthew G. Knepley PetscFunctionReturn(0); 63170034214SMatthew G. Knepley } 63270034214SMatthew G. Knepley 63377623264SMatthew G. Knepley /*@C 63477623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 63577623264SMatthew G. Knepley 63677623264SMatthew G. Knepley Not Collective 63777623264SMatthew G. Knepley 63877623264SMatthew G. Knepley Input Parameters: 63977623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 64077623264SMatthew G. Knepley - create_func - The creation routine itself 64177623264SMatthew G. Knepley 64277623264SMatthew G. Knepley Notes: 64377623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 64477623264SMatthew G. Knepley 64577623264SMatthew G. Knepley Sample usage: 64677623264SMatthew G. Knepley .vb 64777623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 64877623264SMatthew G. Knepley .ve 64977623264SMatthew G. Knepley 65077623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 65177623264SMatthew G. Knepley .vb 65277623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 65377623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 65477623264SMatthew G. Knepley .ve 65577623264SMatthew G. Knepley or at runtime via the option 65677623264SMatthew G. Knepley .vb 65777623264SMatthew G. Knepley -petscpartitioner_type my_part 65877623264SMatthew G. Knepley .ve 65977623264SMatthew G. Knepley 66077623264SMatthew G. Knepley Level: advanced 66177623264SMatthew G. Knepley 66277623264SMatthew G. Knepley .keywords: PetscPartitioner, register 66377623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 66477623264SMatthew G. Knepley 66577623264SMatthew G. Knepley @*/ 66677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 66777623264SMatthew G. Knepley { 66877623264SMatthew G. Knepley PetscErrorCode ierr; 66977623264SMatthew G. Knepley 67077623264SMatthew G. Knepley PetscFunctionBegin; 67177623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 67277623264SMatthew G. Knepley PetscFunctionReturn(0); 67377623264SMatthew G. Knepley } 67477623264SMatthew G. Knepley 67577623264SMatthew G. Knepley /*@C 67677623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 67777623264SMatthew G. Knepley 67877623264SMatthew G. Knepley Collective on PetscPartitioner 67977623264SMatthew G. Knepley 68077623264SMatthew G. Knepley Input Parameters: 68177623264SMatthew G. Knepley + part - The PetscPartitioner object 68277623264SMatthew G. Knepley - name - The kind of partitioner 68377623264SMatthew G. Knepley 68477623264SMatthew G. Knepley Options Database Key: 68577623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 68677623264SMatthew G. Knepley 68777623264SMatthew G. Knepley Level: intermediate 68877623264SMatthew G. Knepley 68977623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 69077623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 69177623264SMatthew G. Knepley @*/ 69277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 69377623264SMatthew G. Knepley { 69477623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 69577623264SMatthew G. Knepley PetscBool match; 69677623264SMatthew G. Knepley PetscErrorCode ierr; 69777623264SMatthew G. Knepley 69877623264SMatthew G. Knepley PetscFunctionBegin; 69977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 70077623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 70177623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 70277623264SMatthew G. Knepley 7030f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 70477623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 70577623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 70677623264SMatthew G. Knepley 70777623264SMatthew G. Knepley if (part->ops->destroy) { 70877623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 70977623264SMatthew G. Knepley } 710074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 71109161815SVaclav Hapla ierr = PetscMemzero(part->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 71277623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 71377623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 71477623264SMatthew G. Knepley PetscFunctionReturn(0); 71577623264SMatthew G. Knepley } 71677623264SMatthew G. Knepley 71777623264SMatthew G. Knepley /*@C 71877623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 71977623264SMatthew G. Knepley 72077623264SMatthew G. Knepley Not Collective 72177623264SMatthew G. Knepley 72277623264SMatthew G. Knepley Input Parameter: 72377623264SMatthew G. Knepley . part - The PetscPartitioner 72477623264SMatthew G. Knepley 72577623264SMatthew G. Knepley Output Parameter: 72677623264SMatthew G. Knepley . name - The PetscPartitioner type name 72777623264SMatthew G. Knepley 72877623264SMatthew G. Knepley Level: intermediate 72977623264SMatthew G. Knepley 73077623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 73177623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 73277623264SMatthew G. Knepley @*/ 73377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 73477623264SMatthew G. Knepley { 73577623264SMatthew G. Knepley PetscErrorCode ierr; 73677623264SMatthew G. Knepley 73777623264SMatthew G. Knepley PetscFunctionBegin; 73877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 73977623264SMatthew G. Knepley PetscValidPointer(name, 2); 7400f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 74177623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 74277623264SMatthew G. Knepley PetscFunctionReturn(0); 74377623264SMatthew G. Knepley } 74477623264SMatthew G. Knepley 74577623264SMatthew G. Knepley /*@C 74677623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 74777623264SMatthew G. Knepley 74877623264SMatthew G. Knepley Collective on PetscPartitioner 74977623264SMatthew G. Knepley 75077623264SMatthew G. Knepley Input Parameter: 75177623264SMatthew G. Knepley + part - the PetscPartitioner object to view 75277623264SMatthew G. Knepley - v - the viewer 75377623264SMatthew G. Knepley 75477623264SMatthew G. Knepley Level: developer 75577623264SMatthew G. Knepley 75677623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 75777623264SMatthew G. Knepley @*/ 75877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 75977623264SMatthew G. Knepley { 760ffc59708SMatthew G. Knepley PetscMPIInt size; 7612abdaa70SMatthew G. Knepley PetscBool isascii; 76277623264SMatthew G. Knepley PetscErrorCode ierr; 76377623264SMatthew G. Knepley 76477623264SMatthew G. Knepley PetscFunctionBegin; 76577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 76677623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 7672abdaa70SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 7682abdaa70SMatthew G. Knepley if (isascii) { 7692abdaa70SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 770ffc59708SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");CHKERRQ(ierr); 7712abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " type: %s\n", part->hdr.type_name);CHKERRQ(ierr); 7722abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 7732abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "edge cut: %D\n", part->edgeCut);CHKERRQ(ierr); 7742abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "balance: %.2g\n", part->balance);CHKERRQ(ierr); 7752abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 7762abdaa70SMatthew G. Knepley } 77777623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 77877623264SMatthew G. Knepley PetscFunctionReturn(0); 77977623264SMatthew G. Knepley } 78077623264SMatthew G. Knepley 781a0058e54SToby Isaac static PetscErrorCode PetscPartitionerGetDefaultType(const char *currentType, const char **defaultType) 782a0058e54SToby Isaac { 783a0058e54SToby Isaac PetscFunctionBegin; 784a0058e54SToby Isaac if (!currentType) { 78556bf5a81SLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 786a0058e54SToby Isaac *defaultType = PETSCPARTITIONERPARMETIS; 787137cd93aSLisandro Dalcin #elif defined(PETSC_HAVE_PTSCOTCH) 788137cd93aSLisandro Dalcin *defaultType = PETSCPARTITIONERPTSCOTCH; 78956bf5a81SLisandro Dalcin #elif defined(PETSC_HAVE_CHACO) 79056bf5a81SLisandro Dalcin *defaultType = PETSCPARTITIONERCHACO; 791a0058e54SToby Isaac #else 792a0058e54SToby Isaac *defaultType = PETSCPARTITIONERSIMPLE; 793a0058e54SToby Isaac #endif 794a0058e54SToby Isaac } else { 795a0058e54SToby Isaac *defaultType = currentType; 796a0058e54SToby Isaac } 797a0058e54SToby Isaac PetscFunctionReturn(0); 798a0058e54SToby Isaac } 799a0058e54SToby Isaac 80077623264SMatthew G. Knepley /*@ 80177623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 80277623264SMatthew G. Knepley 80377623264SMatthew G. Knepley Collective on PetscPartitioner 80477623264SMatthew G. Knepley 80577623264SMatthew G. Knepley Input Parameter: 80677623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 80777623264SMatthew G. Knepley 80877623264SMatthew G. Knepley Level: developer 80977623264SMatthew G. Knepley 81077623264SMatthew G. Knepley .seealso: PetscPartitionerView() 81177623264SMatthew G. Knepley @*/ 81277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 81377623264SMatthew G. Knepley { 8146bb9daa8SLisandro Dalcin const char *defaultType; 8156bb9daa8SLisandro Dalcin char name[256]; 8166bb9daa8SLisandro Dalcin PetscBool flg; 81777623264SMatthew G. Knepley PetscErrorCode ierr; 81877623264SMatthew G. Knepley 81977623264SMatthew G. Knepley PetscFunctionBegin; 82077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8216bb9daa8SLisandro Dalcin ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 8226bb9daa8SLisandro Dalcin ierr = PetscPartitionerGetDefaultType(((PetscObject) part)->type_name,&defaultType);CHKERRQ(ierr); 82377623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 8246bb9daa8SLisandro Dalcin ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, sizeof(name), &flg);CHKERRQ(ierr); 8256bb9daa8SLisandro Dalcin if (flg) { 8266bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 8276bb9daa8SLisandro Dalcin } else if (!((PetscObject) part)->type_name) { 8286bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 8296bb9daa8SLisandro Dalcin } 8306bb9daa8SLisandro Dalcin if (part->ops->setfromoptions) { 8316bb9daa8SLisandro Dalcin ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr); 8326bb9daa8SLisandro Dalcin } 833783e1fb6SStefano Zampini ierr = PetscViewerDestroy(&part->viewerGraph);CHKERRQ(ierr); 8340358368aSMatthew G. Knepley ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, &part->formatGraph, &part->viewGraph);CHKERRQ(ierr); 83577623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 8360633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 83777623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 83877623264SMatthew G. Knepley PetscFunctionReturn(0); 83977623264SMatthew G. Knepley } 84077623264SMatthew G. Knepley 84177623264SMatthew G. Knepley /*@C 84277623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 84377623264SMatthew G. Knepley 84477623264SMatthew G. Knepley Collective on PetscPartitioner 84577623264SMatthew G. Knepley 84677623264SMatthew G. Knepley Input Parameter: 84777623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 84877623264SMatthew G. Knepley 84977623264SMatthew G. Knepley Level: developer 85077623264SMatthew G. Knepley 85177623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 85277623264SMatthew G. Knepley @*/ 85377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 85477623264SMatthew G. Knepley { 85577623264SMatthew G. Knepley PetscErrorCode ierr; 85677623264SMatthew G. Knepley 85777623264SMatthew G. Knepley PetscFunctionBegin; 85877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 85977623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 86077623264SMatthew G. Knepley PetscFunctionReturn(0); 86177623264SMatthew G. Knepley } 86277623264SMatthew G. Knepley 86377623264SMatthew G. Knepley /*@ 86477623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 86577623264SMatthew G. Knepley 86677623264SMatthew G. Knepley Collective on PetscPartitioner 86777623264SMatthew G. Knepley 86877623264SMatthew G. Knepley Input Parameter: 86977623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 87077623264SMatthew G. Knepley 87177623264SMatthew G. Knepley Level: developer 87277623264SMatthew G. Knepley 87377623264SMatthew G. Knepley .seealso: PetscPartitionerView() 87477623264SMatthew G. Knepley @*/ 87577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 87677623264SMatthew G. Knepley { 87777623264SMatthew G. Knepley PetscErrorCode ierr; 87877623264SMatthew G. Knepley 87977623264SMatthew G. Knepley PetscFunctionBegin; 88077623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 88177623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 88277623264SMatthew G. Knepley 88377623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 88477623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 88577623264SMatthew G. Knepley 8860358368aSMatthew G. Knepley ierr = PetscViewerDestroy(&(*part)->viewerGraph);CHKERRQ(ierr); 88777623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 88877623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 88977623264SMatthew G. Knepley PetscFunctionReturn(0); 89077623264SMatthew G. Knepley } 89177623264SMatthew G. Knepley 89277623264SMatthew G. Knepley /*@ 89377623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 89477623264SMatthew G. Knepley 89577623264SMatthew G. Knepley Collective on MPI_Comm 89677623264SMatthew G. Knepley 89777623264SMatthew G. Knepley Input Parameter: 89877623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 89977623264SMatthew G. Knepley 90077623264SMatthew G. Knepley Output Parameter: 90177623264SMatthew G. Knepley . part - The PetscPartitioner object 90277623264SMatthew G. Knepley 90377623264SMatthew G. Knepley Level: beginner 90477623264SMatthew G. Knepley 905dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 90677623264SMatthew G. Knepley @*/ 90777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 90877623264SMatthew G. Knepley { 90977623264SMatthew G. Knepley PetscPartitioner p; 910a0058e54SToby Isaac const char *partitionerType = NULL; 91177623264SMatthew G. Knepley PetscErrorCode ierr; 91277623264SMatthew G. Knepley 91377623264SMatthew G. Knepley PetscFunctionBegin; 91477623264SMatthew G. Knepley PetscValidPointer(part, 2); 91577623264SMatthew G. Knepley *part = NULL; 91683cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 91777623264SMatthew G. Knepley 91873107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 919a0058e54SToby Isaac ierr = PetscPartitionerGetDefaultType(NULL,&partitionerType);CHKERRQ(ierr); 920a0058e54SToby Isaac ierr = PetscPartitionerSetType(p,partitionerType);CHKERRQ(ierr); 92177623264SMatthew G. Knepley 92272379da4SMatthew G. Knepley p->edgeCut = 0; 92372379da4SMatthew G. Knepley p->balance = 0.0; 92472379da4SMatthew G. Knepley 92577623264SMatthew G. Knepley *part = p; 92677623264SMatthew G. Knepley PetscFunctionReturn(0); 92777623264SMatthew G. Knepley } 92877623264SMatthew G. Knepley 92977623264SMatthew G. Knepley /*@ 93077623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 93177623264SMatthew G. Knepley 93277623264SMatthew G. Knepley Collective on DM 93377623264SMatthew G. Knepley 93477623264SMatthew G. Knepley Input Parameters: 93577623264SMatthew G. Knepley + part - The PetscPartitioner 936f8987ae8SMichael Lange - dm - The mesh DM 93777623264SMatthew G. Knepley 93877623264SMatthew G. Knepley Output Parameters: 93977623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 940f8987ae8SMichael Lange - partition - The list of points by partition 94177623264SMatthew G. Knepley 9420358368aSMatthew G. Knepley Options Database: 9430358368aSMatthew G. Knepley . -petscpartitioner_view_graph - View the graph we are partitioning 9440358368aSMatthew G. Knepley 94577623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 94677623264SMatthew G. Knepley 94777623264SMatthew G. Knepley Level: developer 94877623264SMatthew G. Knepley 94977623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 9504b15ede2SMatthew G. Knepley @*/ 951f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 95277623264SMatthew G. Knepley { 95377623264SMatthew G. Knepley PetscMPIInt size; 95477623264SMatthew G. Knepley PetscErrorCode ierr; 95577623264SMatthew G. Knepley 95677623264SMatthew G. Knepley PetscFunctionBegin; 95777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 95877623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 95977623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 96077623264SMatthew G. Knepley PetscValidPointer(partition, 5); 96177623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 96277623264SMatthew G. Knepley if (size == 1) { 96377623264SMatthew G. Knepley PetscInt *points; 96477623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 96577623264SMatthew G. Knepley 96677623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 96777623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 96877623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 96977623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 97077623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 97177623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 97277623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 97377623264SMatthew G. Knepley PetscFunctionReturn(0); 97477623264SMatthew G. Knepley } 97577623264SMatthew G. Knepley if (part->height == 0) { 976074d466cSStefano Zampini PetscInt numVertices = 0; 97777623264SMatthew G. Knepley PetscInt *start = NULL; 97877623264SMatthew G. Knepley PetscInt *adjacency = NULL; 9793fa7752dSToby Isaac IS globalNumbering; 98077623264SMatthew G. Knepley 981074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 982074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 983*13911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 984074d466cSStefano Zampini const PetscInt *idxs; 985074d466cSStefano Zampini PetscInt p, pStart, pEnd; 986074d466cSStefano Zampini 987074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 988074d466cSStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 989074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 990074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 991074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 992074d466cSStefano Zampini } 9930358368aSMatthew G. Knepley if (part->viewGraph) { 9940358368aSMatthew G. Knepley PetscViewer viewer = part->viewerGraph; 9950358368aSMatthew G. Knepley PetscBool isascii; 9960358368aSMatthew G. Knepley PetscInt v, i; 9970358368aSMatthew G. Knepley PetscMPIInt rank; 9980358368aSMatthew G. Knepley 9990358368aSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRQ(ierr); 10000358368aSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 10010358368aSMatthew G. Knepley if (isascii) { 10020358368aSMatthew G. Knepley ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 10030358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);CHKERRQ(ierr); 10040358368aSMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 10050358368aSMatthew G. Knepley const PetscInt s = start[v]; 10060358368aSMatthew G. Knepley const PetscInt e = start[v+1]; 10070358368aSMatthew G. Knepley 10080358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank);CHKERRQ(ierr); 10090358368aSMatthew G. Knepley for (i = s; i < e; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);CHKERRQ(ierr);} 10100358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);CHKERRQ(ierr); 10110358368aSMatthew G. Knepley } 10120358368aSMatthew G. Knepley ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 10130358368aSMatthew G. Knepley ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 10140358368aSMatthew G. Knepley } 10150358368aSMatthew G. Knepley } 1016bbbc8e51SStefano Zampini if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no partitioning method"); 101777623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 101877623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 101977623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 10203fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 10213fa7752dSToby Isaac const PetscInt *globalNum; 10223fa7752dSToby Isaac const PetscInt *partIdx; 10233fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 10243fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 10253fa7752dSToby Isaac IS newPartition; 10263fa7752dSToby Isaac 10273fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 10283fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 10293fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10303fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 10313fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 10323fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 10333fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 10343fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 10353fa7752dSToby Isaac } 10363fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 10373fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 10383fa7752dSToby Isaac } 10393fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 10403fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 10413fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10423fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 10433fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 10443fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 10453fa7752dSToby Isaac *partition = newPartition; 10463fa7752dSToby Isaac } 104777623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 10482abdaa70SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 104977623264SMatthew G. Knepley PetscFunctionReturn(0); 105077623264SMatthew G. Knepley } 105177623264SMatthew G. Knepley 1052d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 105377623264SMatthew G. Knepley { 105477623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 105577623264SMatthew G. Knepley PetscErrorCode ierr; 105677623264SMatthew G. Knepley 105777623264SMatthew G. Knepley PetscFunctionBegin; 105877623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 105977623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 106077623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 106177623264SMatthew G. Knepley PetscFunctionReturn(0); 106277623264SMatthew G. Knepley } 106377623264SMatthew G. Knepley 1064d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 106577623264SMatthew G. Knepley { 1066077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 106777623264SMatthew G. Knepley PetscErrorCode ierr; 106877623264SMatthew G. Knepley 106977623264SMatthew G. Knepley PetscFunctionBegin; 1070077101c0SMatthew G. Knepley if (p->random) { 1071077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1072077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 1073077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1074077101c0SMatthew G. Knepley } 107577623264SMatthew G. Knepley PetscFunctionReturn(0); 107677623264SMatthew G. Knepley } 107777623264SMatthew G. Knepley 1078d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 107977623264SMatthew G. Knepley { 108077623264SMatthew G. Knepley PetscBool iascii; 108177623264SMatthew G. Knepley PetscErrorCode ierr; 108277623264SMatthew G. Knepley 108377623264SMatthew G. Knepley PetscFunctionBegin; 108477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 108577623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 108677623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 108777623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 108877623264SMatthew G. Knepley PetscFunctionReturn(0); 108977623264SMatthew G. Knepley } 109077623264SMatthew G. Knepley 1091d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 1092077101c0SMatthew G. Knepley { 1093077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1094077101c0SMatthew G. Knepley PetscErrorCode ierr; 1095077101c0SMatthew G. Knepley 1096077101c0SMatthew G. Knepley PetscFunctionBegin; 1097077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 1098077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 1099077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1100077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1101077101c0SMatthew G. Knepley } 1102077101c0SMatthew G. Knepley 1103d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 110477623264SMatthew G. Knepley { 110577623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 110677623264SMatthew G. Knepley PetscInt np; 110777623264SMatthew G. Knepley PetscErrorCode ierr; 110877623264SMatthew G. Knepley 110977623264SMatthew G. Knepley PetscFunctionBegin; 1110077101c0SMatthew G. Knepley if (p->random) { 1111077101c0SMatthew G. Knepley PetscRandom r; 1112aa1d5631SMatthew G. Knepley PetscInt *sizes, *points, v, p; 1113aa1d5631SMatthew G. Knepley PetscMPIInt rank; 1114077101c0SMatthew G. Knepley 1115aa1d5631SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1116077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 1117c717d290SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 1118077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 1119077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 1120aa1d5631SMatthew G. Knepley for (v = 0; v < numVertices; ++v) {points[v] = v;} 1121ac9a96f1SMichael Lange for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 1122aa1d5631SMatthew G. Knepley for (v = numVertices-1; v > 0; --v) { 1123077101c0SMatthew G. Knepley PetscReal val; 1124aa1d5631SMatthew G. Knepley PetscInt w, tmp; 1125077101c0SMatthew G. Knepley 1126aa1d5631SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 1127077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 1128aa1d5631SMatthew G. Knepley w = PetscFloorReal(val); 1129aa1d5631SMatthew G. Knepley tmp = points[v]; 1130aa1d5631SMatthew G. Knepley points[v] = points[w]; 1131aa1d5631SMatthew G. Knepley points[w] = tmp; 1132077101c0SMatthew G. Knepley } 1133077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 1134077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 1135077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 1136077101c0SMatthew G. Knepley } 1137c717d290SMatthew G. Knepley if (!p->section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 113877623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 113977623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 114077623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 114177623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 11425680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 114377623264SMatthew G. Knepley *partition = p->partition; 114477623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 114577623264SMatthew G. Knepley PetscFunctionReturn(0); 114677623264SMatthew G. Knepley } 114777623264SMatthew G. Knepley 1148d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 114977623264SMatthew G. Knepley { 115077623264SMatthew G. Knepley PetscFunctionBegin; 1151074d466cSStefano Zampini part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 115277623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 1153077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 115477623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 115577623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 115677623264SMatthew G. Knepley PetscFunctionReturn(0); 115777623264SMatthew G. Knepley } 115877623264SMatthew G. Knepley 115977623264SMatthew G. Knepley /*MC 116077623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 116177623264SMatthew G. Knepley 116277623264SMatthew G. Knepley Level: intermediate 116377623264SMatthew G. Knepley 116477623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 116577623264SMatthew G. Knepley M*/ 116677623264SMatthew G. Knepley 116777623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 116877623264SMatthew G. Knepley { 116977623264SMatthew G. Knepley PetscPartitioner_Shell *p; 117077623264SMatthew G. Knepley PetscErrorCode ierr; 117177623264SMatthew G. Knepley 117277623264SMatthew G. Knepley PetscFunctionBegin; 117377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 117477623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 117577623264SMatthew G. Knepley part->data = p; 117677623264SMatthew G. Knepley 117777623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 1178077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 117977623264SMatthew G. Knepley PetscFunctionReturn(0); 118077623264SMatthew G. Knepley } 118177623264SMatthew G. Knepley 11825680f57bSMatthew G. Knepley /*@C 11835680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 11845680f57bSMatthew G. Knepley 1185077101c0SMatthew G. Knepley Collective on Part 11865680f57bSMatthew G. Knepley 11875680f57bSMatthew G. Knepley Input Parameters: 11885680f57bSMatthew G. Knepley + part - The PetscPartitioner 11899852e123SBarry Smith . size - The number of partitions 11909852e123SBarry Smith . sizes - array of size size (or NULL) providing the number of points in each partition 11919758bf69SToby 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.) 11925680f57bSMatthew G. Knepley 11935680f57bSMatthew G. Knepley Level: developer 11945680f57bSMatthew G. Knepley 1195b7e49471SLawrence Mitchell Notes: 1196b7e49471SLawrence Mitchell 1197b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 1198b7e49471SLawrence Mitchell 11995680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 12005680f57bSMatthew G. Knepley @*/ 12019852e123SBarry Smith PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 12025680f57bSMatthew G. Knepley { 12035680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 12045680f57bSMatthew G. Knepley PetscInt proc, numPoints; 12055680f57bSMatthew G. Knepley PetscErrorCode ierr; 12065680f57bSMatthew G. Knepley 12075680f57bSMatthew G. Knepley PetscFunctionBegin; 12085680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 12095680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 1210c717d290SMatthew G. Knepley if (points) {PetscValidPointer(points, 4);} 12115680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 12125680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 12135680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 12149852e123SBarry Smith ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 12155680f57bSMatthew G. Knepley if (sizes) { 12169852e123SBarry Smith for (proc = 0; proc < size; ++proc) { 12175680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 12185680f57bSMatthew G. Knepley } 12195680f57bSMatthew G. Knepley } 12205680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 12215680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 12225680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 12235680f57bSMatthew G. Knepley PetscFunctionReturn(0); 12245680f57bSMatthew G. Knepley } 12255680f57bSMatthew G. Knepley 1226077101c0SMatthew G. Knepley /*@ 1227077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 1228077101c0SMatthew G. Knepley 1229077101c0SMatthew G. Knepley Collective on Part 1230077101c0SMatthew G. Knepley 1231077101c0SMatthew G. Knepley Input Parameters: 1232077101c0SMatthew G. Knepley + part - The PetscPartitioner 1233077101c0SMatthew G. Knepley - random - The flag to use a random partition 1234077101c0SMatthew G. Knepley 1235077101c0SMatthew G. Knepley Level: intermediate 1236077101c0SMatthew G. Knepley 1237077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 1238077101c0SMatthew G. Knepley @*/ 1239077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 1240077101c0SMatthew G. Knepley { 1241077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1242077101c0SMatthew G. Knepley 1243077101c0SMatthew G. Knepley PetscFunctionBegin; 1244077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1245077101c0SMatthew G. Knepley p->random = random; 1246077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1247077101c0SMatthew G. Knepley } 1248077101c0SMatthew G. Knepley 1249077101c0SMatthew G. Knepley /*@ 1250077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 1251077101c0SMatthew G. Knepley 1252077101c0SMatthew G. Knepley Collective on Part 1253077101c0SMatthew G. Knepley 1254077101c0SMatthew G. Knepley Input Parameter: 1255077101c0SMatthew G. Knepley . part - The PetscPartitioner 1256077101c0SMatthew G. Knepley 1257077101c0SMatthew G. Knepley Output Parameter 1258077101c0SMatthew G. Knepley . random - The flag to use a random partition 1259077101c0SMatthew G. Knepley 1260077101c0SMatthew G. Knepley Level: intermediate 1261077101c0SMatthew G. Knepley 1262077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 1263077101c0SMatthew G. Knepley @*/ 1264077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 1265077101c0SMatthew G. Knepley { 1266077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1267077101c0SMatthew G. Knepley 1268077101c0SMatthew G. Knepley PetscFunctionBegin; 1269077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1270077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 1271077101c0SMatthew G. Knepley *random = p->random; 1272077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1273077101c0SMatthew G. Knepley } 1274077101c0SMatthew G. Knepley 1275d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 1276555a9cf8SMatthew G. Knepley { 1277555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 1278555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1279555a9cf8SMatthew G. Knepley 1280555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1281555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 1282555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1283555a9cf8SMatthew G. Knepley } 1284555a9cf8SMatthew G. Knepley 1285d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 1286555a9cf8SMatthew G. Knepley { 1287555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1288555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1289555a9cf8SMatthew G. Knepley } 1290555a9cf8SMatthew G. Knepley 1291d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 1292555a9cf8SMatthew G. Knepley { 1293555a9cf8SMatthew G. Knepley PetscBool iascii; 1294555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1295555a9cf8SMatthew G. Knepley 1296555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1297555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1298555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1299555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1300555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 1301555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1302555a9cf8SMatthew G. Knepley } 1303555a9cf8SMatthew G. Knepley 1304d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1305555a9cf8SMatthew G. Knepley { 1306cead94edSToby Isaac MPI_Comm comm; 1307555a9cf8SMatthew G. Knepley PetscInt np; 1308cead94edSToby Isaac PetscMPIInt size; 1309555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1310555a9cf8SMatthew G. Knepley 1311555a9cf8SMatthew G. Knepley PetscFunctionBegin; 131204ba2274SStefano Zampini comm = PetscObjectComm((PetscObject)part); 1313cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1314555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1315555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1316cead94edSToby Isaac if (size == 1) { 1317cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 131804ba2274SStefano Zampini } else { 1319cead94edSToby Isaac PetscMPIInt rank; 1320cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 1321cead94edSToby Isaac 1322a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1323cead94edSToby Isaac offsets[0] = 0; 1324cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1325cead94edSToby Isaac for (np = 2; np <= size; np++) { 1326cead94edSToby Isaac offsets[np] += offsets[np-1]; 1327cead94edSToby Isaac } 1328cead94edSToby Isaac nvGlobal = offsets[size]; 1329cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1330cead94edSToby Isaac myFirst = offsets[rank]; 1331cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1332cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1333cead94edSToby Isaac if (numVertices) { 1334cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1335cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1336cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1337cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1338cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1339cead94edSToby Isaac 1340cead94edSToby Isaac 1341cead94edSToby Isaac if (rem) { 1342cead94edSToby Isaac firstLargePart = myFirst / pBig; 1343cead94edSToby Isaac lastLargePart = myLast / pBig; 1344cead94edSToby Isaac 1345cead94edSToby Isaac if (firstLargePart < rem) { 1346cead94edSToby Isaac firstPart = firstLargePart; 134704ba2274SStefano Zampini } else { 1348cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1349cead94edSToby Isaac } 1350cead94edSToby Isaac if (lastLargePart < rem) { 1351cead94edSToby Isaac lastPart = lastLargePart; 135204ba2274SStefano Zampini } else { 1353cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1354cead94edSToby Isaac } 135504ba2274SStefano Zampini } else { 1356cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1357cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1358cead94edSToby Isaac } 1359cead94edSToby Isaac 1360cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1361cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1362cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1363cead94edSToby Isaac 1364cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1365cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1366cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1367cead94edSToby Isaac } 1368cead94edSToby Isaac } 1369cead94edSToby Isaac } 1370cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1371555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1372555a9cf8SMatthew G. Knepley } 1373555a9cf8SMatthew G. Knepley 1374d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1375555a9cf8SMatthew G. Knepley { 1376555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1377074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1378555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1379555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1380555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1381555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1382555a9cf8SMatthew G. Knepley } 1383555a9cf8SMatthew G. Knepley 1384555a9cf8SMatthew G. Knepley /*MC 1385555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1386555a9cf8SMatthew G. Knepley 1387555a9cf8SMatthew G. Knepley Level: intermediate 1388555a9cf8SMatthew G. Knepley 1389555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1390555a9cf8SMatthew G. Knepley M*/ 1391555a9cf8SMatthew G. Knepley 1392555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1393555a9cf8SMatthew G. Knepley { 1394555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1395555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1396555a9cf8SMatthew G. Knepley 1397555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1398555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1399555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1400555a9cf8SMatthew G. Knepley part->data = p; 1401555a9cf8SMatthew G. Knepley 1402555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1403555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1404555a9cf8SMatthew G. Knepley } 1405555a9cf8SMatthew G. Knepley 1406d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1407dae52e14SToby Isaac { 1408dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1409dae52e14SToby Isaac PetscErrorCode ierr; 1410dae52e14SToby Isaac 1411dae52e14SToby Isaac PetscFunctionBegin; 1412dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1413dae52e14SToby Isaac PetscFunctionReturn(0); 1414dae52e14SToby Isaac } 1415dae52e14SToby Isaac 1416d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1417dae52e14SToby Isaac { 1418dae52e14SToby Isaac PetscFunctionBegin; 1419dae52e14SToby Isaac PetscFunctionReturn(0); 1420dae52e14SToby Isaac } 1421dae52e14SToby Isaac 1422d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1423dae52e14SToby Isaac { 1424dae52e14SToby Isaac PetscBool iascii; 1425dae52e14SToby Isaac PetscErrorCode ierr; 1426dae52e14SToby Isaac 1427dae52e14SToby Isaac PetscFunctionBegin; 1428dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1429dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1430dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1431dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1432dae52e14SToby Isaac PetscFunctionReturn(0); 1433dae52e14SToby Isaac } 1434dae52e14SToby Isaac 1435d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1436dae52e14SToby Isaac { 1437dae52e14SToby Isaac PetscInt np; 1438dae52e14SToby Isaac PetscErrorCode ierr; 1439dae52e14SToby Isaac 1440dae52e14SToby Isaac PetscFunctionBegin; 1441dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1442dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1443dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1444dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1445dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1446dae52e14SToby Isaac PetscFunctionReturn(0); 1447dae52e14SToby Isaac } 1448dae52e14SToby Isaac 1449d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1450dae52e14SToby Isaac { 1451dae52e14SToby Isaac PetscFunctionBegin; 1452074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1453dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1454dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1455dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1456dae52e14SToby Isaac PetscFunctionReturn(0); 1457dae52e14SToby Isaac } 1458dae52e14SToby Isaac 1459dae52e14SToby Isaac /*MC 1460dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1461dae52e14SToby Isaac 1462dae52e14SToby Isaac Level: intermediate 1463dae52e14SToby Isaac 1464dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1465dae52e14SToby Isaac M*/ 1466dae52e14SToby Isaac 1467dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1468dae52e14SToby Isaac { 1469dae52e14SToby Isaac PetscPartitioner_Gather *p; 1470dae52e14SToby Isaac PetscErrorCode ierr; 1471dae52e14SToby Isaac 1472dae52e14SToby Isaac PetscFunctionBegin; 1473dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1474dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1475dae52e14SToby Isaac part->data = p; 1476dae52e14SToby Isaac 1477dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1478dae52e14SToby Isaac PetscFunctionReturn(0); 1479dae52e14SToby Isaac } 1480dae52e14SToby Isaac 1481dae52e14SToby Isaac 1482d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 148377623264SMatthew G. Knepley { 148477623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 148577623264SMatthew G. Knepley PetscErrorCode ierr; 148677623264SMatthew G. Knepley 148777623264SMatthew G. Knepley PetscFunctionBegin; 148877623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 148977623264SMatthew G. Knepley PetscFunctionReturn(0); 149077623264SMatthew G. Knepley } 149177623264SMatthew G. Knepley 1492d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 149377623264SMatthew G. Knepley { 149477623264SMatthew G. Knepley PetscFunctionBegin; 149577623264SMatthew G. Knepley PetscFunctionReturn(0); 149677623264SMatthew G. Knepley } 149777623264SMatthew G. Knepley 1498d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 149977623264SMatthew G. Knepley { 150077623264SMatthew G. Knepley PetscBool iascii; 150177623264SMatthew G. Knepley PetscErrorCode ierr; 150277623264SMatthew G. Knepley 150377623264SMatthew G. Knepley PetscFunctionBegin; 150477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 150577623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 150677623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 150777623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 150877623264SMatthew G. Knepley PetscFunctionReturn(0); 150977623264SMatthew G. Knepley } 151077623264SMatthew G. Knepley 151170034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 151270034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 151370034214SMatthew G. Knepley #include <unistd.h> 151470034214SMatthew G. Knepley #endif 151511d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 151611d1e910SBarry Smith #include <chaco.h> 151711d1e910SBarry Smith #else 151811d1e910SBarry Smith /* Older versions of Chaco do not have an include file */ 151970034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 152070034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 152170034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 152270034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 152370034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 152411d1e910SBarry Smith #endif 152570034214SMatthew G. Knepley extern int FREE_GRAPH; 152677623264SMatthew G. Knepley #endif 152770034214SMatthew G. Knepley 1528d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 152970034214SMatthew G. Knepley { 153077623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 153170034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 153270034214SMatthew G. Knepley MPI_Comm comm; 153370034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 153470034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 153570034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 153670034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 153770034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 153870034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 153970034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 154070034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 154170034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 154270034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 154370034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 154470034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 154570034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 154670034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 154770034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 154870034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 154970034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 155011d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 155111d1e910SBarry Smith int *assignment; /* Output partition */ 155211d1e910SBarry Smith #else 155370034214SMatthew G. Knepley short int *assignment; /* Output partition */ 155411d1e910SBarry Smith #endif 155570034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 155670034214SMatthew G. Knepley PetscInt *points; 155770034214SMatthew G. Knepley int i, v, p; 155870034214SMatthew G. Knepley PetscErrorCode ierr; 155970034214SMatthew G. Knepley 156070034214SMatthew G. Knepley PetscFunctionBegin; 156170034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 156207ed3857SLisandro Dalcin #if defined (PETSC_USE_DEBUG) 156307ed3857SLisandro Dalcin { 156407ed3857SLisandro Dalcin int ival,isum; 156507ed3857SLisandro Dalcin PetscBool distributed; 156607ed3857SLisandro Dalcin 156707ed3857SLisandro Dalcin ival = (numVertices > 0); 156807ed3857SLisandro Dalcin ierr = MPI_Allreduce(&ival, &isum, 1, MPI_INT, MPI_SUM, comm);CHKERRQ(ierr); 156907ed3857SLisandro Dalcin distributed = (isum > 1) ? PETSC_TRUE : PETSC_FALSE; 157007ed3857SLisandro Dalcin if (distributed) SETERRQ(comm, PETSC_ERR_SUP, "Chaco cannot partition a distributed graph"); 157107ed3857SLisandro Dalcin } 157207ed3857SLisandro Dalcin #endif 157370034214SMatthew G. Knepley if (!numVertices) { 157477623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 157577623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 157670034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 157770034214SMatthew G. Knepley PetscFunctionReturn(0); 157870034214SMatthew G. Knepley } 157970034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 158070034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 158170034214SMatthew G. Knepley 158270034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 158370034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 158470034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 158570034214SMatthew G. Knepley } 158677623264SMatthew G. Knepley mesh_dims[0] = nparts; 158770034214SMatthew G. Knepley mesh_dims[1] = 1; 158870034214SMatthew G. Knepley mesh_dims[2] = 1; 158970034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 159070034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 159170034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 159270034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 159370034214SMatthew G. Knepley { 159470034214SMatthew G. Knepley int piperet; 159570034214SMatthew G. Knepley piperet = pipe(fd_pipe); 159670034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 159770034214SMatthew G. Knepley fd_stdout = dup(1); 159870034214SMatthew G. Knepley close(1); 159970034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 160070034214SMatthew G. Knepley } 160170034214SMatthew G. Knepley #endif 160270034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 160370034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 160470034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 160570034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 160670034214SMatthew G. Knepley { 160770034214SMatthew G. Knepley char msgLog[10000]; 160870034214SMatthew G. Knepley int count; 160970034214SMatthew G. Knepley 161070034214SMatthew G. Knepley fflush(stdout); 161170034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 161270034214SMatthew G. Knepley if (count < 0) count = 0; 161370034214SMatthew G. Knepley msgLog[count] = 0; 161470034214SMatthew G. Knepley close(1); 161570034214SMatthew G. Knepley dup2(fd_stdout, 1); 161670034214SMatthew G. Knepley close(fd_stdout); 161770034214SMatthew G. Knepley close(fd_pipe[0]); 161870034214SMatthew G. Knepley close(fd_pipe[1]); 161970034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 162070034214SMatthew G. Knepley } 162107ed3857SLisandro Dalcin #else 162207ed3857SLisandro Dalcin if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", "error in stdout"); 162370034214SMatthew G. Knepley #endif 162470034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 162577623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 162670034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 162777623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 162870034214SMatthew G. Knepley } 162977623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 163070034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 163177623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 163270034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 163370034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 163470034214SMatthew G. Knepley } 163570034214SMatthew G. Knepley } 163670034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 163770034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 163870034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 163970034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 164070034214SMatthew G. Knepley } 164170034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 164270034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 164370034214SMatthew G. Knepley PetscFunctionReturn(0); 164477623264SMatthew G. Knepley #else 164577623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 164670034214SMatthew G. Knepley #endif 164777623264SMatthew G. Knepley } 164877623264SMatthew G. Knepley 1649d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 165077623264SMatthew G. Knepley { 165177623264SMatthew G. Knepley PetscFunctionBegin; 1652074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 165377623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 165477623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 165577623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 165677623264SMatthew G. Knepley PetscFunctionReturn(0); 165777623264SMatthew G. Knepley } 165877623264SMatthew G. Knepley 165977623264SMatthew G. Knepley /*MC 166077623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 166177623264SMatthew G. Knepley 166277623264SMatthew G. Knepley Level: intermediate 166377623264SMatthew G. Knepley 166477623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 166577623264SMatthew G. Knepley M*/ 166677623264SMatthew G. Knepley 166777623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 166877623264SMatthew G. Knepley { 166977623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 167077623264SMatthew G. Knepley PetscErrorCode ierr; 167177623264SMatthew G. Knepley 167277623264SMatthew G. Knepley PetscFunctionBegin; 167377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 167477623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 167577623264SMatthew G. Knepley part->data = p; 167677623264SMatthew G. Knepley 167777623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 167877623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 167977623264SMatthew G. Knepley PetscFunctionReturn(0); 168077623264SMatthew G. Knepley } 168177623264SMatthew G. Knepley 16825b440754SMatthew G. Knepley static const char *ptypes[] = {"kway", "rb"}; 16835b440754SMatthew G. Knepley 1684d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 168577623264SMatthew G. Knepley { 168677623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 168777623264SMatthew G. Knepley PetscErrorCode ierr; 168877623264SMatthew G. Knepley 168977623264SMatthew G. Knepley PetscFunctionBegin; 169077623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 169177623264SMatthew G. Knepley PetscFunctionReturn(0); 169277623264SMatthew G. Knepley } 169377623264SMatthew G. Knepley 1694d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 169577623264SMatthew G. Knepley { 16962abdaa70SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 169777623264SMatthew G. Knepley PetscErrorCode ierr; 169877623264SMatthew G. Knepley 169977623264SMatthew G. Knepley PetscFunctionBegin; 17002abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 17012abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 17022abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 17032abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 17049d459c0eSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer, "random seed %D\n", p->randomSeed);CHKERRQ(ierr); 17052abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 170677623264SMatthew G. Knepley PetscFunctionReturn(0); 170777623264SMatthew G. Knepley } 170877623264SMatthew G. Knepley 1709d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 171077623264SMatthew G. Knepley { 171177623264SMatthew G. Knepley PetscBool iascii; 171277623264SMatthew G. Knepley PetscErrorCode ierr; 171377623264SMatthew G. Knepley 171477623264SMatthew G. Knepley PetscFunctionBegin; 171577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 171677623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 171777623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 171877623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 171977623264SMatthew G. Knepley PetscFunctionReturn(0); 172077623264SMatthew G. Knepley } 172170034214SMatthew G. Knepley 172244d8be81SLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 172344d8be81SLisandro Dalcin { 172444d8be81SLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 172544d8be81SLisandro Dalcin PetscErrorCode ierr; 172644d8be81SLisandro Dalcin 172744d8be81SLisandro Dalcin PetscFunctionBegin; 172844d8be81SLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 172944d8be81SLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 17305b440754SMatthew G. Knepley ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 17315b440754SMatthew G. Knepley ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 17329d459c0eSStefano Zampini ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p->randomSeed, &p->randomSeed, NULL);CHKERRQ(ierr); 173344d8be81SLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 173444d8be81SLisandro Dalcin PetscFunctionReturn(0); 173544d8be81SLisandro Dalcin } 173644d8be81SLisandro Dalcin 173770034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 173870034214SMatthew G. Knepley #include <parmetis.h> 173977623264SMatthew G. Knepley #endif 174070034214SMatthew G. Knepley 1741d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 174270034214SMatthew G. Knepley { 174377623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 17445b440754SMatthew G. Knepley PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 174570034214SMatthew G. Knepley MPI_Comm comm; 1746deea36a5SMatthew G. Knepley PetscSection section; 174770034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 174870034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 174970034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 175070034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 175170034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 175270034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 175370034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 175470034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 175570034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 17565b440754SMatthew G. Knepley PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 1757fb83b9f2SMichael Gegg real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 1758fb83b9f2SMichael Gegg real_t *ubvec; /* The balance intolerance for vertex weights */ 1759b3ce585bSLisandro Dalcin PetscInt options[64]; /* Options */ 176070034214SMatthew G. Knepley /* Outputs */ 1761b3ce585bSLisandro Dalcin PetscInt v, i, *assignment, *points; 1762b3ce585bSLisandro Dalcin PetscMPIInt size, rank, p; 176370034214SMatthew G. Knepley PetscErrorCode ierr; 176470034214SMatthew G. Knepley 176570034214SMatthew G. Knepley PetscFunctionBegin; 176677623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 1767b3ce585bSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 176870034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 176970034214SMatthew G. Knepley /* Calculate vertex distribution */ 1770b3ce585bSLisandro Dalcin ierr = PetscMalloc5(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment,nvtxs,&vwgt);CHKERRQ(ierr); 177170034214SMatthew G. Knepley vtxdist[0] = 0; 177270034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1773b3ce585bSLisandro Dalcin for (p = 2; p <= size; ++p) { 177470034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 177570034214SMatthew G. Knepley } 177644d8be81SLisandro Dalcin /* Calculate partition weights */ 177770034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 177870034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 177970034214SMatthew G. Knepley } 17805b440754SMatthew G. Knepley ubvec[0] = pm->imbalanceRatio; 1781deea36a5SMatthew G. Knepley /* Weight cells by dofs on cell by default */ 1782e87a4003SBarry Smith ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 17838ef05d33SStefano Zampini for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1784deea36a5SMatthew G. Knepley if (section) { 1785deea36a5SMatthew G. Knepley PetscInt cStart, cEnd, dof; 178670034214SMatthew G. Knepley 1787925b1076SLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 1788925b1076SLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 17898ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 17908ef05d33SStefano Zampini for (v = cStart; v < cStart + numVertices; ++v) { 17918ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 17928ef05d33SStefano Zampini vwgt[v-cStart] = PetscMax(dof, 1); 1793deea36a5SMatthew G. Knepley } 1794cd0de0f2SShri } 179544d8be81SLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 1796cd0de0f2SShri 179770034214SMatthew G. Knepley if (nparts == 1) { 17989fc93327SToby Isaac ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 179970034214SMatthew G. Knepley } else { 1800b3ce585bSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 1801b3ce585bSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 1802b3ce585bSLisandro Dalcin if (rank == p) { 180344d8be81SLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 180442678178SLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 18059d459c0eSStefano Zampini options[METIS_OPTION_SEED] = pm->randomSeed; 180644d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 180744d8be81SLisandro Dalcin if (metis_ptype == 1) { 180844d8be81SLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 180972379da4SMatthew G. Knepley ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 181044d8be81SLisandro Dalcin PetscStackPop; 181144d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 181244d8be81SLisandro Dalcin } else { 181344d8be81SLisandro Dalcin /* 181444d8be81SLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 181544d8be81SLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 181644d8be81SLisandro 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. 181744d8be81SLisandro Dalcin */ 181844d8be81SLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 181944d8be81SLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 182070034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 182172379da4SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 182270034214SMatthew G. Knepley PetscStackPop; 182370034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 182470034214SMatthew G. Knepley } 182544d8be81SLisandro Dalcin } 182670034214SMatthew G. Knepley } else { 182742678178SLisandro Dalcin options[0] = 1; /*use options */ 18285b440754SMatthew G. Knepley options[1] = pm->debugFlag; 18299d459c0eSStefano Zampini options[2] = (pm->randomSeed == -1) ? 15 : pm->randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 183070034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 183172379da4SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &comm); 183270034214SMatthew G. Knepley PetscStackPop; 1833c717d290SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 183470034214SMatthew G. Knepley } 183570034214SMatthew G. Knepley } 183670034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 183777623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 183877623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 183977623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 184070034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 184177623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 184270034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 184370034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 184470034214SMatthew G. Knepley } 184570034214SMatthew G. Knepley } 184670034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 184770034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1848cd0de0f2SShri ierr = PetscFree5(vtxdist,tpwgts,ubvec,assignment,vwgt);CHKERRQ(ierr); 18499b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 185070034214SMatthew G. Knepley #else 185177623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 185270034214SMatthew G. Knepley #endif 185370034214SMatthew G. Knepley } 185470034214SMatthew G. Knepley 1855d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 185677623264SMatthew G. Knepley { 185777623264SMatthew G. Knepley PetscFunctionBegin; 1858074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 185977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 186044d8be81SLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 186177623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 186277623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 186377623264SMatthew G. Knepley PetscFunctionReturn(0); 186477623264SMatthew G. Knepley } 186577623264SMatthew G. Knepley 186677623264SMatthew G. Knepley /*MC 186777623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 186877623264SMatthew G. Knepley 186977623264SMatthew G. Knepley Level: intermediate 187077623264SMatthew G. Knepley 187177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 187277623264SMatthew G. Knepley M*/ 187377623264SMatthew G. Knepley 187477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 187577623264SMatthew G. Knepley { 187677623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 187777623264SMatthew G. Knepley PetscErrorCode ierr; 187877623264SMatthew G. Knepley 187977623264SMatthew G. Knepley PetscFunctionBegin; 188077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 188177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 188277623264SMatthew G. Knepley part->data = p; 188377623264SMatthew G. Knepley 18845b440754SMatthew G. Knepley p->ptype = 0; 18855b440754SMatthew G. Knepley p->imbalanceRatio = 1.05; 18865b440754SMatthew G. Knepley p->debugFlag = 0; 18879d459c0eSStefano Zampini p->randomSeed = -1; /* defaults to GLOBAL_SEED=15 from `libparmetis/defs.h` */ 18885b440754SMatthew G. Knepley 188977623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 189077623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 189170034214SMatthew G. Knepley PetscFunctionReturn(0); 189270034214SMatthew G. Knepley } 189370034214SMatthew G. Knepley 1894137cd93aSLisandro Dalcin PetscBool PTScotchPartitionercite = PETSC_FALSE; 1895137cd93aSLisandro Dalcin const char PTScotchPartitionerCitation[] = 1896137cd93aSLisandro Dalcin "@article{PTSCOTCH,\n" 1897137cd93aSLisandro Dalcin " author = {C. Chevalier and F. Pellegrini},\n" 1898137cd93aSLisandro Dalcin " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 1899137cd93aSLisandro Dalcin " journal = {Parallel Computing},\n" 1900137cd93aSLisandro Dalcin " volume = {34},\n" 1901137cd93aSLisandro Dalcin " number = {6},\n" 1902137cd93aSLisandro Dalcin " pages = {318--331},\n" 1903137cd93aSLisandro Dalcin " year = {2008},\n" 1904137cd93aSLisandro Dalcin " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 1905137cd93aSLisandro Dalcin "}\n"; 1906137cd93aSLisandro Dalcin 1907137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 1908137cd93aSLisandro Dalcin 1909137cd93aSLisandro Dalcin EXTERN_C_BEGIN 1910137cd93aSLisandro Dalcin #include <ptscotch.h> 1911137cd93aSLisandro Dalcin EXTERN_C_END 1912137cd93aSLisandro Dalcin 1913137cd93aSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 1914137cd93aSLisandro Dalcin 1915137cd93aSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 1916137cd93aSLisandro Dalcin { 1917137cd93aSLisandro Dalcin switch (strategy) { 1918137cd93aSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 1919137cd93aSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 1920137cd93aSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 1921137cd93aSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 1922137cd93aSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 1923137cd93aSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 1924137cd93aSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 1925137cd93aSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 1926137cd93aSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 1927137cd93aSLisandro Dalcin } 1928137cd93aSLisandro Dalcin } 1929137cd93aSLisandro Dalcin 1930137cd93aSLisandro Dalcin 1931137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1932137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[]) 1933137cd93aSLisandro Dalcin { 1934137cd93aSLisandro Dalcin SCOTCH_Graph grafdat; 1935137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1936137cd93aSLisandro Dalcin SCOTCH_Num vertnbr = n; 1937137cd93aSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 1938137cd93aSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 1939137cd93aSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 1940137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1941137cd93aSLisandro Dalcin double kbalval = imbalance; 1942137cd93aSLisandro Dalcin PetscErrorCode ierr; 1943137cd93aSLisandro Dalcin 1944137cd93aSLisandro Dalcin PetscFunctionBegin; 1945d99a0000SVaclav Hapla { 1946d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1947d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1948d99a0000SVaclav Hapla if (!flg) velotab = NULL; 1949d99a0000SVaclav Hapla } 1950137cd93aSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 1951137cd93aSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 1952137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1953137cd93aSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 1954137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1955137cd93aSLisandro Dalcin ierr = SCOTCH_graphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1956137cd93aSLisandro Dalcin #endif 1957137cd93aSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 1958137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 1959137cd93aSLisandro Dalcin SCOTCH_graphExit(&grafdat); 1960137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1961137cd93aSLisandro Dalcin } 1962137cd93aSLisandro Dalcin 1963137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1964137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[], MPI_Comm comm) 1965137cd93aSLisandro Dalcin { 1966137cd93aSLisandro Dalcin PetscMPIInt procglbnbr; 1967137cd93aSLisandro Dalcin PetscMPIInt proclocnum; 1968137cd93aSLisandro Dalcin SCOTCH_Arch archdat; 1969137cd93aSLisandro Dalcin SCOTCH_Dgraph grafdat; 1970137cd93aSLisandro Dalcin SCOTCH_Dmapping mappdat; 1971137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1972137cd93aSLisandro Dalcin SCOTCH_Num vertlocnbr; 1973137cd93aSLisandro Dalcin SCOTCH_Num edgelocnbr; 1974137cd93aSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 1975137cd93aSLisandro Dalcin SCOTCH_Num* edloloctab = 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) veloloctab = NULL; 1985d99a0000SVaclav Hapla } 1986137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 1987137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 1988137cd93aSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 1989137cd93aSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 1990137cd93aSLisandro Dalcin 1991137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 1992137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 1993137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1994137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1995137cd93aSLisandro Dalcin #endif 1996137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1997137cd93aSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 1998137cd93aSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 1999137cd93aSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 2000137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 2001cb87ef4cSFlorian Wechsung 2002137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 2003137cd93aSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 2004137cd93aSLisandro Dalcin SCOTCH_archExit(&archdat); 2005137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 2006137cd93aSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 2007137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2008137cd93aSLisandro Dalcin } 2009137cd93aSLisandro Dalcin 2010137cd93aSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 2011137cd93aSLisandro Dalcin 2012137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 2013137cd93aSLisandro Dalcin { 2014137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2015137cd93aSLisandro Dalcin PetscErrorCode ierr; 2016137cd93aSLisandro Dalcin 2017137cd93aSLisandro Dalcin PetscFunctionBegin; 2018137cd93aSLisandro Dalcin ierr = PetscFree(p);CHKERRQ(ierr); 2019137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2020137cd93aSLisandro Dalcin } 2021137cd93aSLisandro Dalcin 2022137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_Ascii(PetscPartitioner part, PetscViewer viewer) 2023137cd93aSLisandro Dalcin { 2024137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2025137cd93aSLisandro Dalcin PetscErrorCode ierr; 2026137cd93aSLisandro Dalcin 2027137cd93aSLisandro Dalcin PetscFunctionBegin; 2028137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2029137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 2030137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 2031137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2032137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2033137cd93aSLisandro Dalcin } 2034137cd93aSLisandro Dalcin 2035137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 2036137cd93aSLisandro Dalcin { 2037137cd93aSLisandro Dalcin PetscBool iascii; 2038137cd93aSLisandro Dalcin PetscErrorCode ierr; 2039137cd93aSLisandro Dalcin 2040137cd93aSLisandro Dalcin PetscFunctionBegin; 2041137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2042137cd93aSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2043137cd93aSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 2044137cd93aSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_Ascii(part, viewer);CHKERRQ(ierr);} 2045137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2046137cd93aSLisandro Dalcin } 2047137cd93aSLisandro Dalcin 2048137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 2049137cd93aSLisandro Dalcin { 2050137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2051137cd93aSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 2052137cd93aSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 2053137cd93aSLisandro Dalcin PetscBool flag; 2054137cd93aSLisandro Dalcin PetscErrorCode ierr; 2055137cd93aSLisandro Dalcin 2056137cd93aSLisandro Dalcin PetscFunctionBegin; 2057137cd93aSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 2058137cd93aSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 2059137cd93aSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 2060137cd93aSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 2061137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2062137cd93aSLisandro Dalcin } 2063137cd93aSLisandro Dalcin 2064137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 2065137cd93aSLisandro Dalcin { 2066137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 2067137cd93aSLisandro Dalcin MPI_Comm comm = PetscObjectComm((PetscObject)part); 2068137cd93aSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 2069137cd93aSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 2070137cd93aSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 2071137cd93aSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 2072137cd93aSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 2073137cd93aSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 2074137cd93aSLisandro Dalcin PetscInt v, i, *assignment, *points; 2075137cd93aSLisandro Dalcin PetscMPIInt size, rank, p; 2076137cd93aSLisandro Dalcin PetscErrorCode ierr; 2077137cd93aSLisandro Dalcin 2078137cd93aSLisandro Dalcin PetscFunctionBegin; 2079137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2080137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 208199b53901SStefano Zampini ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 2082137cd93aSLisandro Dalcin 2083137cd93aSLisandro Dalcin /* Calculate vertex distribution */ 2084137cd93aSLisandro Dalcin vtxdist[0] = 0; 2085137cd93aSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2086137cd93aSLisandro Dalcin for (p = 2; p <= size; ++p) { 2087137cd93aSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 2088137cd93aSLisandro Dalcin } 2089137cd93aSLisandro Dalcin 2090137cd93aSLisandro Dalcin if (nparts == 1) { 2091137cd93aSLisandro Dalcin ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 20928ef05d33SStefano Zampini } else { /* Weight cells by dofs on cell by default */ 2093137cd93aSLisandro Dalcin PetscSection section; 20948ef05d33SStefano Zampini 2095137cd93aSLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 2096137cd93aSLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 20978ef05d33SStefano Zampini ierr = PetscMalloc1(PetscMax(nvtxs,1),&vwgt);CHKERRQ(ierr); 20988ef05d33SStefano Zampini for (v = 0; v < PetscMax(nvtxs,1); ++v) vwgt[v] = 1; 20998ef05d33SStefano Zampini ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 21008ef05d33SStefano Zampini if (section) { 21018ef05d33SStefano Zampini PetscInt vStart, vEnd, dof; 21028ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &vStart, &vEnd);CHKERRQ(ierr); 21038ef05d33SStefano Zampini for (v = vStart; v < vStart + numVertices; ++v) { 21048ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 21058ef05d33SStefano Zampini vwgt[v-vStart] = PetscMax(dof, 1); 2106137cd93aSLisandro Dalcin } 2107137cd93aSLisandro Dalcin } 2108137cd93aSLisandro Dalcin { 2109137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 2110137cd93aSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 2111137cd93aSLisandro Dalcin double imbal = (double)pts->imbalance; 2112137cd93aSLisandro Dalcin 2113137cd93aSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 2114137cd93aSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 2115137cd93aSLisandro Dalcin if (rank == p) { 2116137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, assignment);CHKERRQ(ierr); 2117137cd93aSLisandro Dalcin } 2118137cd93aSLisandro Dalcin } else { 2119137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, assignment, comm);CHKERRQ(ierr); 2120137cd93aSLisandro Dalcin } 2121137cd93aSLisandro Dalcin } 2122137cd93aSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 2123137cd93aSLisandro Dalcin } 2124137cd93aSLisandro Dalcin 2125137cd93aSLisandro Dalcin /* Convert to PetscSection+IS */ 2126137cd93aSLisandro Dalcin ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 2127137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 2128137cd93aSLisandro Dalcin ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 2129137cd93aSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 2130137cd93aSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 2131137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 2132137cd93aSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 2133137cd93aSLisandro Dalcin } 2134137cd93aSLisandro Dalcin } 2135137cd93aSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2136137cd93aSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2137137cd93aSLisandro Dalcin 2138137cd93aSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 2139137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2140137cd93aSLisandro Dalcin #else 2141137cd93aSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 2142137cd93aSLisandro Dalcin #endif 2143137cd93aSLisandro Dalcin } 2144137cd93aSLisandro Dalcin 2145137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 2146137cd93aSLisandro Dalcin { 2147137cd93aSLisandro Dalcin PetscFunctionBegin; 2148074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 2149137cd93aSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 2150137cd93aSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 2151137cd93aSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 2152137cd93aSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 2153137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2154137cd93aSLisandro Dalcin } 2155137cd93aSLisandro Dalcin 2156137cd93aSLisandro Dalcin /*MC 2157137cd93aSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 2158137cd93aSLisandro Dalcin 2159137cd93aSLisandro Dalcin Level: intermediate 2160137cd93aSLisandro Dalcin 2161137cd93aSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 2162137cd93aSLisandro Dalcin M*/ 2163137cd93aSLisandro Dalcin 2164137cd93aSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 2165137cd93aSLisandro Dalcin { 2166137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p; 2167137cd93aSLisandro Dalcin PetscErrorCode ierr; 2168137cd93aSLisandro Dalcin 2169137cd93aSLisandro Dalcin PetscFunctionBegin; 2170137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2171137cd93aSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 2172137cd93aSLisandro Dalcin part->data = p; 2173137cd93aSLisandro Dalcin 2174137cd93aSLisandro Dalcin p->strategy = 0; 2175137cd93aSLisandro Dalcin p->imbalance = 0.01; 2176137cd93aSLisandro Dalcin 2177137cd93aSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 2178137cd93aSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionercite);CHKERRQ(ierr); 2179137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2180137cd93aSLisandro Dalcin } 2181137cd93aSLisandro Dalcin 2182137cd93aSLisandro Dalcin 21835680f57bSMatthew G. Knepley /*@ 21845680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 21855680f57bSMatthew G. Knepley 21865680f57bSMatthew G. Knepley Not collective 21875680f57bSMatthew G. Knepley 21885680f57bSMatthew G. Knepley Input Parameter: 21895680f57bSMatthew G. Knepley . dm - The DM 21905680f57bSMatthew G. Knepley 21915680f57bSMatthew G. Knepley Output Parameter: 21925680f57bSMatthew G. Knepley . part - The PetscPartitioner 21935680f57bSMatthew G. Knepley 21945680f57bSMatthew G. Knepley Level: developer 21955680f57bSMatthew G. Knepley 219698599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 219798599a47SLawrence Mitchell 219898599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 21995680f57bSMatthew G. Knepley @*/ 22005680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 22015680f57bSMatthew G. Knepley { 22025680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 22035680f57bSMatthew G. Knepley 22045680f57bSMatthew G. Knepley PetscFunctionBegin; 22055680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22065680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 22075680f57bSMatthew G. Knepley *part = mesh->partitioner; 22085680f57bSMatthew G. Knepley PetscFunctionReturn(0); 22095680f57bSMatthew G. Knepley } 22105680f57bSMatthew G. Knepley 221171bb2955SLawrence Mitchell /*@ 221271bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 221371bb2955SLawrence Mitchell 221471bb2955SLawrence Mitchell logically collective on dm and part 221571bb2955SLawrence Mitchell 221671bb2955SLawrence Mitchell Input Parameters: 221771bb2955SLawrence Mitchell + dm - The DM 221871bb2955SLawrence Mitchell - part - The partitioner 221971bb2955SLawrence Mitchell 222071bb2955SLawrence Mitchell Level: developer 222171bb2955SLawrence Mitchell 222271bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 222371bb2955SLawrence Mitchell 222471bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 222571bb2955SLawrence Mitchell @*/ 222671bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 222771bb2955SLawrence Mitchell { 222871bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 222971bb2955SLawrence Mitchell PetscErrorCode ierr; 223071bb2955SLawrence Mitchell 223171bb2955SLawrence Mitchell PetscFunctionBegin; 223271bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 223371bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 223471bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 223571bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 223671bb2955SLawrence Mitchell mesh->partitioner = part; 223771bb2955SLawrence Mitchell PetscFunctionReturn(0); 223871bb2955SLawrence Mitchell } 223971bb2955SLawrence Mitchell 2240e8f14785SLisandro Dalcin static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 2241270bba0cSToby Isaac { 2242270bba0cSToby Isaac PetscErrorCode ierr; 2243270bba0cSToby Isaac 2244270bba0cSToby Isaac PetscFunctionBegin; 22456a5a2ffdSToby Isaac if (up) { 22466a5a2ffdSToby Isaac PetscInt parent; 22476a5a2ffdSToby Isaac 2248270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 22496a5a2ffdSToby Isaac if (parent != point) { 22506a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 22516a5a2ffdSToby Isaac 2252270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2253270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 2254270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 2255270bba0cSToby Isaac 2256e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 22571b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 2258270bba0cSToby Isaac } 2259270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 22606a5a2ffdSToby Isaac } 22616a5a2ffdSToby Isaac } 22626a5a2ffdSToby Isaac if (down) { 22636a5a2ffdSToby Isaac PetscInt numChildren; 22646a5a2ffdSToby Isaac const PetscInt *children; 22656a5a2ffdSToby Isaac 22666a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 22676a5a2ffdSToby Isaac if (numChildren) { 22686a5a2ffdSToby Isaac PetscInt i; 22696a5a2ffdSToby Isaac 22706a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 22716a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 22726a5a2ffdSToby Isaac 2273e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 22741b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 22756a5a2ffdSToby Isaac } 22766a5a2ffdSToby Isaac } 22776a5a2ffdSToby Isaac } 2278270bba0cSToby Isaac PetscFunctionReturn(0); 2279270bba0cSToby Isaac } 2280270bba0cSToby Isaac 2281825f8a23SLisandro Dalcin PETSC_INTERN PetscErrorCode DMPlexPartitionLabelClosure_Private(DM,DMLabel,PetscInt,PetscInt,const PetscInt[],IS*); 2282825f8a23SLisandro Dalcin 2283825f8a23SLisandro Dalcin PetscErrorCode DMPlexPartitionLabelClosure_Private(DM dm, DMLabel label, PetscInt rank, PetscInt numPoints, const PetscInt points[], IS *closureIS) 2284825f8a23SLisandro Dalcin { 2285825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 2286825f8a23SLisandro Dalcin PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 2287825f8a23SLisandro Dalcin PetscInt *closure = NULL, closureSize, nelems, *elems, off = 0, p, c; 2288825f8a23SLisandro Dalcin PetscHSetI ht; 2289825f8a23SLisandro Dalcin PetscErrorCode ierr; 2290825f8a23SLisandro Dalcin 2291825f8a23SLisandro Dalcin PetscFunctionBegin; 2292825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 2293825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 2294825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 2295825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2296825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 2297825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 2298825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 2299825f8a23SLisandro Dalcin } 2300825f8a23SLisandro Dalcin } 2301825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 2302825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 2303825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 2304825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 2305825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 2306825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 2307825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 2308825f8a23SLisandro Dalcin PetscFunctionReturn(0); 2309825f8a23SLisandro Dalcin } 2310825f8a23SLisandro Dalcin 23115abbe4feSMichael Lange /*@ 23125abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 23135abbe4feSMichael Lange 23145abbe4feSMichael Lange Input Parameters: 23155abbe4feSMichael Lange + dm - The DM 23165abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 23175abbe4feSMichael Lange 23185abbe4feSMichael Lange Level: developer 23195abbe4feSMichael Lange 23205abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 23215abbe4feSMichael Lange @*/ 23225abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 23239ffc88e4SToby Isaac { 2324825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 23255abbe4feSMichael Lange const PetscInt *ranks, *points; 2326825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 23279ffc88e4SToby Isaac PetscErrorCode ierr; 23289ffc88e4SToby Isaac 23299ffc88e4SToby Isaac PetscFunctionBegin; 23305abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 23315abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 23325abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 23335abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 23345abbe4feSMichael Lange const PetscInt rank = ranks[r]; 23355abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 23365abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 23375abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2338825f8a23SLisandro Dalcin ierr = DMPlexPartitionLabelClosure_Private(dm, label, rank, numPoints, points, &closureIS);CHKERRQ(ierr); 23395abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 23405abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2341825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 2342825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 23439ffc88e4SToby Isaac } 23445abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 23455abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 23469ffc88e4SToby Isaac PetscFunctionReturn(0); 23479ffc88e4SToby Isaac } 23489ffc88e4SToby Isaac 234924d039d7SMichael Lange /*@ 235024d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 235124d039d7SMichael Lange 235224d039d7SMichael Lange Input Parameters: 235324d039d7SMichael Lange + dm - The DM 235424d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 235524d039d7SMichael Lange 235624d039d7SMichael Lange Level: developer 235724d039d7SMichael Lange 235824d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 235924d039d7SMichael Lange @*/ 236024d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 236170034214SMatthew G. Knepley { 236224d039d7SMichael Lange IS rankIS, pointIS; 236324d039d7SMichael Lange const PetscInt *ranks, *points; 236424d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 236524d039d7SMichael Lange PetscInt *adj = NULL; 236670034214SMatthew G. Knepley PetscErrorCode ierr; 236770034214SMatthew G. Knepley 236870034214SMatthew G. Knepley PetscFunctionBegin; 236924d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 237024d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 237124d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 237224d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 237324d039d7SMichael Lange const PetscInt rank = ranks[r]; 237470034214SMatthew G. Knepley 237524d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 237624d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 237724d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 237870034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 237924d039d7SMichael Lange adjSize = PETSC_DETERMINE; 238024d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 238124d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 238270034214SMatthew G. Knepley } 238324d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 238424d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 238570034214SMatthew G. Knepley } 238624d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 238724d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 238824d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 238924d039d7SMichael Lange PetscFunctionReturn(0); 239070034214SMatthew G. Knepley } 239170034214SMatthew G. Knepley 2392be200f8dSMichael Lange /*@ 2393be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 2394be200f8dSMichael Lange 2395be200f8dSMichael Lange Input Parameters: 2396be200f8dSMichael Lange + dm - The DM 2397be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 2398be200f8dSMichael Lange 2399be200f8dSMichael Lange Level: developer 2400be200f8dSMichael Lange 2401be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 2402be200f8dSMichael Lange overlap points from non-neighbouring partitions. 2403be200f8dSMichael Lange 2404be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 2405be200f8dSMichael Lange @*/ 2406be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 2407be200f8dSMichael Lange { 2408be200f8dSMichael Lange MPI_Comm comm; 2409be200f8dSMichael Lange PetscMPIInt rank; 2410be200f8dSMichael Lange PetscSF sfPoint; 24115d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 2412be200f8dSMichael Lange IS rankIS, pointIS; 2413be200f8dSMichael Lange const PetscInt *ranks; 2414be200f8dSMichael Lange PetscInt numRanks, r; 2415be200f8dSMichael Lange PetscErrorCode ierr; 2416be200f8dSMichael Lange 2417be200f8dSMichael Lange PetscFunctionBegin; 2418be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2419be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2420be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 24215d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 24225d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 24235d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 24245d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 24255d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 24265d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 24275d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 24285d04f6ebSMichael Lange if (remoteRank == rank) continue; 24295d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 24305d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 24315d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 24325d04f6ebSMichael Lange } 24335d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 24345d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 24355d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 2436be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 2437be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 2438be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 2439be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 2440be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 2441be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 2442be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 2443be200f8dSMichael Lange if (remoteRank == rank) continue; 2444be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 2445be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 2446be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2447be200f8dSMichael Lange } 2448be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 2449be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 2450be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 2451be200f8dSMichael Lange PetscFunctionReturn(0); 2452be200f8dSMichael Lange } 2453be200f8dSMichael Lange 24541fd9873aSMichael Lange /*@ 24551fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 24561fd9873aSMichael Lange 24571fd9873aSMichael Lange Input Parameters: 24581fd9873aSMichael Lange + dm - The DM 24591fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 24601fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 24611fd9873aSMichael Lange 24621fd9873aSMichael Lange Output Parameter: 24631fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 24641fd9873aSMichael Lange 24651fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 24661fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 24671fd9873aSMichael Lange 24681fd9873aSMichael Lange Level: developer 24691fd9873aSMichael Lange 24701fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 24711fd9873aSMichael Lange @*/ 24721fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 24731fd9873aSMichael Lange { 24741fd9873aSMichael Lange MPI_Comm comm; 2475874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 2476874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 24771fd9873aSMichael Lange PetscSF sfPoint; 2478874ddda9SLisandro Dalcin PetscSection rootSection; 24791fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 24801fd9873aSMichael Lange const PetscSFNode *remote; 24811fd9873aSMichael Lange const PetscInt *local, *neighbors; 24821fd9873aSMichael Lange IS valueIS; 2483874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 24841fd9873aSMichael Lange PetscErrorCode ierr; 24851fd9873aSMichael Lange 24861fd9873aSMichael Lange PetscFunctionBegin; 24871fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 24881fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 24899852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 24901fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 24911fd9873aSMichael Lange 24921fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 24931fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 24949852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 24951fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 24961fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 24971fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 24981fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 24991fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 25001fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 25011fd9873aSMichael Lange } 25021fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 2503874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 2504874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 25051fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 25061fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 25071fd9873aSMichael Lange IS pointIS; 25081fd9873aSMichael Lange const PetscInt *points; 25091fd9873aSMichael Lange 25101fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 25111fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 25121fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 25131fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 25141fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 2515f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 2516f8987ae8SMichael Lange else {l = -1;} 25171fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 25181fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 25191fd9873aSMichael Lange } 25201fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 25211fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 25221fd9873aSMichael Lange } 2523874ddda9SLisandro Dalcin 2524874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 2525874ddda9SLisandro Dalcin if (!processSF) { 2526874ddda9SLisandro Dalcin PetscInt64 counter = 0; 2527874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 2528874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 2529874ddda9SLisandro Dalcin 2530874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 2531874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 2532874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 2533874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 2534874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 2535874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2536874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2537874ddda9SLisandro Dalcin #endif 2538874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 2539874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 2540874ddda9SLisandro Dalcin } 2541874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 2542874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 2543874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 2544874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 2545874ddda9SLisandro Dalcin if (!mpiOverflow) { 2546874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 2547874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 2548874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 2549874ddda9SLisandro Dalcin } 2550874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 2551874ddda9SLisandro Dalcin } 2552874ddda9SLisandro Dalcin 2553874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 2554874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 2555874ddda9SLisandro Dalcin PetscSF procSF; 2556874ddda9SLisandro Dalcin PetscSFNode *remote; 2557874ddda9SLisandro Dalcin PetscSection leafSection; 2558874ddda9SLisandro Dalcin 2559874ddda9SLisandro Dalcin if (processSF) { 2560874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 2561874ddda9SLisandro Dalcin procSF = processSF; 2562874ddda9SLisandro Dalcin } else { 2563874ddda9SLisandro Dalcin ierr = PetscMalloc1(size, &remote);CHKERRQ(ierr); 2564874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { remote[r].rank = r; remote[r].index = rank; } 2565874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm, &procSF);CHKERRQ(ierr); 2566874ddda9SLisandro Dalcin ierr = PetscSFSetGraph(procSF, size, size, NULL, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 2567874ddda9SLisandro Dalcin } 2568874ddda9SLisandro Dalcin 2569874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 25701fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 2571874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 2572874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 2573874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 2574874ddda9SLisandro Dalcin } 2575874ddda9SLisandro Dalcin 2576874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 25771fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 25781fd9873aSMichael Lange } 2579874ddda9SLisandro Dalcin 2580874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 2581874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 25821fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 2583874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 25841fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 25851fd9873aSMichael Lange PetscFunctionReturn(0); 25861fd9873aSMichael Lange } 25871fd9873aSMichael Lange 2588aa3148a8SMichael Lange /*@ 2589aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 2590aa3148a8SMichael Lange 2591aa3148a8SMichael Lange Input Parameters: 2592aa3148a8SMichael Lange + dm - The DM 2593aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 2594aa3148a8SMichael Lange 2595aa3148a8SMichael Lange Output Parameter: 2596aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 2597aa3148a8SMichael Lange 2598aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 2599aa3148a8SMichael Lange 2600aa3148a8SMichael Lange Level: developer 2601aa3148a8SMichael Lange 2602aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 2603aa3148a8SMichael Lange @*/ 2604aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 2605aa3148a8SMichael Lange { 26069852e123SBarry Smith PetscMPIInt rank, size; 260743f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 2608aa3148a8SMichael Lange PetscSFNode *remotePoints; 260943f7d02bSMichael Lange IS remoteRootIS; 261043f7d02bSMichael Lange const PetscInt *remoteRoots; 2611aa3148a8SMichael Lange PetscErrorCode ierr; 2612aa3148a8SMichael Lange 2613aa3148a8SMichael Lange PetscFunctionBegin; 261443f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 26159852e123SBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr); 2616aa3148a8SMichael Lange 26179852e123SBarry Smith for (numRemote = 0, n = 0; n < size; ++n) { 2618aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 2619aa3148a8SMichael Lange numRemote += numPoints; 2620aa3148a8SMichael Lange } 2621aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 262243f7d02bSMichael Lange /* Put owned points first */ 262343f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 262443f7d02bSMichael Lange if (numPoints > 0) { 262543f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 262643f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 262743f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 262843f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 262943f7d02bSMichael Lange remotePoints[idx].rank = rank; 263043f7d02bSMichael Lange idx++; 263143f7d02bSMichael Lange } 263243f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 263343f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 263443f7d02bSMichael Lange } 263543f7d02bSMichael Lange /* Now add remote points */ 26369852e123SBarry Smith for (n = 0; n < size; ++n) { 2637aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 263843f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 2639aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 2640aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2641aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 2642aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 2643aa3148a8SMichael Lange remotePoints[idx].rank = n; 2644aa3148a8SMichael Lange idx++; 2645aa3148a8SMichael Lange } 2646aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2647aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 2648aa3148a8SMichael Lange } 2649aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 2650aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2651aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 265270034214SMatthew G. Knepley PetscFunctionReturn(0); 265370034214SMatthew G. Knepley } 2654cb87ef4cSFlorian Wechsung 26556a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 26566a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 26576a3739e5SFlorian Wechsung * them out in that case. */ 26586a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 26597a82c785SFlorian Wechsung /*@C 26607f57c1a4SFlorian Wechsung 26617f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 26627f57c1a4SFlorian Wechsung 26637f57c1a4SFlorian Wechsung Input parameters: 26647f57c1a4SFlorian Wechsung + dm - The DMPlex object. 26657f57c1a4SFlorian Wechsung + n - The number of points. 26667f57c1a4SFlorian Wechsung + pointsToRewrite - The points in the SF whose ownership will change. 26677f57c1a4SFlorian Wechsung + targetOwners - New owner for each element in pointsToRewrite. 26687f57c1a4SFlorian Wechsung + degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 26697f57c1a4SFlorian Wechsung 26707f57c1a4SFlorian Wechsung Level: developer 26717f57c1a4SFlorian Wechsung 26727f57c1a4SFlorian Wechsung @*/ 26737f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 26747f57c1a4SFlorian Wechsung { 26757f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 26767f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 26777f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 26787f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 26797f57c1a4SFlorian Wechsung const PetscInt *ilocal; 26807f57c1a4SFlorian Wechsung PetscBool *isLeaf; 26817f57c1a4SFlorian Wechsung PetscSF sf; 26827f57c1a4SFlorian Wechsung MPI_Comm comm; 26835a30b08bSFlorian Wechsung PetscMPIInt rank, size; 26847f57c1a4SFlorian Wechsung 26857f57c1a4SFlorian Wechsung PetscFunctionBegin; 26867f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 26877f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 26887f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 26897f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 26907f57c1a4SFlorian Wechsung 26917f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 26927f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 26937f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 26947f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 26957f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 26967f57c1a4SFlorian Wechsung } 26977f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 26987f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 26997f57c1a4SFlorian Wechsung } 27007f57c1a4SFlorian Wechsung 27017f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 27027f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 27037f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 27047f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 27057f57c1a4SFlorian Wechsung } 27067f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 27077f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 27087f57c1a4SFlorian Wechsung 27097f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 27107f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 27117f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27127f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 27137f57c1a4SFlorian Wechsung } 27147f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 27157f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 27167f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 27177f57c1a4SFlorian Wechsung 27187f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 27197f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 27207f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 27217f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27227f57c1a4SFlorian Wechsung points[i] = pStart+i; 27237f57c1a4SFlorian Wechsung } 27247f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 27257f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 27267f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 27277f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 27287f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 27297f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 27307f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27317f57c1a4SFlorian Wechsung newOwners[i] = -1; 27327f57c1a4SFlorian Wechsung newNumbers[i] = -1; 27337f57c1a4SFlorian Wechsung } 27347f57c1a4SFlorian Wechsung { 27357f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 27367f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 27377f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 27387f57c1a4SFlorian Wechsung newNumber = -1; 27397f57c1a4SFlorian Wechsung oldOwner = rank; 27407f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 27417f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 27427f57c1a4SFlorian Wechsung newNumber = oldNumber; 27437f57c1a4SFlorian Wechsung } else { 27447f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 27457f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 27467f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 27477f57c1a4SFlorian Wechsung break; 27487f57c1a4SFlorian Wechsung } 27497f57c1a4SFlorian Wechsung } 27507f57c1a4SFlorian Wechsung } 27517f57c1a4SFlorian Wechsung if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 27527f57c1a4SFlorian Wechsung 27537f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 27547f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 27557f57c1a4SFlorian Wechsung } 27567f57c1a4SFlorian Wechsung } 27577f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 27587f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 27597f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 27607f57c1a4SFlorian Wechsung 27617f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 27627f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 27637f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 27647f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 27657f57c1a4SFlorian Wechsung 27667f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 27677f57c1a4SFlorian Wechsung leafCounter=0; 27687f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27697f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 27707f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 27717f57c1a4SFlorian Wechsung leafCounter++; 27727f57c1a4SFlorian Wechsung } 27737f57c1a4SFlorian Wechsung } else { 27747f57c1a4SFlorian Wechsung if (isLeaf[i]) { 27757f57c1a4SFlorian Wechsung leafCounter++; 27767f57c1a4SFlorian Wechsung } 27777f57c1a4SFlorian Wechsung } 27787f57c1a4SFlorian Wechsung } 27797f57c1a4SFlorian Wechsung 27807f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 27817f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 27827f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 27837f57c1a4SFlorian Wechsung 27847f57c1a4SFlorian Wechsung leafCounter = 0; 27857f57c1a4SFlorian Wechsung counter = 0; 27867f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27877f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 27887f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 27897f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 27907f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 27917f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 27927f57c1a4SFlorian Wechsung leafCounter++; 27937f57c1a4SFlorian Wechsung } 27947f57c1a4SFlorian Wechsung } else { 27957f57c1a4SFlorian Wechsung if (isLeaf[i]) { 27967f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 27977f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 27987f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 27997f57c1a4SFlorian Wechsung leafCounter++; 28007f57c1a4SFlorian Wechsung } 28017f57c1a4SFlorian Wechsung } 28027f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28037f57c1a4SFlorian Wechsung counter++; 28047f57c1a4SFlorian Wechsung } 28057f57c1a4SFlorian Wechsung } 28067f57c1a4SFlorian Wechsung 28077f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 28087f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 28097f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 28107f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 28117f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 28127f57c1a4SFlorian Wechsung } 28137f57c1a4SFlorian Wechsung 2814125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 2815125d2a8fSFlorian Wechsung { 28165a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 28175a30b08bSFlorian Wechsung PetscMPIInt rank, size; 2818125d2a8fSFlorian Wechsung PetscFunctionBegin; 2819125d2a8fSFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2820125d2a8fSFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2821125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 2822125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 2823125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 2824125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 2825125d2a8fSFlorian Wechsung } 2826125d2a8fSFlorian Wechsung ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 2827125d2a8fSFlorian Wechsung min = distribution[0]; 2828125d2a8fSFlorian Wechsung max = distribution[0]; 2829125d2a8fSFlorian Wechsung sum = distribution[0]; 2830125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 2831125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 2832125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 2833125d2a8fSFlorian Wechsung sum += distribution[i]; 2834125d2a8fSFlorian Wechsung } 2835125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 2836125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 2837125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 2838125d2a8fSFlorian Wechsung } 2839125d2a8fSFlorian Wechsung 28406a3739e5SFlorian Wechsung #endif 28416a3739e5SFlorian Wechsung 2842cb87ef4cSFlorian Wechsung /*@ 28435dc86ac1SFlorian 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. 2844cb87ef4cSFlorian Wechsung 2845cb87ef4cSFlorian Wechsung Input parameters: 2846ed44d270SFlorian Wechsung + dm - The DMPlex object. 28477f57c1a4SFlorian Wechsung + entityDepth - depth of the entity to balance (0 -> balance vertices). 28487f57c1a4SFlorian Wechsung + useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 28497f57c1a4SFlorian 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. 2850cb87ef4cSFlorian Wechsung 28518b879b41SFlorian Wechsung Output parameters: 28528b879b41SFlorian Wechsung + success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 28538b879b41SFlorian Wechsung 2854cb87ef4cSFlorian Wechsung Level: user 2855cb87ef4cSFlorian Wechsung 2856cb87ef4cSFlorian Wechsung @*/ 2857cb87ef4cSFlorian Wechsung 28588b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 2859cb87ef4cSFlorian Wechsung { 286041525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 2861cb87ef4cSFlorian Wechsung PetscSF sf; 28620faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 28637f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 28647f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 28657f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 2866cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 2867cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 2868cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 28697f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 28705dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 2871cb87ef4cSFlorian Wechsung PetscInt offset, counter; 28727f57c1a4SFlorian Wechsung PetscInt lenadjncy; 2873cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 2874cb87ef4cSFlorian Wechsung PetscInt lenxadj; 2875cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 2876cb87ef4cSFlorian Wechsung PetscInt *part, *options; 2877cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 2878cb87ef4cSFlorian Wechsung real_t *ubvec; 2879cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 2880cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 2881cb87ef4cSFlorian Wechsung MPI_Comm comm; 28824baf1206SFlorian Wechsung Mat A, Apre; 288312617df9SFlorian Wechsung const char *prefix = NULL; 28847d197802SFlorian Wechsung PetscViewer viewer; 28857d197802SFlorian Wechsung PetscViewerFormat format; 28865a30b08bSFlorian Wechsung PetscLayout layout; 288712617df9SFlorian Wechsung 288812617df9SFlorian Wechsung PetscFunctionBegin; 28898b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 28907f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 28917f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 28927f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 28937f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 28947f57c1a4SFlorian Wechsung 289541525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 289641525646SFlorian Wechsung 28975a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 28985dc86ac1SFlorian Wechsung if (viewer) { 28995a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 29007d197802SFlorian Wechsung } 29017d197802SFlorian Wechsung 2902ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 2903d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 2904cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2905cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 2906cf818975SFlorian Wechsung 2907cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 29085a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 2909cb87ef4cSFlorian Wechsung } 2910cb87ef4cSFlorian Wechsung 2911cf818975SFlorian Wechsung /* There are three types of points: 2912cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 2913cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 2914cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 2915cf818975SFlorian Wechsung */ 2916cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 2917cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 2918cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 2919cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 2920cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 2921cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2922cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 2923cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 2924cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 2925cb87ef4cSFlorian Wechsung } 2926cf818975SFlorian Wechsung 2927cf818975SFlorian Wechsung /* start by marking all the leafs */ 2928cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 2929cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 2930cb87ef4cSFlorian Wechsung } 2931cb87ef4cSFlorian Wechsung 2932cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 2933cf818975SFlorian Wechsung * not by calculating its degree */ 29347f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 29357f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 2936cf818975SFlorian Wechsung 2937cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 2938cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 2939cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2940cb87ef4cSFlorian Wechsung if (toBalance[i]) { 29417f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 2942cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 2943cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 2944cb87ef4cSFlorian Wechsung } else { 2945cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 2946cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 2947cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 2948cb87ef4cSFlorian Wechsung } 2949cb87ef4cSFlorian Wechsung } 2950cb87ef4cSFlorian Wechsung } 2951cb87ef4cSFlorian Wechsung } 2952cb87ef4cSFlorian Wechsung 2953cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 2954cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 2955cf818975SFlorian Wechsung * point. */ 2956cb87ef4cSFlorian Wechsung 29575dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 29585dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 29595dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 29605dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 29615dc86ac1SFlorian Wechsung 2962cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 2963cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 2964cb87ef4cSFlorian Wechsung counter = 0; 2965cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 2966cb87ef4cSFlorian Wechsung if (toBalance[i]) { 29677f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 2968cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 2969cb87ef4cSFlorian Wechsung counter++; 2970cb87ef4cSFlorian Wechsung } 2971cb87ef4cSFlorian Wechsung } 2972cb87ef4cSFlorian Wechsung } 2973cb87ef4cSFlorian Wechsung 2974cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 2975cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 2976cb87ef4cSFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 2977cb87ef4cSFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 2978cb87ef4cSFlorian Wechsung 29790faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 2980cb87ef4cSFlorian Wechsung 29814baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 29824baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 29834baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 29844baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 29858c9a1619SFlorian Wechsung 29868c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 29878c9a1619SFlorian Wechsung if (toBalance[i]) { 29880faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 29890faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 29900faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 29910faf6628SFlorian Wechsung else continue; 29920faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 29930faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 29944baf1206SFlorian Wechsung } 29954baf1206SFlorian Wechsung } 29964baf1206SFlorian Wechsung 29974baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 29984baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 29994baf1206SFlorian Wechsung 30004baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 30014baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 30024baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 30034baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 30044baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 30054baf1206SFlorian Wechsung 30064baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 30074baf1206SFlorian Wechsung if (toBalance[i]) { 30080faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 30090faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 30100faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 30110faf6628SFlorian Wechsung else continue; 30120faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 30130faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 30140941debbSFlorian Wechsung } 30150941debbSFlorian Wechsung } 30168c9a1619SFlorian Wechsung 30178c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30188c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30194baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 30204baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 30214baf1206SFlorian Wechsung 302241525646SFlorian Wechsung nparts = size; 302341525646SFlorian Wechsung wgtflag = 2; 302441525646SFlorian Wechsung numflag = 0; 302541525646SFlorian Wechsung ncon = 2; 302641525646SFlorian Wechsung real_t *tpwgts; 302741525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 302841525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 302941525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 303041525646SFlorian Wechsung } 303141525646SFlorian Wechsung 303241525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 303341525646SFlorian Wechsung ubvec[0] = 1.01; 30345a30b08bSFlorian Wechsung ubvec[1] = 1.01; 30358c9a1619SFlorian Wechsung lenadjncy = 0; 30368c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 30378c9a1619SFlorian Wechsung PetscInt temp=0; 30388c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 30398c9a1619SFlorian Wechsung lenadjncy += temp; 30408c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 30418c9a1619SFlorian Wechsung } 30428c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 30437407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 30440941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 30450941debbSFlorian Wechsung xadj[0] = 0; 30468c9a1619SFlorian Wechsung counter = 0; 30478c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 30482953a68cSFlorian Wechsung PetscInt temp=0; 30492953a68cSFlorian Wechsung const PetscInt *cols; 30508c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 3051694ea26eSFlorian Wechsung ierr = PetscMemcpy(&adjncy[counter], cols, temp*sizeof(PetscInt));CHKERRQ(ierr); 30528c9a1619SFlorian Wechsung counter += temp; 30530941debbSFlorian Wechsung xadj[i+1] = counter; 30548c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 30558c9a1619SFlorian Wechsung } 30568c9a1619SFlorian Wechsung 3057cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 305841525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 305941525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 306041525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 306141525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 306241525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 306341525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 306441525646SFlorian Wechsung } 30658c9a1619SFlorian Wechsung 30665dc86ac1SFlorian Wechsung if (viewer) { 30677d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 30687d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 306912617df9SFlorian Wechsung } 307041525646SFlorian Wechsung if (parallel) { 30715a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 30725a30b08bSFlorian Wechsung options[0] = 1; 30735a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 30745a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 30755a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 30765dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 30778c9a1619SFlorian Wechsung if (useInitialGuess) { 30785dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 30798c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 30805dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 308106b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 30828c9a1619SFlorian Wechsung PetscStackPop; 30838c9a1619SFlorian Wechsung } else { 30848c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 30855dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 30868c9a1619SFlorian Wechsung PetscStackPop; 308706b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 30888c9a1619SFlorian Wechsung } 3089ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 309041525646SFlorian Wechsung } else { 30915dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 309241525646SFlorian Wechsung Mat As; 309341525646SFlorian Wechsung PetscInt numRows; 309441525646SFlorian Wechsung PetscInt *partGlobal; 309541525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 3096cb87ef4cSFlorian Wechsung 309741525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 309841525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 309941525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 31002953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRQ(ierr); 3101cb87ef4cSFlorian Wechsung 310241525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 310341525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 31045dc86ac1SFlorian Wechsung if (!rank) { 310541525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 310641525646SFlorian Wechsung lenadjncy = 0; 310741525646SFlorian Wechsung 310841525646SFlorian Wechsung for (i=0; i<numRows; i++) { 310941525646SFlorian Wechsung PetscInt temp=0; 311041525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 311141525646SFlorian Wechsung lenadjncy += temp; 311241525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 311341525646SFlorian Wechsung } 311441525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 311541525646SFlorian Wechsung lenxadj = 1 + numRows; 311641525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 311741525646SFlorian Wechsung xadj_g[0] = 0; 311841525646SFlorian Wechsung counter = 0; 311941525646SFlorian Wechsung for (i=0; i<numRows; i++) { 31202953a68cSFlorian Wechsung PetscInt temp=0; 31212953a68cSFlorian Wechsung const PetscInt *cols; 312241525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 3123694ea26eSFlorian Wechsung ierr = PetscMemcpy(&adjncy_g[counter], cols, temp*sizeof(PetscInt));CHKERRQ(ierr); 312441525646SFlorian Wechsung counter += temp; 312541525646SFlorian Wechsung xadj_g[i+1] = counter; 312641525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 312741525646SFlorian Wechsung } 312841525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 312941525646SFlorian Wechsung for (i=0; i<size; i++){ 313041525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 313141525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 313241525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 313341525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 313441525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 313541525646SFlorian Wechsung } 313641525646SFlorian Wechsung } 313741525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 313841525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 313906b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 314041525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 314141525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 314206b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 314341525646SFlorian Wechsung PetscStackPop; 314406b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 3145ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 314641525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 314741525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 314841525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 314941525646SFlorian Wechsung } 315041525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 315141525646SFlorian Wechsung 31525dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 31535dc86ac1SFlorian Wechsung { 315481a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 31555dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 315681a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 31575dc86ac1SFlorian Wechsung for(i=0; i<size; i++) { 315881a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 315941525646SFlorian Wechsung } 316081a13b52SFlorian Wechsung for(i=0; i<=size; i++) { 316181a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 316281a13b52SFlorian Wechsung } 316381a13b52SFlorian Wechsung ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRQ(ierr); 31645dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 316581a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 31665dc86ac1SFlorian Wechsung } 31675dc86ac1SFlorian Wechsung 316841525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 31692953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 317041525646SFlorian Wechsung } 3171cb87ef4cSFlorian Wechsung 31722953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 3173cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 3174cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 3175cb87ef4cSFlorian Wechsung 3176cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 3177cb87ef4cSFlorian Wechsung 3178cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 3179cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 3180cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 31812953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRQ(ierr); 3182cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 3183cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 3184cb87ef4cSFlorian Wechsung } 3185cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 3186cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 3187cb87ef4cSFlorian Wechsung } 3188cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 3189cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 31902953a68cSFlorian Wechsung ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 3191cb87ef4cSFlorian Wechsung 31927f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 31937f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 31947f57c1a4SFlorian Wechsung 3195cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 31967f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 31977f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 31987f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 31997f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 32007f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 32017f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 32027f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 32037f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 32047f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 32057f57c1a4SFlorian Wechsung if (viewer) { 320606b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 320706b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 32087f57c1a4SFlorian Wechsung } 32097f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 32108b879b41SFlorian Wechsung PetscFunctionReturn(0); 3211cb87ef4cSFlorian Wechsung } 3212cb87ef4cSFlorian Wechsung 32137407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 32145dc86ac1SFlorian Wechsung if (viewer) { 32157d197802SFlorian 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); 3216125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 3217125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 3218125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 3219125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 32207407ba93SFlorian Wechsung } 32217407ba93SFlorian Wechsung 3222cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 322341525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 3224cb87ef4cSFlorian Wechsung PetscInt loc = 0; 322541525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 32267407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 3227cb87ef4cSFlorian Wechsung if (loc<0) { 322841525646SFlorian Wechsung part[i] = rank; 3229cb87ef4cSFlorian Wechsung } 3230cb87ef4cSFlorian Wechsung } 3231cb87ef4cSFlorian Wechsung 32327407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 32335dc86ac1SFlorian Wechsung if (viewer) { 3234125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 3235125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 32367407ba93SFlorian Wechsung } 32377407ba93SFlorian Wechsung 32385dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3239cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 3240cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 324141525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 3242cb87ef4cSFlorian Wechsung 32437f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 3244cf818975SFlorian Wechsung { 32457f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 324606b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 32477f57c1a4SFlorian Wechsung counter = 0; 3248cb87ef4cSFlorian Wechsung for(i=0; i<pEnd-pStart; i++) { 3249cb87ef4cSFlorian Wechsung if (toBalance[i]) { 3250cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 32517f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 3252cb87ef4cSFlorian Wechsung counter++; 3253cb87ef4cSFlorian Wechsung } 3254cb87ef4cSFlorian Wechsung } 3255cb87ef4cSFlorian Wechsung } 32567f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 32577f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 3258cf818975SFlorian Wechsung } 3259cb87ef4cSFlorian Wechsung 3260cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 3261cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 3262cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 3263cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 32647f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 32655dc86ac1SFlorian Wechsung if (viewer) { 326606b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 326706b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 32687d197802SFlorian Wechsung } 32698b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 327041525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 3271240408d3SFlorian Wechsung #else 32725f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 327341525646SFlorian Wechsung #endif 3274cb87ef4cSFlorian Wechsung PetscFunctionReturn(0); 3275cb87ef4cSFlorian Wechsung } 3276