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" 16a8d69d7bSBarry Smith " doi = {https://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); 204580bdb30SBarry Smith ierr = PetscArraycpy(edges, &graph[start], numEdges);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); 506580bdb30SBarry Smith ierr = PetscArraycpy(tmp, off, numCells+1);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 .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 66377623264SMatthew G. Knepley 66477623264SMatthew G. Knepley @*/ 66577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 66677623264SMatthew G. Knepley { 66777623264SMatthew G. Knepley PetscErrorCode ierr; 66877623264SMatthew G. Knepley 66977623264SMatthew G. Knepley PetscFunctionBegin; 67077623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 67177623264SMatthew G. Knepley PetscFunctionReturn(0); 67277623264SMatthew G. Knepley } 67377623264SMatthew G. Knepley 67477623264SMatthew G. Knepley /*@C 67577623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 67677623264SMatthew G. Knepley 677d083f849SBarry Smith Collective on part 67877623264SMatthew G. Knepley 67977623264SMatthew G. Knepley Input Parameters: 68077623264SMatthew G. Knepley + part - The PetscPartitioner object 68177623264SMatthew G. Knepley - name - The kind of partitioner 68277623264SMatthew G. Knepley 68377623264SMatthew G. Knepley Options Database Key: 68477623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 68577623264SMatthew G. Knepley 68677623264SMatthew G. Knepley Level: intermediate 68777623264SMatthew G. Knepley 68877623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 68977623264SMatthew G. Knepley @*/ 69077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 69177623264SMatthew G. Knepley { 69277623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 69377623264SMatthew G. Knepley PetscBool match; 69477623264SMatthew G. Knepley PetscErrorCode ierr; 69577623264SMatthew G. Knepley 69677623264SMatthew G. Knepley PetscFunctionBegin; 69777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 69877623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 69977623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 70077623264SMatthew G. Knepley 7010f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 70277623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 70377623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 70477623264SMatthew G. Knepley 70577623264SMatthew G. Knepley if (part->ops->destroy) { 70677623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 70777623264SMatthew G. Knepley } 708074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 709d57f96a3SLisandro Dalcin ierr = PetscMemzero(part->ops, sizeof(*part->ops));CHKERRQ(ierr); 71077623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 711d57f96a3SLisandro Dalcin ierr = (*r)(part);CHKERRQ(ierr); 71277623264SMatthew G. Knepley PetscFunctionReturn(0); 71377623264SMatthew G. Knepley } 71477623264SMatthew G. Knepley 71577623264SMatthew G. Knepley /*@C 71677623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 71777623264SMatthew G. Knepley 71877623264SMatthew G. Knepley Not Collective 71977623264SMatthew G. Knepley 72077623264SMatthew G. Knepley Input Parameter: 72177623264SMatthew G. Knepley . part - The PetscPartitioner 72277623264SMatthew G. Knepley 72377623264SMatthew G. Knepley Output Parameter: 72477623264SMatthew G. Knepley . name - The PetscPartitioner type name 72577623264SMatthew G. Knepley 72677623264SMatthew G. Knepley Level: intermediate 72777623264SMatthew G. Knepley 72877623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 72977623264SMatthew G. Knepley @*/ 73077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 73177623264SMatthew G. Knepley { 73277623264SMatthew G. Knepley PetscErrorCode ierr; 73377623264SMatthew G. Knepley 73477623264SMatthew G. Knepley PetscFunctionBegin; 73577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 73677623264SMatthew G. Knepley PetscValidPointer(name, 2); 7370f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 73877623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 73977623264SMatthew G. Knepley PetscFunctionReturn(0); 74077623264SMatthew G. Knepley } 74177623264SMatthew G. Knepley 74277623264SMatthew G. Knepley /*@C 74377623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 74477623264SMatthew G. Knepley 745d083f849SBarry Smith Collective on part 74677623264SMatthew G. Knepley 74777623264SMatthew G. Knepley Input Parameter: 74877623264SMatthew G. Knepley + part - the PetscPartitioner object to view 74977623264SMatthew G. Knepley - v - the viewer 75077623264SMatthew G. Knepley 75177623264SMatthew G. Knepley Level: developer 75277623264SMatthew G. Knepley 75377623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 75477623264SMatthew G. Knepley @*/ 75577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 75677623264SMatthew G. Knepley { 757ffc59708SMatthew G. Knepley PetscMPIInt size; 7582abdaa70SMatthew G. Knepley PetscBool isascii; 75977623264SMatthew G. Knepley PetscErrorCode ierr; 76077623264SMatthew G. Knepley 76177623264SMatthew G. Knepley PetscFunctionBegin; 76277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 76377623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 7642abdaa70SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 7652abdaa70SMatthew G. Knepley if (isascii) { 7662abdaa70SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 767ffc59708SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");CHKERRQ(ierr); 7682abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " type: %s\n", part->hdr.type_name);CHKERRQ(ierr); 7692abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 7702abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "edge cut: %D\n", part->edgeCut);CHKERRQ(ierr); 7712abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "balance: %.2g\n", part->balance);CHKERRQ(ierr); 7722abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 7732abdaa70SMatthew G. Knepley } 77477623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 77577623264SMatthew G. Knepley PetscFunctionReturn(0); 77677623264SMatthew G. Knepley } 77777623264SMatthew G. Knepley 778a0058e54SToby Isaac static PetscErrorCode PetscPartitionerGetDefaultType(const char *currentType, const char **defaultType) 779a0058e54SToby Isaac { 780a0058e54SToby Isaac PetscFunctionBegin; 781a0058e54SToby Isaac if (!currentType) { 78256bf5a81SLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 783a0058e54SToby Isaac *defaultType = PETSCPARTITIONERPARMETIS; 784137cd93aSLisandro Dalcin #elif defined(PETSC_HAVE_PTSCOTCH) 785137cd93aSLisandro Dalcin *defaultType = PETSCPARTITIONERPTSCOTCH; 78656bf5a81SLisandro Dalcin #elif defined(PETSC_HAVE_CHACO) 78756bf5a81SLisandro Dalcin *defaultType = PETSCPARTITIONERCHACO; 788a0058e54SToby Isaac #else 789a0058e54SToby Isaac *defaultType = PETSCPARTITIONERSIMPLE; 790a0058e54SToby Isaac #endif 791a0058e54SToby Isaac } else { 792a0058e54SToby Isaac *defaultType = currentType; 793a0058e54SToby Isaac } 794a0058e54SToby Isaac PetscFunctionReturn(0); 795a0058e54SToby Isaac } 796a0058e54SToby Isaac 79777623264SMatthew G. Knepley /*@ 79877623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 79977623264SMatthew G. Knepley 800d083f849SBarry Smith Collective on part 80177623264SMatthew G. Knepley 80277623264SMatthew G. Knepley Input Parameter: 80377623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 80477623264SMatthew G. Knepley 80577623264SMatthew G. Knepley Level: developer 80677623264SMatthew G. Knepley 80777623264SMatthew G. Knepley .seealso: PetscPartitionerView() 80877623264SMatthew G. Knepley @*/ 80977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 81077623264SMatthew G. Knepley { 8116bb9daa8SLisandro Dalcin const char *defaultType; 8126bb9daa8SLisandro Dalcin char name[256]; 8136bb9daa8SLisandro Dalcin PetscBool flg; 81477623264SMatthew G. Knepley PetscErrorCode ierr; 81577623264SMatthew G. Knepley 81677623264SMatthew G. Knepley PetscFunctionBegin; 81777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8186bb9daa8SLisandro Dalcin ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 8196bb9daa8SLisandro Dalcin ierr = PetscPartitionerGetDefaultType(((PetscObject) part)->type_name,&defaultType);CHKERRQ(ierr); 82077623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 8216bb9daa8SLisandro Dalcin ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, sizeof(name), &flg);CHKERRQ(ierr); 8226bb9daa8SLisandro Dalcin if (flg) { 8236bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 8246bb9daa8SLisandro Dalcin } else if (!((PetscObject) part)->type_name) { 8256bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 8266bb9daa8SLisandro Dalcin } 8276bb9daa8SLisandro Dalcin if (part->ops->setfromoptions) { 8286bb9daa8SLisandro Dalcin ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr); 8296bb9daa8SLisandro Dalcin } 830783e1fb6SStefano Zampini ierr = PetscViewerDestroy(&part->viewerGraph);CHKERRQ(ierr); 8310358368aSMatthew G. Knepley ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, &part->formatGraph, &part->viewGraph);CHKERRQ(ierr); 83277623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 8330633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 83477623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 83577623264SMatthew G. Knepley PetscFunctionReturn(0); 83677623264SMatthew G. Knepley } 83777623264SMatthew G. Knepley 83877623264SMatthew G. Knepley /*@C 83977623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 84077623264SMatthew G. Knepley 841d083f849SBarry Smith Collective on part 84277623264SMatthew G. Knepley 84377623264SMatthew G. Knepley Input Parameter: 84477623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 84577623264SMatthew G. Knepley 84677623264SMatthew G. Knepley Level: developer 84777623264SMatthew G. Knepley 84877623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 84977623264SMatthew G. Knepley @*/ 85077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 85177623264SMatthew G. Knepley { 85277623264SMatthew G. Knepley PetscErrorCode ierr; 85377623264SMatthew G. Knepley 85477623264SMatthew G. Knepley PetscFunctionBegin; 85577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 85677623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 85777623264SMatthew G. Knepley PetscFunctionReturn(0); 85877623264SMatthew G. Knepley } 85977623264SMatthew G. Knepley 86077623264SMatthew G. Knepley /*@ 86177623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 86277623264SMatthew G. Knepley 863d083f849SBarry Smith Collective on part 86477623264SMatthew G. Knepley 86577623264SMatthew G. Knepley Input Parameter: 86677623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 86777623264SMatthew G. Knepley 86877623264SMatthew G. Knepley Level: developer 86977623264SMatthew G. Knepley 87077623264SMatthew G. Knepley .seealso: PetscPartitionerView() 87177623264SMatthew G. Knepley @*/ 87277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 87377623264SMatthew G. Knepley { 87477623264SMatthew G. Knepley PetscErrorCode ierr; 87577623264SMatthew G. Knepley 87677623264SMatthew G. Knepley PetscFunctionBegin; 87777623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 87877623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 87977623264SMatthew G. Knepley 88077623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 88177623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 88277623264SMatthew G. Knepley 8830358368aSMatthew G. Knepley ierr = PetscViewerDestroy(&(*part)->viewerGraph);CHKERRQ(ierr); 88477623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 88577623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 88677623264SMatthew G. Knepley PetscFunctionReturn(0); 88777623264SMatthew G. Knepley } 88877623264SMatthew G. Knepley 88977623264SMatthew G. Knepley /*@ 89077623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 89177623264SMatthew G. Knepley 892d083f849SBarry Smith Collective 89377623264SMatthew G. Knepley 89477623264SMatthew G. Knepley Input Parameter: 89577623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 89677623264SMatthew G. Knepley 89777623264SMatthew G. Knepley Output Parameter: 89877623264SMatthew G. Knepley . part - The PetscPartitioner object 89977623264SMatthew G. Knepley 90077623264SMatthew G. Knepley Level: beginner 90177623264SMatthew G. Knepley 902dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 90377623264SMatthew G. Knepley @*/ 90477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 90577623264SMatthew G. Knepley { 90677623264SMatthew G. Knepley PetscPartitioner p; 907a0058e54SToby Isaac const char *partitionerType = NULL; 90877623264SMatthew G. Knepley PetscErrorCode ierr; 90977623264SMatthew G. Knepley 91077623264SMatthew G. Knepley PetscFunctionBegin; 91177623264SMatthew G. Knepley PetscValidPointer(part, 2); 91277623264SMatthew G. Knepley *part = NULL; 91383cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 91477623264SMatthew G. Knepley 91573107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 916a0058e54SToby Isaac ierr = PetscPartitionerGetDefaultType(NULL,&partitionerType);CHKERRQ(ierr); 917a0058e54SToby Isaac ierr = PetscPartitionerSetType(p,partitionerType);CHKERRQ(ierr); 91877623264SMatthew G. Knepley 91972379da4SMatthew G. Knepley p->edgeCut = 0; 92072379da4SMatthew G. Knepley p->balance = 0.0; 92172379da4SMatthew G. Knepley 92277623264SMatthew G. Knepley *part = p; 92377623264SMatthew G. Knepley PetscFunctionReturn(0); 92477623264SMatthew G. Knepley } 92577623264SMatthew G. Knepley 92677623264SMatthew G. Knepley /*@ 92777623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 92877623264SMatthew G. Knepley 929d083f849SBarry Smith Collective on dm 93077623264SMatthew G. Knepley 93177623264SMatthew G. Knepley Input Parameters: 93277623264SMatthew G. Knepley + part - The PetscPartitioner 933f8987ae8SMichael Lange - dm - The mesh DM 93477623264SMatthew G. Knepley 93577623264SMatthew G. Knepley Output Parameters: 93677623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 937f8987ae8SMichael Lange - partition - The list of points by partition 93877623264SMatthew G. Knepley 9390358368aSMatthew G. Knepley Options Database: 9400358368aSMatthew G. Knepley . -petscpartitioner_view_graph - View the graph we are partitioning 9410358368aSMatthew G. Knepley 94277623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 94377623264SMatthew G. Knepley 94477623264SMatthew G. Knepley Level: developer 94577623264SMatthew G. Knepley 94677623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 9474b15ede2SMatthew G. Knepley @*/ 948f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 94977623264SMatthew G. Knepley { 95077623264SMatthew G. Knepley PetscMPIInt size; 95177623264SMatthew G. Knepley PetscErrorCode ierr; 95277623264SMatthew G. Knepley 95377623264SMatthew G. Knepley PetscFunctionBegin; 95477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 95577623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 95677623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 95777623264SMatthew G. Knepley PetscValidPointer(partition, 5); 95877623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 95977623264SMatthew G. Knepley if (size == 1) { 96077623264SMatthew G. Knepley PetscInt *points; 96177623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 96277623264SMatthew G. Knepley 96377623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 96477623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 96577623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 96677623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 96777623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 96877623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 96977623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 97077623264SMatthew G. Knepley PetscFunctionReturn(0); 97177623264SMatthew G. Knepley } 97277623264SMatthew G. Knepley if (part->height == 0) { 973074d466cSStefano Zampini PetscInt numVertices = 0; 97477623264SMatthew G. Knepley PetscInt *start = NULL; 97577623264SMatthew G. Knepley PetscInt *adjacency = NULL; 9763fa7752dSToby Isaac IS globalNumbering; 97777623264SMatthew G. Knepley 978074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 979074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 98013911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 981074d466cSStefano Zampini const PetscInt *idxs; 982074d466cSStefano Zampini PetscInt p, pStart, pEnd; 983074d466cSStefano Zampini 984074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 985074d466cSStefano Zampini ierr = DMPlexCreateNumbering_Internal(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 986074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 987074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 988074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 989074d466cSStefano Zampini } 9900358368aSMatthew G. Knepley if (part->viewGraph) { 9910358368aSMatthew G. Knepley PetscViewer viewer = part->viewerGraph; 9920358368aSMatthew G. Knepley PetscBool isascii; 9930358368aSMatthew G. Knepley PetscInt v, i; 9940358368aSMatthew G. Knepley PetscMPIInt rank; 9950358368aSMatthew G. Knepley 9960358368aSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRQ(ierr); 9970358368aSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 9980358368aSMatthew G. Knepley if (isascii) { 9990358368aSMatthew G. Knepley ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 10000358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);CHKERRQ(ierr); 10010358368aSMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 10020358368aSMatthew G. Knepley const PetscInt s = start[v]; 10030358368aSMatthew G. Knepley const PetscInt e = start[v+1]; 10040358368aSMatthew G. Knepley 10050358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank);CHKERRQ(ierr); 10060358368aSMatthew G. Knepley for (i = s; i < e; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);CHKERRQ(ierr);} 10070358368aSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);CHKERRQ(ierr); 10080358368aSMatthew G. Knepley } 10090358368aSMatthew G. Knepley ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 10100358368aSMatthew G. Knepley ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 10110358368aSMatthew G. Knepley } 10120358368aSMatthew G. Knepley } 1013bbbc8e51SStefano Zampini if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no partitioning method"); 101477623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 101577623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 101677623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 10173fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 10183fa7752dSToby Isaac const PetscInt *globalNum; 10193fa7752dSToby Isaac const PetscInt *partIdx; 10203fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 10213fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 10223fa7752dSToby Isaac IS newPartition; 10233fa7752dSToby Isaac 10243fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 10253fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 10263fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10273fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 10283fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 10293fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 10303fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 10313fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 10323fa7752dSToby Isaac } 10333fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 10343fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 10353fa7752dSToby Isaac } 10363fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 10373fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 10383fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 10393fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 10403fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 10413fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 10423fa7752dSToby Isaac *partition = newPartition; 10433fa7752dSToby Isaac } 104477623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 10452abdaa70SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 104677623264SMatthew G. Knepley PetscFunctionReturn(0); 104777623264SMatthew G. Knepley } 104877623264SMatthew G. Knepley 1049d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 105077623264SMatthew G. Knepley { 105177623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 105277623264SMatthew G. Knepley PetscErrorCode ierr; 105377623264SMatthew G. Knepley 105477623264SMatthew G. Knepley PetscFunctionBegin; 105577623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 105677623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 105777623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 105877623264SMatthew G. Knepley PetscFunctionReturn(0); 105977623264SMatthew G. Knepley } 106077623264SMatthew G. Knepley 1061d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 106277623264SMatthew G. Knepley { 1063077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 106477623264SMatthew G. Knepley PetscErrorCode ierr; 106577623264SMatthew G. Knepley 106677623264SMatthew G. Knepley PetscFunctionBegin; 1067077101c0SMatthew G. Knepley if (p->random) { 1068077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1069077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 1070077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1071077101c0SMatthew G. Knepley } 107277623264SMatthew G. Knepley PetscFunctionReturn(0); 107377623264SMatthew G. Knepley } 107477623264SMatthew G. Knepley 1075d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 107677623264SMatthew G. Knepley { 107777623264SMatthew G. Knepley PetscBool iascii; 107877623264SMatthew G. Knepley PetscErrorCode ierr; 107977623264SMatthew G. Knepley 108077623264SMatthew G. Knepley PetscFunctionBegin; 108177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 108277623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 108377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 108477623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 108577623264SMatthew G. Knepley PetscFunctionReturn(0); 108677623264SMatthew G. Knepley } 108777623264SMatthew G. Knepley 1088d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 1089077101c0SMatthew G. Knepley { 1090077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1091077101c0SMatthew G. Knepley PetscErrorCode ierr; 1092077101c0SMatthew G. Knepley 1093077101c0SMatthew G. Knepley PetscFunctionBegin; 1094077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 1095077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 1096077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1097077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1098077101c0SMatthew G. Knepley } 1099077101c0SMatthew G. Knepley 1100d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 110177623264SMatthew G. Knepley { 110277623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 110377623264SMatthew G. Knepley PetscInt np; 110477623264SMatthew G. Knepley PetscErrorCode ierr; 110577623264SMatthew G. Knepley 110677623264SMatthew G. Knepley PetscFunctionBegin; 1107077101c0SMatthew G. Knepley if (p->random) { 1108077101c0SMatthew G. Knepley PetscRandom r; 1109aa1d5631SMatthew G. Knepley PetscInt *sizes, *points, v, p; 1110aa1d5631SMatthew G. Knepley PetscMPIInt rank; 1111077101c0SMatthew G. Knepley 1112aa1d5631SMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1113077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 1114c717d290SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 1115077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 1116077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 1117aa1d5631SMatthew G. Knepley for (v = 0; v < numVertices; ++v) {points[v] = v;} 1118ac9a96f1SMichael Lange for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 1119aa1d5631SMatthew G. Knepley for (v = numVertices-1; v > 0; --v) { 1120077101c0SMatthew G. Knepley PetscReal val; 1121aa1d5631SMatthew G. Knepley PetscInt w, tmp; 1122077101c0SMatthew G. Knepley 1123aa1d5631SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 1124077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 1125aa1d5631SMatthew G. Knepley w = PetscFloorReal(val); 1126aa1d5631SMatthew G. Knepley tmp = points[v]; 1127aa1d5631SMatthew G. Knepley points[v] = points[w]; 1128aa1d5631SMatthew G. Knepley points[w] = tmp; 1129077101c0SMatthew G. Knepley } 1130077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 1131077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 1132077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 1133077101c0SMatthew G. Knepley } 1134c717d290SMatthew G. Knepley if (!p->section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 113577623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 113677623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 113777623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 113877623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 11395680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 114077623264SMatthew G. Knepley *partition = p->partition; 114177623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 114277623264SMatthew G. Knepley PetscFunctionReturn(0); 114377623264SMatthew G. Knepley } 114477623264SMatthew G. Knepley 1145d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 114677623264SMatthew G. Knepley { 114777623264SMatthew G. Knepley PetscFunctionBegin; 1148074d466cSStefano Zampini part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 114977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 1150077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 115177623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 115277623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 115377623264SMatthew G. Knepley PetscFunctionReturn(0); 115477623264SMatthew G. Knepley } 115577623264SMatthew G. Knepley 115677623264SMatthew G. Knepley /*MC 115777623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 115877623264SMatthew G. Knepley 115977623264SMatthew G. Knepley Level: intermediate 116077623264SMatthew G. Knepley 116177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 116277623264SMatthew G. Knepley M*/ 116377623264SMatthew G. Knepley 116477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 116577623264SMatthew G. Knepley { 116677623264SMatthew G. Knepley PetscPartitioner_Shell *p; 116777623264SMatthew G. Knepley PetscErrorCode ierr; 116877623264SMatthew G. Knepley 116977623264SMatthew G. Knepley PetscFunctionBegin; 117077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 117177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 117277623264SMatthew G. Knepley part->data = p; 117377623264SMatthew G. Knepley 117477623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 1175077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 117677623264SMatthew G. Knepley PetscFunctionReturn(0); 117777623264SMatthew G. Knepley } 117877623264SMatthew G. Knepley 11795680f57bSMatthew G. Knepley /*@C 11805680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 11815680f57bSMatthew G. Knepley 1182d083f849SBarry Smith Collective on part 11835680f57bSMatthew G. Knepley 11845680f57bSMatthew G. Knepley Input Parameters: 11855680f57bSMatthew G. Knepley + part - The PetscPartitioner 11869852e123SBarry Smith . size - The number of partitions 11879852e123SBarry Smith . sizes - array of size size (or NULL) providing the number of points in each partition 11889758bf69SToby 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.) 11895680f57bSMatthew G. Knepley 11905680f57bSMatthew G. Knepley Level: developer 11915680f57bSMatthew G. Knepley 1192b7e49471SLawrence Mitchell Notes: 1193b7e49471SLawrence Mitchell 1194b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 1195b7e49471SLawrence Mitchell 11965680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 11975680f57bSMatthew G. Knepley @*/ 11989852e123SBarry Smith PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 11995680f57bSMatthew G. Knepley { 12005680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 12015680f57bSMatthew G. Knepley PetscInt proc, numPoints; 12025680f57bSMatthew G. Knepley PetscErrorCode ierr; 12035680f57bSMatthew G. Knepley 12045680f57bSMatthew G. Knepley PetscFunctionBegin; 12055680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 12065680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 1207c717d290SMatthew G. Knepley if (points) {PetscValidPointer(points, 4);} 12085680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 12095680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 12105680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 12119852e123SBarry Smith ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 12125680f57bSMatthew G. Knepley if (sizes) { 12139852e123SBarry Smith for (proc = 0; proc < size; ++proc) { 12145680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 12155680f57bSMatthew G. Knepley } 12165680f57bSMatthew G. Knepley } 12175680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 12185680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 12195680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 12205680f57bSMatthew G. Knepley PetscFunctionReturn(0); 12215680f57bSMatthew G. Knepley } 12225680f57bSMatthew G. Knepley 1223077101c0SMatthew G. Knepley /*@ 1224077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 1225077101c0SMatthew G. Knepley 1226d083f849SBarry Smith Collective on part 1227077101c0SMatthew G. Knepley 1228077101c0SMatthew G. Knepley Input Parameters: 1229077101c0SMatthew G. Knepley + part - The PetscPartitioner 1230077101c0SMatthew G. Knepley - random - The flag to use a random partition 1231077101c0SMatthew G. Knepley 1232077101c0SMatthew G. Knepley Level: intermediate 1233077101c0SMatthew G. Knepley 1234077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 1235077101c0SMatthew G. Knepley @*/ 1236077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 1237077101c0SMatthew G. Knepley { 1238077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1239077101c0SMatthew G. Knepley 1240077101c0SMatthew G. Knepley PetscFunctionBegin; 1241077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1242077101c0SMatthew G. Knepley p->random = random; 1243077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1244077101c0SMatthew G. Knepley } 1245077101c0SMatthew G. Knepley 1246077101c0SMatthew G. Knepley /*@ 1247077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 1248077101c0SMatthew G. Knepley 1249d083f849SBarry Smith Collective on part 1250077101c0SMatthew G. Knepley 1251077101c0SMatthew G. Knepley Input Parameter: 1252077101c0SMatthew G. Knepley . part - The PetscPartitioner 1253077101c0SMatthew G. Knepley 1254077101c0SMatthew G. Knepley Output Parameter 1255077101c0SMatthew G. Knepley . random - The flag to use a random partition 1256077101c0SMatthew G. Knepley 1257077101c0SMatthew G. Knepley Level: intermediate 1258077101c0SMatthew G. Knepley 1259077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 1260077101c0SMatthew G. Knepley @*/ 1261077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 1262077101c0SMatthew G. Knepley { 1263077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1264077101c0SMatthew G. Knepley 1265077101c0SMatthew G. Knepley PetscFunctionBegin; 1266077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1267077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 1268077101c0SMatthew G. Knepley *random = p->random; 1269077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1270077101c0SMatthew G. Knepley } 1271077101c0SMatthew G. Knepley 1272d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 1273555a9cf8SMatthew G. Knepley { 1274555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 1275555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1276555a9cf8SMatthew G. Knepley 1277555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1278555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 1279555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1280555a9cf8SMatthew G. Knepley } 1281555a9cf8SMatthew G. Knepley 1282d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 1283555a9cf8SMatthew G. Knepley { 1284555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1285555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1286555a9cf8SMatthew G. Knepley } 1287555a9cf8SMatthew G. Knepley 1288d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 1289555a9cf8SMatthew G. Knepley { 1290555a9cf8SMatthew G. Knepley PetscBool iascii; 1291555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1292555a9cf8SMatthew G. Knepley 1293555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1294555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1295555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1296555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1297555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 1298555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1299555a9cf8SMatthew G. Knepley } 1300555a9cf8SMatthew G. Knepley 1301d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1302555a9cf8SMatthew G. Knepley { 1303cead94edSToby Isaac MPI_Comm comm; 1304555a9cf8SMatthew G. Knepley PetscInt np; 1305cead94edSToby Isaac PetscMPIInt size; 1306555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1307555a9cf8SMatthew G. Knepley 1308555a9cf8SMatthew G. Knepley PetscFunctionBegin; 130904ba2274SStefano Zampini comm = PetscObjectComm((PetscObject)part); 1310cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1311555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1312555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1313cead94edSToby Isaac if (size == 1) { 1314cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 131504ba2274SStefano Zampini } else { 1316cead94edSToby Isaac PetscMPIInt rank; 1317cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 1318cead94edSToby Isaac 1319a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1320cead94edSToby Isaac offsets[0] = 0; 1321cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1322cead94edSToby Isaac for (np = 2; np <= size; np++) { 1323cead94edSToby Isaac offsets[np] += offsets[np-1]; 1324cead94edSToby Isaac } 1325cead94edSToby Isaac nvGlobal = offsets[size]; 1326cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1327cead94edSToby Isaac myFirst = offsets[rank]; 1328cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1329cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1330cead94edSToby Isaac if (numVertices) { 1331cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1332cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1333cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1334cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1335cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1336cead94edSToby Isaac 1337cead94edSToby Isaac 1338cead94edSToby Isaac if (rem) { 1339cead94edSToby Isaac firstLargePart = myFirst / pBig; 1340cead94edSToby Isaac lastLargePart = myLast / pBig; 1341cead94edSToby Isaac 1342cead94edSToby Isaac if (firstLargePart < rem) { 1343cead94edSToby Isaac firstPart = firstLargePart; 134404ba2274SStefano Zampini } else { 1345cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1346cead94edSToby Isaac } 1347cead94edSToby Isaac if (lastLargePart < rem) { 1348cead94edSToby Isaac lastPart = lastLargePart; 134904ba2274SStefano Zampini } else { 1350cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1351cead94edSToby Isaac } 135204ba2274SStefano Zampini } else { 1353cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1354cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1355cead94edSToby Isaac } 1356cead94edSToby Isaac 1357cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1358cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1359cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1360cead94edSToby Isaac 1361cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1362cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1363cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1364cead94edSToby Isaac } 1365cead94edSToby Isaac } 1366cead94edSToby Isaac } 1367cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1368555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1369555a9cf8SMatthew G. Knepley } 1370555a9cf8SMatthew G. Knepley 1371d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1372555a9cf8SMatthew G. Knepley { 1373555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1374074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1375555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1376555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1377555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1378555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1379555a9cf8SMatthew G. Knepley } 1380555a9cf8SMatthew G. Knepley 1381555a9cf8SMatthew G. Knepley /*MC 1382555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1383555a9cf8SMatthew G. Knepley 1384555a9cf8SMatthew G. Knepley Level: intermediate 1385555a9cf8SMatthew G. Knepley 1386555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1387555a9cf8SMatthew G. Knepley M*/ 1388555a9cf8SMatthew G. Knepley 1389555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1390555a9cf8SMatthew G. Knepley { 1391555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1392555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1393555a9cf8SMatthew G. Knepley 1394555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1395555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1396555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1397555a9cf8SMatthew G. Knepley part->data = p; 1398555a9cf8SMatthew G. Knepley 1399555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1400555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1401555a9cf8SMatthew G. Knepley } 1402555a9cf8SMatthew G. Knepley 1403d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1404dae52e14SToby Isaac { 1405dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1406dae52e14SToby Isaac PetscErrorCode ierr; 1407dae52e14SToby Isaac 1408dae52e14SToby Isaac PetscFunctionBegin; 1409dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1410dae52e14SToby Isaac PetscFunctionReturn(0); 1411dae52e14SToby Isaac } 1412dae52e14SToby Isaac 1413d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1414dae52e14SToby Isaac { 1415dae52e14SToby Isaac PetscFunctionBegin; 1416dae52e14SToby Isaac PetscFunctionReturn(0); 1417dae52e14SToby Isaac } 1418dae52e14SToby Isaac 1419d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1420dae52e14SToby Isaac { 1421dae52e14SToby Isaac PetscBool iascii; 1422dae52e14SToby Isaac PetscErrorCode ierr; 1423dae52e14SToby Isaac 1424dae52e14SToby Isaac PetscFunctionBegin; 1425dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1426dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1427dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1428dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1429dae52e14SToby Isaac PetscFunctionReturn(0); 1430dae52e14SToby Isaac } 1431dae52e14SToby Isaac 1432d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1433dae52e14SToby Isaac { 1434dae52e14SToby Isaac PetscInt np; 1435dae52e14SToby Isaac PetscErrorCode ierr; 1436dae52e14SToby Isaac 1437dae52e14SToby Isaac PetscFunctionBegin; 1438dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1439dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1440dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1441dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1442dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1443dae52e14SToby Isaac PetscFunctionReturn(0); 1444dae52e14SToby Isaac } 1445dae52e14SToby Isaac 1446d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1447dae52e14SToby Isaac { 1448dae52e14SToby Isaac PetscFunctionBegin; 1449074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1450dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1451dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1452dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1453dae52e14SToby Isaac PetscFunctionReturn(0); 1454dae52e14SToby Isaac } 1455dae52e14SToby Isaac 1456dae52e14SToby Isaac /*MC 1457dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1458dae52e14SToby Isaac 1459dae52e14SToby Isaac Level: intermediate 1460dae52e14SToby Isaac 1461dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1462dae52e14SToby Isaac M*/ 1463dae52e14SToby Isaac 1464dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1465dae52e14SToby Isaac { 1466dae52e14SToby Isaac PetscPartitioner_Gather *p; 1467dae52e14SToby Isaac PetscErrorCode ierr; 1468dae52e14SToby Isaac 1469dae52e14SToby Isaac PetscFunctionBegin; 1470dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1471dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1472dae52e14SToby Isaac part->data = p; 1473dae52e14SToby Isaac 1474dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1475dae52e14SToby Isaac PetscFunctionReturn(0); 1476dae52e14SToby Isaac } 1477dae52e14SToby Isaac 1478dae52e14SToby Isaac 1479d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 148077623264SMatthew G. Knepley { 148177623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 148277623264SMatthew G. Knepley PetscErrorCode ierr; 148377623264SMatthew G. Knepley 148477623264SMatthew G. Knepley PetscFunctionBegin; 148577623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 148677623264SMatthew G. Knepley PetscFunctionReturn(0); 148777623264SMatthew G. Knepley } 148877623264SMatthew G. Knepley 1489d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 149077623264SMatthew G. Knepley { 149177623264SMatthew G. Knepley PetscFunctionBegin; 149277623264SMatthew G. Knepley PetscFunctionReturn(0); 149377623264SMatthew G. Knepley } 149477623264SMatthew G. Knepley 1495d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 149677623264SMatthew G. Knepley { 149777623264SMatthew G. Knepley PetscBool iascii; 149877623264SMatthew G. Knepley PetscErrorCode ierr; 149977623264SMatthew G. Knepley 150077623264SMatthew G. Knepley PetscFunctionBegin; 150177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 150277623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 150377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 150477623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 150577623264SMatthew G. Knepley PetscFunctionReturn(0); 150677623264SMatthew G. Knepley } 150777623264SMatthew G. Knepley 150870034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 150970034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 151070034214SMatthew G. Knepley #include <unistd.h> 151170034214SMatthew G. Knepley #endif 151211d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 151311d1e910SBarry Smith #include <chaco.h> 151411d1e910SBarry Smith #else 151511d1e910SBarry Smith /* Older versions of Chaco do not have an include file */ 151670034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 151770034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 151870034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 151970034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 152070034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 152111d1e910SBarry Smith #endif 152270034214SMatthew G. Knepley extern int FREE_GRAPH; 152377623264SMatthew G. Knepley #endif 152470034214SMatthew G. Knepley 1525d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 152670034214SMatthew G. Knepley { 152777623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 152870034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 152970034214SMatthew G. Knepley MPI_Comm comm; 153070034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 153170034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 153270034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 153370034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 153470034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 153570034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 153670034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 153770034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 153870034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 153970034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 154070034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 154170034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 154270034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 154370034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 154470034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 154570034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 154670034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 154711d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 154811d1e910SBarry Smith int *assignment; /* Output partition */ 154911d1e910SBarry Smith #else 155070034214SMatthew G. Knepley short int *assignment; /* Output partition */ 155111d1e910SBarry Smith #endif 155270034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 155370034214SMatthew G. Knepley PetscInt *points; 155470034214SMatthew G. Knepley int i, v, p; 155570034214SMatthew G. Knepley PetscErrorCode ierr; 155670034214SMatthew G. Knepley 155770034214SMatthew G. Knepley PetscFunctionBegin; 155870034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 155907ed3857SLisandro Dalcin #if defined (PETSC_USE_DEBUG) 156007ed3857SLisandro Dalcin { 156107ed3857SLisandro Dalcin int ival,isum; 156207ed3857SLisandro Dalcin PetscBool distributed; 156307ed3857SLisandro Dalcin 156407ed3857SLisandro Dalcin ival = (numVertices > 0); 156507ed3857SLisandro Dalcin ierr = MPI_Allreduce(&ival, &isum, 1, MPI_INT, MPI_SUM, comm);CHKERRQ(ierr); 156607ed3857SLisandro Dalcin distributed = (isum > 1) ? PETSC_TRUE : PETSC_FALSE; 156707ed3857SLisandro Dalcin if (distributed) SETERRQ(comm, PETSC_ERR_SUP, "Chaco cannot partition a distributed graph"); 156807ed3857SLisandro Dalcin } 156907ed3857SLisandro Dalcin #endif 157070034214SMatthew G. Knepley if (!numVertices) { 157177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 157277623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 157370034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 157470034214SMatthew G. Knepley PetscFunctionReturn(0); 157570034214SMatthew G. Knepley } 157670034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 157770034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 157870034214SMatthew G. Knepley 157970034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 158070034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 158170034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 158270034214SMatthew G. Knepley } 158377623264SMatthew G. Knepley mesh_dims[0] = nparts; 158470034214SMatthew G. Knepley mesh_dims[1] = 1; 158570034214SMatthew G. Knepley mesh_dims[2] = 1; 158670034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 158770034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 158870034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 158970034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 159070034214SMatthew G. Knepley { 159170034214SMatthew G. Knepley int piperet; 159270034214SMatthew G. Knepley piperet = pipe(fd_pipe); 159370034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 159470034214SMatthew G. Knepley fd_stdout = dup(1); 159570034214SMatthew G. Knepley close(1); 159670034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 159770034214SMatthew G. Knepley } 159870034214SMatthew G. Knepley #endif 159970034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 160070034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 160170034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 160270034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 160370034214SMatthew G. Knepley { 160470034214SMatthew G. Knepley char msgLog[10000]; 160570034214SMatthew G. Knepley int count; 160670034214SMatthew G. Knepley 160770034214SMatthew G. Knepley fflush(stdout); 160870034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 160970034214SMatthew G. Knepley if (count < 0) count = 0; 161070034214SMatthew G. Knepley msgLog[count] = 0; 161170034214SMatthew G. Knepley close(1); 161270034214SMatthew G. Knepley dup2(fd_stdout, 1); 161370034214SMatthew G. Knepley close(fd_stdout); 161470034214SMatthew G. Knepley close(fd_pipe[0]); 161570034214SMatthew G. Knepley close(fd_pipe[1]); 161670034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 161770034214SMatthew G. Knepley } 161807ed3857SLisandro Dalcin #else 161907ed3857SLisandro Dalcin if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", "error in stdout"); 162070034214SMatthew G. Knepley #endif 162170034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 162277623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 162370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 162477623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 162570034214SMatthew G. Knepley } 162677623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 162770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 162877623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 162970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 163070034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 163170034214SMatthew G. Knepley } 163270034214SMatthew G. Knepley } 163370034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 163470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 163570034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 163670034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 163770034214SMatthew G. Knepley } 163870034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 163970034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 164070034214SMatthew G. Knepley PetscFunctionReturn(0); 164177623264SMatthew G. Knepley #else 164277623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 164370034214SMatthew G. Knepley #endif 164477623264SMatthew G. Knepley } 164577623264SMatthew G. Knepley 1646d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 164777623264SMatthew G. Knepley { 164877623264SMatthew G. Knepley PetscFunctionBegin; 1649074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 165077623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 165177623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 165277623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 165377623264SMatthew G. Knepley PetscFunctionReturn(0); 165477623264SMatthew G. Knepley } 165577623264SMatthew G. Knepley 165677623264SMatthew G. Knepley /*MC 165777623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 165877623264SMatthew G. Knepley 165977623264SMatthew G. Knepley Level: intermediate 166077623264SMatthew G. Knepley 166177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 166277623264SMatthew G. Knepley M*/ 166377623264SMatthew G. Knepley 166477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 166577623264SMatthew G. Knepley { 166677623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 166777623264SMatthew G. Knepley PetscErrorCode ierr; 166877623264SMatthew G. Knepley 166977623264SMatthew G. Knepley PetscFunctionBegin; 167077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 167177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 167277623264SMatthew G. Knepley part->data = p; 167377623264SMatthew G. Knepley 167477623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 167577623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 167677623264SMatthew G. Knepley PetscFunctionReturn(0); 167777623264SMatthew G. Knepley } 167877623264SMatthew G. Knepley 16795b440754SMatthew G. Knepley static const char *ptypes[] = {"kway", "rb"}; 16805b440754SMatthew G. Knepley 1681d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 168277623264SMatthew G. Knepley { 168377623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 168477623264SMatthew G. Knepley PetscErrorCode ierr; 168577623264SMatthew G. Knepley 168677623264SMatthew G. Knepley PetscFunctionBegin; 168777623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 168877623264SMatthew G. Knepley PetscFunctionReturn(0); 168977623264SMatthew G. Knepley } 169077623264SMatthew G. Knepley 1691d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 169277623264SMatthew G. Knepley { 16932abdaa70SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 169477623264SMatthew G. Knepley PetscErrorCode ierr; 169577623264SMatthew G. Knepley 169677623264SMatthew G. Knepley PetscFunctionBegin; 16972abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 16982abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 16992abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 17002abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 17019d459c0eSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer, "random seed %D\n", p->randomSeed);CHKERRQ(ierr); 17022abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 170377623264SMatthew G. Knepley PetscFunctionReturn(0); 170477623264SMatthew G. Knepley } 170577623264SMatthew G. Knepley 1706d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 170777623264SMatthew G. Knepley { 170877623264SMatthew G. Knepley PetscBool iascii; 170977623264SMatthew G. Knepley PetscErrorCode ierr; 171077623264SMatthew G. Knepley 171177623264SMatthew G. Knepley PetscFunctionBegin; 171277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 171377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 171477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 171577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 171677623264SMatthew G. Knepley PetscFunctionReturn(0); 171777623264SMatthew G. Knepley } 171870034214SMatthew G. Knepley 171944d8be81SLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 172044d8be81SLisandro Dalcin { 172144d8be81SLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 172244d8be81SLisandro Dalcin PetscErrorCode ierr; 172344d8be81SLisandro Dalcin 172444d8be81SLisandro Dalcin PetscFunctionBegin; 172544d8be81SLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 172644d8be81SLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 17275b440754SMatthew G. Knepley ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 17285b440754SMatthew G. Knepley ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 17299d459c0eSStefano Zampini ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p->randomSeed, &p->randomSeed, NULL);CHKERRQ(ierr); 173044d8be81SLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 173144d8be81SLisandro Dalcin PetscFunctionReturn(0); 173244d8be81SLisandro Dalcin } 173344d8be81SLisandro Dalcin 173470034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 173570034214SMatthew G. Knepley #include <parmetis.h> 173677623264SMatthew G. Knepley #endif 173770034214SMatthew G. Knepley 1738d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 173970034214SMatthew G. Knepley { 174077623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 17415b440754SMatthew G. Knepley PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 174270034214SMatthew G. Knepley MPI_Comm comm; 1743deea36a5SMatthew G. Knepley PetscSection section; 174470034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 174570034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 174670034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 174770034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 174870034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 174970034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 175070034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 175170034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 175270034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 17535b440754SMatthew G. Knepley PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 1754fb83b9f2SMichael Gegg real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 1755fb83b9f2SMichael Gegg real_t *ubvec; /* The balance intolerance for vertex weights */ 1756b3ce585bSLisandro Dalcin PetscInt options[64]; /* Options */ 175770034214SMatthew G. Knepley /* Outputs */ 1758b3ce585bSLisandro Dalcin PetscInt v, i, *assignment, *points; 1759b3ce585bSLisandro Dalcin PetscMPIInt size, rank, p; 176070034214SMatthew G. Knepley PetscErrorCode ierr; 176170034214SMatthew G. Knepley 176270034214SMatthew G. Knepley PetscFunctionBegin; 176377623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 1764b3ce585bSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 176570034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 176670034214SMatthew G. Knepley /* Calculate vertex distribution */ 1767b3ce585bSLisandro Dalcin ierr = PetscMalloc5(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment,nvtxs,&vwgt);CHKERRQ(ierr); 176870034214SMatthew G. Knepley vtxdist[0] = 0; 176970034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1770b3ce585bSLisandro Dalcin for (p = 2; p <= size; ++p) { 177170034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 177270034214SMatthew G. Knepley } 177344d8be81SLisandro Dalcin /* Calculate partition weights */ 177470034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 177570034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 177670034214SMatthew G. Knepley } 17775b440754SMatthew G. Knepley ubvec[0] = pm->imbalanceRatio; 1778deea36a5SMatthew G. Knepley /* Weight cells by dofs on cell by default */ 177992fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 17808ef05d33SStefano Zampini for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1781deea36a5SMatthew G. Knepley if (section) { 1782deea36a5SMatthew G. Knepley PetscInt cStart, cEnd, dof; 178370034214SMatthew G. Knepley 1784925b1076SLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 1785925b1076SLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 17868ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 17878ef05d33SStefano Zampini for (v = cStart; v < cStart + numVertices; ++v) { 17888ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 17898ef05d33SStefano Zampini vwgt[v-cStart] = PetscMax(dof, 1); 1790deea36a5SMatthew G. Knepley } 1791cd0de0f2SShri } 179244d8be81SLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 1793cd0de0f2SShri 179470034214SMatthew G. Knepley if (nparts == 1) { 1795580bdb30SBarry Smith ierr = PetscArrayzero(assignment, nvtxs);CHKERRQ(ierr); 179670034214SMatthew G. Knepley } else { 1797b3ce585bSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 1798b3ce585bSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 1799b3ce585bSLisandro Dalcin if (rank == p) { 180044d8be81SLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 180142678178SLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 18029d459c0eSStefano Zampini options[METIS_OPTION_SEED] = pm->randomSeed; 180344d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 180444d8be81SLisandro Dalcin if (metis_ptype == 1) { 180544d8be81SLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 180672379da4SMatthew G. Knepley ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 180744d8be81SLisandro Dalcin PetscStackPop; 180844d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 180944d8be81SLisandro Dalcin } else { 181044d8be81SLisandro Dalcin /* 181144d8be81SLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 181244d8be81SLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 181344d8be81SLisandro 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. 181444d8be81SLisandro Dalcin */ 181544d8be81SLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 181644d8be81SLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 181770034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 181872379da4SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 181970034214SMatthew G. Knepley PetscStackPop; 182070034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 182170034214SMatthew G. Knepley } 182244d8be81SLisandro Dalcin } 182370034214SMatthew G. Knepley } else { 182442678178SLisandro Dalcin options[0] = 1; /*use options */ 18255b440754SMatthew G. Knepley options[1] = pm->debugFlag; 18269d459c0eSStefano Zampini options[2] = (pm->randomSeed == -1) ? 15 : pm->randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 182770034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 182872379da4SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &comm); 182970034214SMatthew G. Knepley PetscStackPop; 1830c717d290SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 183170034214SMatthew G. Knepley } 183270034214SMatthew G. Knepley } 183370034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 183477623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 183577623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 183677623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 183770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 183877623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 183970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 184070034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 184170034214SMatthew G. Knepley } 184270034214SMatthew G. Knepley } 184370034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 184470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1845cd0de0f2SShri ierr = PetscFree5(vtxdist,tpwgts,ubvec,assignment,vwgt);CHKERRQ(ierr); 18469b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 184770034214SMatthew G. Knepley #else 184877623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 184970034214SMatthew G. Knepley #endif 185070034214SMatthew G. Knepley } 185170034214SMatthew G. Knepley 1852d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 185377623264SMatthew G. Knepley { 185477623264SMatthew G. Knepley PetscFunctionBegin; 1855074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 185677623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 185744d8be81SLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 185877623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 185977623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 186077623264SMatthew G. Knepley PetscFunctionReturn(0); 186177623264SMatthew G. Knepley } 186277623264SMatthew G. Knepley 186377623264SMatthew G. Knepley /*MC 186477623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 186577623264SMatthew G. Knepley 186677623264SMatthew G. Knepley Level: intermediate 186777623264SMatthew G. Knepley 186877623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 186977623264SMatthew G. Knepley M*/ 187077623264SMatthew G. Knepley 187177623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 187277623264SMatthew G. Knepley { 187377623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 187477623264SMatthew G. Knepley PetscErrorCode ierr; 187577623264SMatthew G. Knepley 187677623264SMatthew G. Knepley PetscFunctionBegin; 187777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 187877623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 187977623264SMatthew G. Knepley part->data = p; 188077623264SMatthew G. Knepley 18815b440754SMatthew G. Knepley p->ptype = 0; 18825b440754SMatthew G. Knepley p->imbalanceRatio = 1.05; 18835b440754SMatthew G. Knepley p->debugFlag = 0; 18849d459c0eSStefano Zampini p->randomSeed = -1; /* defaults to GLOBAL_SEED=15 from `libparmetis/defs.h` */ 18855b440754SMatthew G. Knepley 188677623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 188777623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 188870034214SMatthew G. Knepley PetscFunctionReturn(0); 188970034214SMatthew G. Knepley } 189070034214SMatthew G. Knepley 1891137cd93aSLisandro Dalcin PetscBool PTScotchPartitionercite = PETSC_FALSE; 1892137cd93aSLisandro Dalcin const char PTScotchPartitionerCitation[] = 1893137cd93aSLisandro Dalcin "@article{PTSCOTCH,\n" 1894137cd93aSLisandro Dalcin " author = {C. Chevalier and F. Pellegrini},\n" 1895137cd93aSLisandro Dalcin " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 1896137cd93aSLisandro Dalcin " journal = {Parallel Computing},\n" 1897137cd93aSLisandro Dalcin " volume = {34},\n" 1898137cd93aSLisandro Dalcin " number = {6},\n" 1899137cd93aSLisandro Dalcin " pages = {318--331},\n" 1900137cd93aSLisandro Dalcin " year = {2008},\n" 1901137cd93aSLisandro Dalcin " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 1902137cd93aSLisandro Dalcin "}\n"; 1903137cd93aSLisandro Dalcin 1904137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 1905137cd93aSLisandro Dalcin 1906137cd93aSLisandro Dalcin EXTERN_C_BEGIN 1907137cd93aSLisandro Dalcin #include <ptscotch.h> 1908137cd93aSLisandro Dalcin EXTERN_C_END 1909137cd93aSLisandro Dalcin 1910137cd93aSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 1911137cd93aSLisandro Dalcin 1912137cd93aSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 1913137cd93aSLisandro Dalcin { 1914137cd93aSLisandro Dalcin switch (strategy) { 1915137cd93aSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 1916137cd93aSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 1917137cd93aSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 1918137cd93aSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 1919137cd93aSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 1920137cd93aSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 1921137cd93aSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 1922137cd93aSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 1923137cd93aSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 1924137cd93aSLisandro Dalcin } 1925137cd93aSLisandro Dalcin } 1926137cd93aSLisandro Dalcin 1927137cd93aSLisandro Dalcin 1928137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1929137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[]) 1930137cd93aSLisandro Dalcin { 1931137cd93aSLisandro Dalcin SCOTCH_Graph grafdat; 1932137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1933137cd93aSLisandro Dalcin SCOTCH_Num vertnbr = n; 1934137cd93aSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 1935137cd93aSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 1936137cd93aSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 1937137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1938137cd93aSLisandro Dalcin double kbalval = imbalance; 1939137cd93aSLisandro Dalcin PetscErrorCode ierr; 1940137cd93aSLisandro Dalcin 1941137cd93aSLisandro Dalcin PetscFunctionBegin; 1942d99a0000SVaclav Hapla { 1943d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1944d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1945d99a0000SVaclav Hapla if (!flg) velotab = NULL; 1946d99a0000SVaclav Hapla } 1947137cd93aSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 1948137cd93aSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 1949137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1950137cd93aSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 1951137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1952137cd93aSLisandro Dalcin ierr = SCOTCH_graphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1953137cd93aSLisandro Dalcin #endif 1954137cd93aSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 1955137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 1956137cd93aSLisandro Dalcin SCOTCH_graphExit(&grafdat); 1957137cd93aSLisandro Dalcin PetscFunctionReturn(0); 1958137cd93aSLisandro Dalcin } 1959137cd93aSLisandro Dalcin 1960137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 1961137cd93aSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num part[], MPI_Comm comm) 1962137cd93aSLisandro Dalcin { 1963137cd93aSLisandro Dalcin PetscMPIInt procglbnbr; 1964137cd93aSLisandro Dalcin PetscMPIInt proclocnum; 1965137cd93aSLisandro Dalcin SCOTCH_Arch archdat; 1966137cd93aSLisandro Dalcin SCOTCH_Dgraph grafdat; 1967137cd93aSLisandro Dalcin SCOTCH_Dmapping mappdat; 1968137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 1969137cd93aSLisandro Dalcin SCOTCH_Num vertlocnbr; 1970137cd93aSLisandro Dalcin SCOTCH_Num edgelocnbr; 1971137cd93aSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 1972137cd93aSLisandro Dalcin SCOTCH_Num* edloloctab = adjwgt; 1973137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 1974137cd93aSLisandro Dalcin double kbalval = imbalance; 1975137cd93aSLisandro Dalcin PetscErrorCode ierr; 1976137cd93aSLisandro Dalcin 1977137cd93aSLisandro Dalcin PetscFunctionBegin; 1978d99a0000SVaclav Hapla { 1979d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 1980d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 1981d99a0000SVaclav Hapla if (!flg) veloloctab = NULL; 1982d99a0000SVaclav Hapla } 1983137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 1984137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 1985137cd93aSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 1986137cd93aSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 1987137cd93aSLisandro Dalcin 1988137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 1989137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 1990137cd93aSLisandro Dalcin #if defined(PETSC_USE_DEBUG) 1991137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphCheck(&grafdat);CHKERRPTSCOTCH(ierr); 1992137cd93aSLisandro Dalcin #endif 1993137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 1994137cd93aSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 1995137cd93aSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 1996137cd93aSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 1997137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 1998cb87ef4cSFlorian Wechsung 1999137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 2000137cd93aSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 2001137cd93aSLisandro Dalcin SCOTCH_archExit(&archdat); 2002137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 2003137cd93aSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 2004137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2005137cd93aSLisandro Dalcin } 2006137cd93aSLisandro Dalcin 2007137cd93aSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 2008137cd93aSLisandro Dalcin 2009137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 2010137cd93aSLisandro Dalcin { 2011137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2012137cd93aSLisandro Dalcin PetscErrorCode ierr; 2013137cd93aSLisandro Dalcin 2014137cd93aSLisandro Dalcin PetscFunctionBegin; 2015137cd93aSLisandro Dalcin ierr = PetscFree(p);CHKERRQ(ierr); 2016137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2017137cd93aSLisandro Dalcin } 2018137cd93aSLisandro Dalcin 2019137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_Ascii(PetscPartitioner part, PetscViewer viewer) 2020137cd93aSLisandro Dalcin { 2021137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2022137cd93aSLisandro Dalcin PetscErrorCode ierr; 2023137cd93aSLisandro Dalcin 2024137cd93aSLisandro Dalcin PetscFunctionBegin; 2025137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2026137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 2027137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 2028137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2029137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2030137cd93aSLisandro Dalcin } 2031137cd93aSLisandro Dalcin 2032137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 2033137cd93aSLisandro Dalcin { 2034137cd93aSLisandro Dalcin PetscBool iascii; 2035137cd93aSLisandro Dalcin PetscErrorCode ierr; 2036137cd93aSLisandro Dalcin 2037137cd93aSLisandro Dalcin PetscFunctionBegin; 2038137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2039137cd93aSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2040137cd93aSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 2041137cd93aSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_Ascii(part, viewer);CHKERRQ(ierr);} 2042137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2043137cd93aSLisandro Dalcin } 2044137cd93aSLisandro Dalcin 2045137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 2046137cd93aSLisandro Dalcin { 2047137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2048137cd93aSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 2049137cd93aSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 2050137cd93aSLisandro Dalcin PetscBool flag; 2051137cd93aSLisandro Dalcin PetscErrorCode ierr; 2052137cd93aSLisandro Dalcin 2053137cd93aSLisandro Dalcin PetscFunctionBegin; 2054137cd93aSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 2055137cd93aSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 2056137cd93aSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 2057137cd93aSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 2058137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2059137cd93aSLisandro Dalcin } 2060137cd93aSLisandro Dalcin 2061137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 2062137cd93aSLisandro Dalcin { 2063137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 2064137cd93aSLisandro Dalcin MPI_Comm comm = PetscObjectComm((PetscObject)part); 2065137cd93aSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 2066137cd93aSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 2067137cd93aSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 2068137cd93aSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 2069137cd93aSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 2070137cd93aSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 2071137cd93aSLisandro Dalcin PetscInt v, i, *assignment, *points; 2072137cd93aSLisandro Dalcin PetscMPIInt size, rank, p; 2073137cd93aSLisandro Dalcin PetscErrorCode ierr; 2074137cd93aSLisandro Dalcin 2075137cd93aSLisandro Dalcin PetscFunctionBegin; 2076137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2077137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 207899b53901SStefano Zampini ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 2079137cd93aSLisandro Dalcin 2080137cd93aSLisandro Dalcin /* Calculate vertex distribution */ 2081137cd93aSLisandro Dalcin vtxdist[0] = 0; 2082137cd93aSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2083137cd93aSLisandro Dalcin for (p = 2; p <= size; ++p) { 2084137cd93aSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 2085137cd93aSLisandro Dalcin } 2086137cd93aSLisandro Dalcin 2087137cd93aSLisandro Dalcin if (nparts == 1) { 2088580bdb30SBarry Smith ierr = PetscArrayzero(assignment, nvtxs);CHKERRQ(ierr); 20898ef05d33SStefano Zampini } else { /* Weight cells by dofs on cell by default */ 2090137cd93aSLisandro Dalcin PetscSection section; 20918ef05d33SStefano Zampini 2092137cd93aSLisandro Dalcin /* WARNING: Assumes that meshes with overlap have the overlapped cells at the end of the stratum. */ 2093137cd93aSLisandro Dalcin /* To do this properly, we should use the cell numbering created in DMPlexCreatePartitionerGraph. */ 20948ef05d33SStefano Zampini ierr = PetscMalloc1(PetscMax(nvtxs,1),&vwgt);CHKERRQ(ierr); 20958ef05d33SStefano Zampini for (v = 0; v < PetscMax(nvtxs,1); ++v) vwgt[v] = 1; 209692fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 20978ef05d33SStefano Zampini if (section) { 20988ef05d33SStefano Zampini PetscInt vStart, vEnd, dof; 20998ef05d33SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &vStart, &vEnd);CHKERRQ(ierr); 21008ef05d33SStefano Zampini for (v = vStart; v < vStart + numVertices; ++v) { 21018ef05d33SStefano Zampini ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 21028ef05d33SStefano Zampini vwgt[v-vStart] = PetscMax(dof, 1); 2103137cd93aSLisandro Dalcin } 2104137cd93aSLisandro Dalcin } 2105137cd93aSLisandro Dalcin { 2106137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 2107137cd93aSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 2108137cd93aSLisandro Dalcin double imbal = (double)pts->imbalance; 2109137cd93aSLisandro Dalcin 2110137cd93aSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 2111137cd93aSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 2112137cd93aSLisandro Dalcin if (rank == p) { 2113137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, assignment);CHKERRQ(ierr); 2114137cd93aSLisandro Dalcin } 2115137cd93aSLisandro Dalcin } else { 2116137cd93aSLisandro Dalcin ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, assignment, comm);CHKERRQ(ierr); 2117137cd93aSLisandro Dalcin } 2118137cd93aSLisandro Dalcin } 2119137cd93aSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 2120137cd93aSLisandro Dalcin } 2121137cd93aSLisandro Dalcin 2122137cd93aSLisandro Dalcin /* Convert to PetscSection+IS */ 2123137cd93aSLisandro Dalcin ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 2124137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 2125137cd93aSLisandro Dalcin ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 2126137cd93aSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 2127137cd93aSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 2128137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 2129137cd93aSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 2130137cd93aSLisandro Dalcin } 2131137cd93aSLisandro Dalcin } 2132137cd93aSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2133137cd93aSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2134137cd93aSLisandro Dalcin 2135137cd93aSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 2136137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2137137cd93aSLisandro Dalcin #else 2138137cd93aSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 2139137cd93aSLisandro Dalcin #endif 2140137cd93aSLisandro Dalcin } 2141137cd93aSLisandro Dalcin 2142137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 2143137cd93aSLisandro Dalcin { 2144137cd93aSLisandro Dalcin PetscFunctionBegin; 2145074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 2146137cd93aSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 2147137cd93aSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 2148137cd93aSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 2149137cd93aSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 2150137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2151137cd93aSLisandro Dalcin } 2152137cd93aSLisandro Dalcin 2153137cd93aSLisandro Dalcin /*MC 2154137cd93aSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 2155137cd93aSLisandro Dalcin 2156137cd93aSLisandro Dalcin Level: intermediate 2157137cd93aSLisandro Dalcin 2158137cd93aSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 2159137cd93aSLisandro Dalcin M*/ 2160137cd93aSLisandro Dalcin 2161137cd93aSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 2162137cd93aSLisandro Dalcin { 2163137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p; 2164137cd93aSLisandro Dalcin PetscErrorCode ierr; 2165137cd93aSLisandro Dalcin 2166137cd93aSLisandro Dalcin PetscFunctionBegin; 2167137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2168137cd93aSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 2169137cd93aSLisandro Dalcin part->data = p; 2170137cd93aSLisandro Dalcin 2171137cd93aSLisandro Dalcin p->strategy = 0; 2172137cd93aSLisandro Dalcin p->imbalance = 0.01; 2173137cd93aSLisandro Dalcin 2174137cd93aSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 2175137cd93aSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionercite);CHKERRQ(ierr); 2176137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2177137cd93aSLisandro Dalcin } 2178137cd93aSLisandro Dalcin 2179137cd93aSLisandro Dalcin 21805680f57bSMatthew G. Knepley /*@ 21815680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 21825680f57bSMatthew G. Knepley 21835680f57bSMatthew G. Knepley Not collective 21845680f57bSMatthew G. Knepley 21855680f57bSMatthew G. Knepley Input Parameter: 21865680f57bSMatthew G. Knepley . dm - The DM 21875680f57bSMatthew G. Knepley 21885680f57bSMatthew G. Knepley Output Parameter: 21895680f57bSMatthew G. Knepley . part - The PetscPartitioner 21905680f57bSMatthew G. Knepley 21915680f57bSMatthew G. Knepley Level: developer 21925680f57bSMatthew G. Knepley 219398599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 219498599a47SLawrence Mitchell 219598599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 21965680f57bSMatthew G. Knepley @*/ 21975680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 21985680f57bSMatthew G. Knepley { 21995680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 22005680f57bSMatthew G. Knepley 22015680f57bSMatthew G. Knepley PetscFunctionBegin; 22025680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22035680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 22045680f57bSMatthew G. Knepley *part = mesh->partitioner; 22055680f57bSMatthew G. Knepley PetscFunctionReturn(0); 22065680f57bSMatthew G. Knepley } 22075680f57bSMatthew G. Knepley 220871bb2955SLawrence Mitchell /*@ 220971bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 221071bb2955SLawrence Mitchell 2211d083f849SBarry Smith logically collective on dm 221271bb2955SLawrence Mitchell 221371bb2955SLawrence Mitchell Input Parameters: 221471bb2955SLawrence Mitchell + dm - The DM 221571bb2955SLawrence Mitchell - part - The partitioner 221671bb2955SLawrence Mitchell 221771bb2955SLawrence Mitchell Level: developer 221871bb2955SLawrence Mitchell 221971bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 222071bb2955SLawrence Mitchell 222171bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 222271bb2955SLawrence Mitchell @*/ 222371bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 222471bb2955SLawrence Mitchell { 222571bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 222671bb2955SLawrence Mitchell PetscErrorCode ierr; 222771bb2955SLawrence Mitchell 222871bb2955SLawrence Mitchell PetscFunctionBegin; 222971bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 223071bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 223171bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 223271bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 223371bb2955SLawrence Mitchell mesh->partitioner = part; 223471bb2955SLawrence Mitchell PetscFunctionReturn(0); 223571bb2955SLawrence Mitchell } 223671bb2955SLawrence Mitchell 22378e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 22388e330a33SStefano Zampini { 22398e330a33SStefano Zampini const PetscInt *cone; 22408e330a33SStefano Zampini PetscInt coneSize, c; 22418e330a33SStefano Zampini PetscBool missing; 22428e330a33SStefano Zampini PetscErrorCode ierr; 22438e330a33SStefano Zampini 22448e330a33SStefano Zampini PetscFunctionBeginHot; 22458e330a33SStefano Zampini ierr = PetscHSetIQueryAdd(ht, point, &missing);CHKERRQ(ierr); 22468e330a33SStefano Zampini if (missing) { 22478e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 22488e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 22498e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 22508e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, cone[c]);CHKERRQ(ierr); 22518e330a33SStefano Zampini } 22528e330a33SStefano Zampini } 22538e330a33SStefano Zampini PetscFunctionReturn(0); 22548e330a33SStefano Zampini } 22558e330a33SStefano Zampini 22568e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 2257270bba0cSToby Isaac { 2258270bba0cSToby Isaac PetscErrorCode ierr; 2259270bba0cSToby Isaac 2260270bba0cSToby Isaac PetscFunctionBegin; 22616a5a2ffdSToby Isaac if (up) { 22626a5a2ffdSToby Isaac PetscInt parent; 22636a5a2ffdSToby Isaac 2264270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 22656a5a2ffdSToby Isaac if (parent != point) { 22666a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 22676a5a2ffdSToby Isaac 2268270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2269270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 2270270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 2271270bba0cSToby Isaac 2272e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 22731b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 2274270bba0cSToby Isaac } 2275270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 22766a5a2ffdSToby Isaac } 22776a5a2ffdSToby Isaac } 22786a5a2ffdSToby Isaac if (down) { 22796a5a2ffdSToby Isaac PetscInt numChildren; 22806a5a2ffdSToby Isaac const PetscInt *children; 22816a5a2ffdSToby Isaac 22826a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 22836a5a2ffdSToby Isaac if (numChildren) { 22846a5a2ffdSToby Isaac PetscInt i; 22856a5a2ffdSToby Isaac 22866a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 22876a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 22886a5a2ffdSToby Isaac 2289e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 22901b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 22916a5a2ffdSToby Isaac } 22926a5a2ffdSToby Isaac } 22936a5a2ffdSToby Isaac } 2294270bba0cSToby Isaac PetscFunctionReturn(0); 2295270bba0cSToby Isaac } 2296270bba0cSToby Isaac 22978e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 22988e330a33SStefano Zampini { 22998e330a33SStefano Zampini PetscInt parent; 23008e330a33SStefano Zampini PetscErrorCode ierr; 2301825f8a23SLisandro Dalcin 23028e330a33SStefano Zampini PetscFunctionBeginHot; 23038e330a33SStefano Zampini ierr = DMPlexGetTreeParent(dm, point, &parent,NULL);CHKERRQ(ierr); 23048e330a33SStefano Zampini if (point != parent) { 23058e330a33SStefano Zampini const PetscInt *cone; 23068e330a33SStefano Zampini PetscInt coneSize, c; 23078e330a33SStefano Zampini 23088e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, parent);CHKERRQ(ierr); 23098e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, parent);CHKERRQ(ierr); 23108e330a33SStefano Zampini ierr = DMPlexGetCone(dm, parent, &cone);CHKERRQ(ierr); 23118e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, parent, &coneSize);CHKERRQ(ierr); 23128e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 23138e330a33SStefano Zampini const PetscInt cp = cone[c]; 23148e330a33SStefano Zampini 23158e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, cp);CHKERRQ(ierr); 23168e330a33SStefano Zampini } 23178e330a33SStefano Zampini } 23188e330a33SStefano Zampini PetscFunctionReturn(0); 23198e330a33SStefano Zampini } 23208e330a33SStefano Zampini 23218e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 23228e330a33SStefano Zampini { 23238e330a33SStefano Zampini PetscInt i, numChildren; 23248e330a33SStefano Zampini const PetscInt *children; 23258e330a33SStefano Zampini PetscErrorCode ierr; 23268e330a33SStefano Zampini 23278e330a33SStefano Zampini PetscFunctionBeginHot; 23288e330a33SStefano Zampini ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 23298e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 23308e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, children[i]);CHKERRQ(ierr); 23318e330a33SStefano Zampini } 23328e330a33SStefano Zampini PetscFunctionReturn(0); 23338e330a33SStefano Zampini } 23348e330a33SStefano Zampini 23358e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 23368e330a33SStefano Zampini { 23378e330a33SStefano Zampini const PetscInt *cone; 23388e330a33SStefano Zampini PetscInt coneSize, c; 23398e330a33SStefano Zampini PetscErrorCode ierr; 23408e330a33SStefano Zampini 23418e330a33SStefano Zampini PetscFunctionBeginHot; 23428e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, point);CHKERRQ(ierr); 23438e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, point);CHKERRQ(ierr); 23448e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Down_Private(dm, ht, point);CHKERRQ(ierr); 23458e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 23468e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 23478e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 23488e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, cone[c]);CHKERRQ(ierr); 23498e330a33SStefano Zampini } 23508e330a33SStefano Zampini PetscFunctionReturn(0); 23518e330a33SStefano Zampini } 23528e330a33SStefano Zampini 23538e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 2354825f8a23SLisandro Dalcin { 2355825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 23568e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 23578e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 2358825f8a23SLisandro Dalcin PetscHSetI ht; 2359825f8a23SLisandro Dalcin PetscErrorCode ierr; 2360825f8a23SLisandro Dalcin 2361825f8a23SLisandro Dalcin PetscFunctionBegin; 2362825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 2363825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 23648e330a33SStefano Zampini if (!hasTree) { 23658e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 23668e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, points[p]);CHKERRQ(ierr); 23678e330a33SStefano Zampini } 23688e330a33SStefano Zampini } else { 23698e330a33SStefano Zampini #if 1 23708e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 23718e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, points[p]);CHKERRQ(ierr); 23728e330a33SStefano Zampini } 23738e330a33SStefano Zampini #else 23748e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 2375825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 2376825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2377825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 2378825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 2379825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 2380825f8a23SLisandro Dalcin } 2381825f8a23SLisandro Dalcin } 2382825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 23838e330a33SStefano Zampini #endif 23848e330a33SStefano Zampini } 2385825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 2386825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 2387825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 2388825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 2389825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 2390825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 2391825f8a23SLisandro Dalcin PetscFunctionReturn(0); 2392825f8a23SLisandro Dalcin } 2393825f8a23SLisandro Dalcin 23945abbe4feSMichael Lange /*@ 23955abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 23965abbe4feSMichael Lange 23975abbe4feSMichael Lange Input Parameters: 23985abbe4feSMichael Lange + dm - The DM 23995abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 24005abbe4feSMichael Lange 24015abbe4feSMichael Lange Level: developer 24025abbe4feSMichael Lange 240330b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 24045abbe4feSMichael Lange @*/ 24055abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 24069ffc88e4SToby Isaac { 2407825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 24085abbe4feSMichael Lange const PetscInt *ranks, *points; 2409825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 24109ffc88e4SToby Isaac PetscErrorCode ierr; 24119ffc88e4SToby Isaac 24129ffc88e4SToby Isaac PetscFunctionBegin; 24135abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 24145abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 24155abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 24165abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 24175abbe4feSMichael Lange const PetscInt rank = ranks[r]; 24185abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 24195abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 24205abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 24218e330a33SStefano Zampini ierr = DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS);CHKERRQ(ierr); 24225abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 24235abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2424825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 2425825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 24269ffc88e4SToby Isaac } 24275abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 24285abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 24299ffc88e4SToby Isaac PetscFunctionReturn(0); 24309ffc88e4SToby Isaac } 24319ffc88e4SToby Isaac 243224d039d7SMichael Lange /*@ 243324d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 243424d039d7SMichael Lange 243524d039d7SMichael Lange Input Parameters: 243624d039d7SMichael Lange + dm - The DM 243724d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 243824d039d7SMichael Lange 243924d039d7SMichael Lange Level: developer 244024d039d7SMichael Lange 244124d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 244224d039d7SMichael Lange @*/ 244324d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 244470034214SMatthew G. Knepley { 244524d039d7SMichael Lange IS rankIS, pointIS; 244624d039d7SMichael Lange const PetscInt *ranks, *points; 244724d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 244824d039d7SMichael Lange PetscInt *adj = NULL; 244970034214SMatthew G. Knepley PetscErrorCode ierr; 245070034214SMatthew G. Knepley 245170034214SMatthew G. Knepley PetscFunctionBegin; 245224d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 245324d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 245424d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 245524d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 245624d039d7SMichael Lange const PetscInt rank = ranks[r]; 245770034214SMatthew G. Knepley 245824d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 245924d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 246024d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 246170034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 246224d039d7SMichael Lange adjSize = PETSC_DETERMINE; 246324d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 246424d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 246570034214SMatthew G. Knepley } 246624d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 246724d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 246870034214SMatthew G. Knepley } 246924d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 247024d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 247124d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 247224d039d7SMichael Lange PetscFunctionReturn(0); 247370034214SMatthew G. Knepley } 247470034214SMatthew G. Knepley 2475be200f8dSMichael Lange /*@ 2476be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 2477be200f8dSMichael Lange 2478be200f8dSMichael Lange Input Parameters: 2479be200f8dSMichael Lange + dm - The DM 2480be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 2481be200f8dSMichael Lange 2482be200f8dSMichael Lange Level: developer 2483be200f8dSMichael Lange 2484be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 2485be200f8dSMichael Lange overlap points from non-neighbouring partitions. 2486be200f8dSMichael Lange 2487be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 2488be200f8dSMichael Lange @*/ 2489be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 2490be200f8dSMichael Lange { 2491be200f8dSMichael Lange MPI_Comm comm; 2492be200f8dSMichael Lange PetscMPIInt rank; 2493be200f8dSMichael Lange PetscSF sfPoint; 24945d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 2495be200f8dSMichael Lange IS rankIS, pointIS; 2496be200f8dSMichael Lange const PetscInt *ranks; 2497be200f8dSMichael Lange PetscInt numRanks, r; 2498be200f8dSMichael Lange PetscErrorCode ierr; 2499be200f8dSMichael Lange 2500be200f8dSMichael Lange PetscFunctionBegin; 2501be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2502be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2503be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 25045d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 25055d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 25065d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 25075d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 25085d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 25095d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 25105d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 25115d04f6ebSMichael Lange if (remoteRank == rank) continue; 25125d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 25135d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 25145d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 25155d04f6ebSMichael Lange } 25165d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 25175d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 25185d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 2519be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 2520be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 2521be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 2522be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 2523be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 2524be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 2525be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 2526be200f8dSMichael Lange if (remoteRank == rank) continue; 2527be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 2528be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 2529be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2530be200f8dSMichael Lange } 2531be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 2532be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 2533be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 2534be200f8dSMichael Lange PetscFunctionReturn(0); 2535be200f8dSMichael Lange } 2536be200f8dSMichael Lange 25371fd9873aSMichael Lange /*@ 25381fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 25391fd9873aSMichael Lange 25401fd9873aSMichael Lange Input Parameters: 25411fd9873aSMichael Lange + dm - The DM 25421fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 25431fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 25441fd9873aSMichael Lange 25451fd9873aSMichael Lange Output Parameter: 25461fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 25471fd9873aSMichael Lange 25481fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 25491fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 25501fd9873aSMichael Lange 25511fd9873aSMichael Lange Level: developer 25521fd9873aSMichael Lange 25531fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 25541fd9873aSMichael Lange @*/ 25551fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 25561fd9873aSMichael Lange { 25571fd9873aSMichael Lange MPI_Comm comm; 2558874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 2559874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 25601fd9873aSMichael Lange PetscSF sfPoint; 2561874ddda9SLisandro Dalcin PetscSection rootSection; 25621fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 25631fd9873aSMichael Lange const PetscSFNode *remote; 25641fd9873aSMichael Lange const PetscInt *local, *neighbors; 25651fd9873aSMichael Lange IS valueIS; 2566874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 25671fd9873aSMichael Lange PetscErrorCode ierr; 25681fd9873aSMichael Lange 25691fd9873aSMichael Lange PetscFunctionBegin; 257030b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 25711fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 25721fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 25739852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 25741fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 25751fd9873aSMichael Lange 25761fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 25771fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 25789852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 25791fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 25801fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 25811fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 25821fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 25831fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 25841fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 25851fd9873aSMichael Lange } 25861fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 2587874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 2588874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 25891fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 25901fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 25911fd9873aSMichael Lange IS pointIS; 25921fd9873aSMichael Lange const PetscInt *points; 25931fd9873aSMichael Lange 25941fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 25951fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 25961fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 25971fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 25981fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 2599f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 2600f8987ae8SMichael Lange else {l = -1;} 26011fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 26021fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 26031fd9873aSMichael Lange } 26041fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 26051fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 26061fd9873aSMichael Lange } 2607874ddda9SLisandro Dalcin 2608874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 2609874ddda9SLisandro Dalcin if (!processSF) { 2610874ddda9SLisandro Dalcin PetscInt64 counter = 0; 2611874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 2612874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 2613874ddda9SLisandro Dalcin 2614874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 2615874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 2616874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 2617874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 2618874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 2619874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2620874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2621874ddda9SLisandro Dalcin #endif 2622874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 2623874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 2624874ddda9SLisandro Dalcin } 2625874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 2626874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 2627874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 2628874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 2629874ddda9SLisandro Dalcin if (!mpiOverflow) { 263094b10faeSStefano Zampini ierr = PetscInfo(dm,"Using Alltoallv for mesh distribution\n");CHKERRQ(ierr); 2631874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 2632874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 2633874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 2634874ddda9SLisandro Dalcin } 2635874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 2636874ddda9SLisandro Dalcin } 2637874ddda9SLisandro Dalcin 2638874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 2639874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 2640874ddda9SLisandro Dalcin PetscSF procSF; 2641874ddda9SLisandro Dalcin PetscSection leafSection; 2642874ddda9SLisandro Dalcin 2643874ddda9SLisandro Dalcin if (processSF) { 264494b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution\n");CHKERRQ(ierr); 2645874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 2646874ddda9SLisandro Dalcin procSF = processSF; 2647874ddda9SLisandro Dalcin } else { 264894b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n");CHKERRQ(ierr); 2649874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm,&procSF);CHKERRQ(ierr); 2650900e0f05SJunchao Zhang ierr = PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr); 2651874ddda9SLisandro Dalcin } 2652874ddda9SLisandro Dalcin 2653874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 2654900e0f05SJunchao Zhang ierr = DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 2655874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 2656874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 2657874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 2658874ddda9SLisandro Dalcin } 2659874ddda9SLisandro Dalcin 2660874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 26611fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 26621fd9873aSMichael Lange } 2663874ddda9SLisandro Dalcin 2664874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 2665874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 26661fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 2667874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 26681fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 266930b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 26701fd9873aSMichael Lange PetscFunctionReturn(0); 26711fd9873aSMichael Lange } 26721fd9873aSMichael Lange 2673aa3148a8SMichael Lange /*@ 2674aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 2675aa3148a8SMichael Lange 2676aa3148a8SMichael Lange Input Parameters: 2677aa3148a8SMichael Lange + dm - The DM 2678aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 2679aa3148a8SMichael Lange 2680aa3148a8SMichael Lange Output Parameter: 2681aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 2682aa3148a8SMichael Lange 2683aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 2684aa3148a8SMichael Lange 2685aa3148a8SMichael Lange Level: developer 2686aa3148a8SMichael Lange 268730b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 2688aa3148a8SMichael Lange @*/ 2689aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 2690aa3148a8SMichael Lange { 26916e203dd9SStefano Zampini PetscMPIInt rank; 26926e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 2693aa3148a8SMichael Lange PetscSFNode *remotePoints; 26946e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 26956e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 2696aa3148a8SMichael Lange PetscErrorCode ierr; 2697aa3148a8SMichael Lange 2698aa3148a8SMichael Lange PetscFunctionBegin; 269930b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 270043f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 2701aa3148a8SMichael Lange 27026e203dd9SStefano Zampini ierr = DMLabelGetValueIS(label, &neighborsIS);CHKERRQ(ierr); 27036e203dd9SStefano Zampini #if 0 27046e203dd9SStefano Zampini { 27056e203dd9SStefano Zampini IS is; 27066e203dd9SStefano Zampini ierr = ISDuplicate(neighborsIS, &is);CHKERRQ(ierr); 27076e203dd9SStefano Zampini ierr = ISSort(is);CHKERRQ(ierr); 27086e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 27096e203dd9SStefano Zampini neighborsIS = is; 27106e203dd9SStefano Zampini } 27116e203dd9SStefano Zampini #endif 27126e203dd9SStefano Zampini ierr = ISGetLocalSize(neighborsIS, &nNeighbors);CHKERRQ(ierr); 27136e203dd9SStefano Zampini ierr = ISGetIndices(neighborsIS, &neighbors);CHKERRQ(ierr); 27146e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 27156e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, neighbors[n], &numPoints);CHKERRQ(ierr); 2716aa3148a8SMichael Lange numRemote += numPoints; 2717aa3148a8SMichael Lange } 2718aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 271943f7d02bSMichael Lange /* Put owned points first */ 272043f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 272143f7d02bSMichael Lange if (numPoints > 0) { 272243f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 272343f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 272443f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 272543f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 272643f7d02bSMichael Lange remotePoints[idx].rank = rank; 272743f7d02bSMichael Lange idx++; 272843f7d02bSMichael Lange } 272943f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 273043f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 273143f7d02bSMichael Lange } 273243f7d02bSMichael Lange /* Now add remote points */ 27336e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 27346e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 27356e203dd9SStefano Zampini 27366e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, nn, &numPoints);CHKERRQ(ierr); 27376e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 27386e203dd9SStefano Zampini ierr = DMLabelGetStratumIS(label, nn, &remoteRootIS);CHKERRQ(ierr); 2739aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2740aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 2741aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 27426e203dd9SStefano Zampini remotePoints[idx].rank = nn; 2743aa3148a8SMichael Lange idx++; 2744aa3148a8SMichael Lange } 2745aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 2746aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 2747aa3148a8SMichael Lange } 2748aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 2749aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2750aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 275130b0ce1bSStefano Zampini ierr = PetscSFSetUp(*sf);CHKERRQ(ierr); 27526e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 275330b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 275470034214SMatthew G. Knepley PetscFunctionReturn(0); 275570034214SMatthew G. Knepley } 2756cb87ef4cSFlorian Wechsung 27576a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 27586a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 27596a3739e5SFlorian Wechsung * them out in that case. */ 27606a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 27617a82c785SFlorian Wechsung /*@C 27627f57c1a4SFlorian Wechsung 27637f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 27647f57c1a4SFlorian Wechsung 27657f57c1a4SFlorian Wechsung Input parameters: 27667f57c1a4SFlorian Wechsung + dm - The DMPlex object. 27677f57c1a4SFlorian Wechsung + n - The number of points. 27687f57c1a4SFlorian Wechsung + pointsToRewrite - The points in the SF whose ownership will change. 27697f57c1a4SFlorian Wechsung + targetOwners - New owner for each element in pointsToRewrite. 27707f57c1a4SFlorian Wechsung + degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 27717f57c1a4SFlorian Wechsung 27727f57c1a4SFlorian Wechsung Level: developer 27737f57c1a4SFlorian Wechsung 27747f57c1a4SFlorian Wechsung @*/ 27757f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 27767f57c1a4SFlorian Wechsung { 27777f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 27787f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 27797f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 27807f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 27817f57c1a4SFlorian Wechsung const PetscInt *ilocal; 27827f57c1a4SFlorian Wechsung PetscBool *isLeaf; 27837f57c1a4SFlorian Wechsung PetscSF sf; 27847f57c1a4SFlorian Wechsung MPI_Comm comm; 27855a30b08bSFlorian Wechsung PetscMPIInt rank, size; 27867f57c1a4SFlorian Wechsung 27877f57c1a4SFlorian Wechsung PetscFunctionBegin; 27887f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 27897f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 27907f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 27917f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 27927f57c1a4SFlorian Wechsung 27937f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 27947f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 27957f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 27967f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 27977f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 27987f57c1a4SFlorian Wechsung } 27997f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 28007f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 28017f57c1a4SFlorian Wechsung } 28027f57c1a4SFlorian Wechsung 28037f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 28047f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 28057f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 28067f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 28077f57c1a4SFlorian Wechsung } 28087f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 28097f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 28107f57c1a4SFlorian Wechsung 28117f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 28127f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 28137f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28147f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 28157f57c1a4SFlorian Wechsung } 28167f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 28177f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 28187f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 28197f57c1a4SFlorian Wechsung 28207f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 28217f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 28227f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 28237f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28247f57c1a4SFlorian Wechsung points[i] = pStart+i; 28257f57c1a4SFlorian Wechsung } 28267f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 28277f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 28287f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 28297f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 28307f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 28317f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 28327f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28337f57c1a4SFlorian Wechsung newOwners[i] = -1; 28347f57c1a4SFlorian Wechsung newNumbers[i] = -1; 28357f57c1a4SFlorian Wechsung } 28367f57c1a4SFlorian Wechsung { 28377f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 28387f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 28397f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 28407f57c1a4SFlorian Wechsung newNumber = -1; 28417f57c1a4SFlorian Wechsung oldOwner = rank; 28427f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 28437f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 28447f57c1a4SFlorian Wechsung newNumber = oldNumber; 28457f57c1a4SFlorian Wechsung } else { 28467f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 28477f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 28487f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 28497f57c1a4SFlorian Wechsung break; 28507f57c1a4SFlorian Wechsung } 28517f57c1a4SFlorian Wechsung } 28527f57c1a4SFlorian Wechsung } 28537f57c1a4SFlorian Wechsung if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 28547f57c1a4SFlorian Wechsung 28557f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 28567f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 28577f57c1a4SFlorian Wechsung } 28587f57c1a4SFlorian Wechsung } 28597f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 28607f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 28617f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 28627f57c1a4SFlorian Wechsung 28637f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 28647f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 28657f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 28667f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 28677f57c1a4SFlorian Wechsung 28687f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 28697f57c1a4SFlorian Wechsung leafCounter=0; 28707f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28717f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 28727f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 28737f57c1a4SFlorian Wechsung leafCounter++; 28747f57c1a4SFlorian Wechsung } 28757f57c1a4SFlorian Wechsung } else { 28767f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28777f57c1a4SFlorian Wechsung leafCounter++; 28787f57c1a4SFlorian Wechsung } 28797f57c1a4SFlorian Wechsung } 28807f57c1a4SFlorian Wechsung } 28817f57c1a4SFlorian Wechsung 28827f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 28837f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 28847f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 28857f57c1a4SFlorian Wechsung 28867f57c1a4SFlorian Wechsung leafCounter = 0; 28877f57c1a4SFlorian Wechsung counter = 0; 28887f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 28897f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 28907f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 28917f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 28927f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 28937f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 28947f57c1a4SFlorian Wechsung leafCounter++; 28957f57c1a4SFlorian Wechsung } 28967f57c1a4SFlorian Wechsung } else { 28977f57c1a4SFlorian Wechsung if (isLeaf[i]) { 28987f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 28997f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 29007f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 29017f57c1a4SFlorian Wechsung leafCounter++; 29027f57c1a4SFlorian Wechsung } 29037f57c1a4SFlorian Wechsung } 29047f57c1a4SFlorian Wechsung if (isLeaf[i]) { 29057f57c1a4SFlorian Wechsung counter++; 29067f57c1a4SFlorian Wechsung } 29077f57c1a4SFlorian Wechsung } 29087f57c1a4SFlorian Wechsung 29097f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 29107f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 29117f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 29127f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 29137f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 29147f57c1a4SFlorian Wechsung } 29157f57c1a4SFlorian Wechsung 2916125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 2917125d2a8fSFlorian Wechsung { 29185a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 29195a30b08bSFlorian Wechsung PetscMPIInt rank, size; 2920125d2a8fSFlorian Wechsung PetscFunctionBegin; 2921125d2a8fSFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2922125d2a8fSFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2923125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 2924125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 2925125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 2926125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 2927125d2a8fSFlorian Wechsung } 2928125d2a8fSFlorian Wechsung ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 2929125d2a8fSFlorian Wechsung min = distribution[0]; 2930125d2a8fSFlorian Wechsung max = distribution[0]; 2931125d2a8fSFlorian Wechsung sum = distribution[0]; 2932125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 2933125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 2934125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 2935125d2a8fSFlorian Wechsung sum += distribution[i]; 2936125d2a8fSFlorian Wechsung } 2937125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 2938125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 2939125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 2940125d2a8fSFlorian Wechsung } 2941125d2a8fSFlorian Wechsung 29426a3739e5SFlorian Wechsung #endif 29436a3739e5SFlorian Wechsung 2944cb87ef4cSFlorian Wechsung /*@ 29455dc86ac1SFlorian 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. 2946cb87ef4cSFlorian Wechsung 2947cb87ef4cSFlorian Wechsung Input parameters: 2948ed44d270SFlorian Wechsung + dm - The DMPlex object. 29497f57c1a4SFlorian Wechsung + entityDepth - depth of the entity to balance (0 -> balance vertices). 29507f57c1a4SFlorian Wechsung + useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 29517f57c1a4SFlorian 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. 2952cb87ef4cSFlorian Wechsung 29538b879b41SFlorian Wechsung Output parameters: 29548b879b41SFlorian Wechsung + success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 29558b879b41SFlorian Wechsung 2956*90ea27d8SSatish Balay Level: intermediate 2957cb87ef4cSFlorian Wechsung 2958cb87ef4cSFlorian Wechsung @*/ 2959cb87ef4cSFlorian Wechsung 29608b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 2961cb87ef4cSFlorian Wechsung { 296241525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 2963cb87ef4cSFlorian Wechsung PetscSF sf; 29640faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 29657f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 29667f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 29677f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 2968cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 2969cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 2970cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 29717f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 29725dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 2973cb87ef4cSFlorian Wechsung PetscInt offset, counter; 29747f57c1a4SFlorian Wechsung PetscInt lenadjncy; 2975cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 2976cb87ef4cSFlorian Wechsung PetscInt lenxadj; 2977cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 2978cb87ef4cSFlorian Wechsung PetscInt *part, *options; 2979cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 2980cb87ef4cSFlorian Wechsung real_t *ubvec; 2981cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 2982cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 2983cb87ef4cSFlorian Wechsung MPI_Comm comm; 29844baf1206SFlorian Wechsung Mat A, Apre; 298512617df9SFlorian Wechsung const char *prefix = NULL; 29867d197802SFlorian Wechsung PetscViewer viewer; 29877d197802SFlorian Wechsung PetscViewerFormat format; 29885a30b08bSFlorian Wechsung PetscLayout layout; 298912617df9SFlorian Wechsung 299012617df9SFlorian Wechsung PetscFunctionBegin; 29918b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 29927f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 29937f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 29947f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 29957f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 29967f57c1a4SFlorian Wechsung 299741525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 299841525646SFlorian Wechsung 29995a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 30005dc86ac1SFlorian Wechsung if (viewer) { 30015a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 30027d197802SFlorian Wechsung } 30037d197802SFlorian Wechsung 3004ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 3005d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 3006cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3007cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 3008cf818975SFlorian Wechsung 3009cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 30105a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 3011cb87ef4cSFlorian Wechsung } 3012cb87ef4cSFlorian Wechsung 3013cf818975SFlorian Wechsung /* There are three types of points: 3014cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 3015cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 3016cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 3017cf818975SFlorian Wechsung */ 3018cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 3019cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 3020cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 3021cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 3022cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 3023cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3024cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 3025cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 3026cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 3027cb87ef4cSFlorian Wechsung } 3028cf818975SFlorian Wechsung 3029cf818975SFlorian Wechsung /* start by marking all the leafs */ 3030cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 3031cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 3032cb87ef4cSFlorian Wechsung } 3033cb87ef4cSFlorian Wechsung 3034cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 3035cf818975SFlorian Wechsung * not by calculating its degree */ 30367f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 30377f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 3038cf818975SFlorian Wechsung 3039cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 3040cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 3041cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3042cb87ef4cSFlorian Wechsung if (toBalance[i]) { 30437f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 3044cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 3045cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 3046cb87ef4cSFlorian Wechsung } else { 3047cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 3048cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 3049cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 3050cb87ef4cSFlorian Wechsung } 3051cb87ef4cSFlorian Wechsung } 3052cb87ef4cSFlorian Wechsung } 3053cb87ef4cSFlorian Wechsung } 3054cb87ef4cSFlorian Wechsung 3055cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 3056cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 3057cf818975SFlorian Wechsung * point. */ 3058cb87ef4cSFlorian Wechsung 30595dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 30605dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 30615dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 30625dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 30635dc86ac1SFlorian Wechsung 3064cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 3065cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 3066cb87ef4cSFlorian Wechsung counter = 0; 3067cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3068cb87ef4cSFlorian Wechsung if (toBalance[i]) { 30697f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 3070cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 3071cb87ef4cSFlorian Wechsung counter++; 3072cb87ef4cSFlorian Wechsung } 3073cb87ef4cSFlorian Wechsung } 3074cb87ef4cSFlorian Wechsung } 3075cb87ef4cSFlorian Wechsung 3076cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 3077cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 3078cb87ef4cSFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3079cb87ef4cSFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3080cb87ef4cSFlorian Wechsung 30810faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 3082cb87ef4cSFlorian Wechsung 30834baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 30844baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 30854baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 30864baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 30878c9a1619SFlorian Wechsung 30888c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 30898c9a1619SFlorian Wechsung if (toBalance[i]) { 30900faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 30910faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 30920faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 30930faf6628SFlorian Wechsung else continue; 30940faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 30950faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 30964baf1206SFlorian Wechsung } 30974baf1206SFlorian Wechsung } 30984baf1206SFlorian Wechsung 30994baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31004baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31014baf1206SFlorian Wechsung 31024baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 31034baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 31044baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 31054baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 31064baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 31074baf1206SFlorian Wechsung 31084baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31094baf1206SFlorian Wechsung if (toBalance[i]) { 31100faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 31110faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 31120faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 31130faf6628SFlorian Wechsung else continue; 31140faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 31150faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 31160941debbSFlorian Wechsung } 31170941debbSFlorian Wechsung } 31188c9a1619SFlorian Wechsung 31198c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31208c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31214baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 31224baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 31234baf1206SFlorian Wechsung 312441525646SFlorian Wechsung nparts = size; 312541525646SFlorian Wechsung wgtflag = 2; 312641525646SFlorian Wechsung numflag = 0; 312741525646SFlorian Wechsung ncon = 2; 312841525646SFlorian Wechsung real_t *tpwgts; 312941525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 313041525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 313141525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 313241525646SFlorian Wechsung } 313341525646SFlorian Wechsung 313441525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 313541525646SFlorian Wechsung ubvec[0] = 1.01; 31365a30b08bSFlorian Wechsung ubvec[1] = 1.01; 31378c9a1619SFlorian Wechsung lenadjncy = 0; 31388c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 31398c9a1619SFlorian Wechsung PetscInt temp=0; 31408c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 31418c9a1619SFlorian Wechsung lenadjncy += temp; 31428c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 31438c9a1619SFlorian Wechsung } 31448c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 31457407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 31460941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 31470941debbSFlorian Wechsung xadj[0] = 0; 31488c9a1619SFlorian Wechsung counter = 0; 31498c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 31502953a68cSFlorian Wechsung PetscInt temp=0; 31512953a68cSFlorian Wechsung const PetscInt *cols; 31528c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 3153580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy[counter], cols, temp);CHKERRQ(ierr); 31548c9a1619SFlorian Wechsung counter += temp; 31550941debbSFlorian Wechsung xadj[i+1] = counter; 31568c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 31578c9a1619SFlorian Wechsung } 31588c9a1619SFlorian Wechsung 3159cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 316041525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 316141525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 316241525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 316341525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 316441525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 316541525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 316641525646SFlorian Wechsung } 31678c9a1619SFlorian Wechsung 31685dc86ac1SFlorian Wechsung if (viewer) { 31697d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 31707d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 317112617df9SFlorian Wechsung } 317241525646SFlorian Wechsung if (parallel) { 31735a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 31745a30b08bSFlorian Wechsung options[0] = 1; 31755a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 31765a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 31775a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 31785dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 31798c9a1619SFlorian Wechsung if (useInitialGuess) { 31805dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 31818c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 31825dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 318306b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 31848c9a1619SFlorian Wechsung PetscStackPop; 31858c9a1619SFlorian Wechsung } else { 31868c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 31875dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 31888c9a1619SFlorian Wechsung PetscStackPop; 318906b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 31908c9a1619SFlorian Wechsung } 3191ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 319241525646SFlorian Wechsung } else { 31935dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 319441525646SFlorian Wechsung Mat As; 319541525646SFlorian Wechsung PetscInt numRows; 319641525646SFlorian Wechsung PetscInt *partGlobal; 319741525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 3198cb87ef4cSFlorian Wechsung 319941525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 320041525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 320141525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 32022953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRQ(ierr); 3203cb87ef4cSFlorian Wechsung 320441525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 320541525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 32065dc86ac1SFlorian Wechsung if (!rank) { 320741525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 320841525646SFlorian Wechsung lenadjncy = 0; 320941525646SFlorian Wechsung 321041525646SFlorian Wechsung for (i=0; i<numRows; i++) { 321141525646SFlorian Wechsung PetscInt temp=0; 321241525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 321341525646SFlorian Wechsung lenadjncy += temp; 321441525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 321541525646SFlorian Wechsung } 321641525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 321741525646SFlorian Wechsung lenxadj = 1 + numRows; 321841525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 321941525646SFlorian Wechsung xadj_g[0] = 0; 322041525646SFlorian Wechsung counter = 0; 322141525646SFlorian Wechsung for (i=0; i<numRows; i++) { 32222953a68cSFlorian Wechsung PetscInt temp=0; 32232953a68cSFlorian Wechsung const PetscInt *cols; 322441525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 3225580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy_g[counter], cols, temp);CHKERRQ(ierr); 322641525646SFlorian Wechsung counter += temp; 322741525646SFlorian Wechsung xadj_g[i+1] = counter; 322841525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 322941525646SFlorian Wechsung } 323041525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 323141525646SFlorian Wechsung for (i=0; i<size; i++){ 323241525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 323341525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 323441525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 323541525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 323641525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 323741525646SFlorian Wechsung } 323841525646SFlorian Wechsung } 323941525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 324041525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 324106b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 324241525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 324341525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 324406b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 324541525646SFlorian Wechsung PetscStackPop; 324606b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 3247ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 324841525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 324941525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 325041525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 325141525646SFlorian Wechsung } 325241525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 325341525646SFlorian Wechsung 32545dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 32555dc86ac1SFlorian Wechsung { 325681a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 32575dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 325881a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 32595dc86ac1SFlorian Wechsung for(i=0; i<size; i++) { 326081a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 326141525646SFlorian Wechsung } 326281a13b52SFlorian Wechsung for(i=0; i<=size; i++) { 326381a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 326481a13b52SFlorian Wechsung } 326581a13b52SFlorian Wechsung ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRQ(ierr); 32665dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 326781a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 32685dc86ac1SFlorian Wechsung } 32695dc86ac1SFlorian Wechsung 327041525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 32712953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 327241525646SFlorian Wechsung } 3273cb87ef4cSFlorian Wechsung 32742953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 3275cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 3276cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 3277cb87ef4cSFlorian Wechsung 3278cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 3279cb87ef4cSFlorian Wechsung 3280cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 3281cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 3282cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 32832953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRQ(ierr); 3284cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 3285cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 3286cb87ef4cSFlorian Wechsung } 3287cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 3288cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 3289cb87ef4cSFlorian Wechsung } 3290cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 3291cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 32922953a68cSFlorian Wechsung ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 3293cb87ef4cSFlorian Wechsung 32947f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 32957f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 32967f57c1a4SFlorian Wechsung 3297cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 32987f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 32997f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 33007f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 33017f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 33027f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 33037f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 33047f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 33057f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 33067f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 33077f57c1a4SFlorian Wechsung if (viewer) { 330806b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 330906b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 33107f57c1a4SFlorian Wechsung } 33117f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 33128b879b41SFlorian Wechsung PetscFunctionReturn(0); 3313cb87ef4cSFlorian Wechsung } 3314cb87ef4cSFlorian Wechsung 33157407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 33165dc86ac1SFlorian Wechsung if (viewer) { 33177d197802SFlorian 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); 3318125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 3319125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 3320125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 3321125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 33227407ba93SFlorian Wechsung } 33237407ba93SFlorian Wechsung 3324cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 332541525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 3326cb87ef4cSFlorian Wechsung PetscInt loc = 0; 332741525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 33287407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 3329cb87ef4cSFlorian Wechsung if (loc<0) { 333041525646SFlorian Wechsung part[i] = rank; 3331cb87ef4cSFlorian Wechsung } 3332cb87ef4cSFlorian Wechsung } 3333cb87ef4cSFlorian Wechsung 33347407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 33355dc86ac1SFlorian Wechsung if (viewer) { 3336125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 3337125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 33387407ba93SFlorian Wechsung } 33397407ba93SFlorian Wechsung 33405dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3341cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 3342cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 334341525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 3344cb87ef4cSFlorian Wechsung 33457f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 3346cf818975SFlorian Wechsung { 33477f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 334806b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 33497f57c1a4SFlorian Wechsung counter = 0; 3350cb87ef4cSFlorian Wechsung for(i=0; i<pEnd-pStart; i++) { 3351cb87ef4cSFlorian Wechsung if (toBalance[i]) { 3352cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 33537f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 3354cb87ef4cSFlorian Wechsung counter++; 3355cb87ef4cSFlorian Wechsung } 3356cb87ef4cSFlorian Wechsung } 3357cb87ef4cSFlorian Wechsung } 33587f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 33597f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 3360cf818975SFlorian Wechsung } 3361cb87ef4cSFlorian Wechsung 3362cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 3363cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 3364cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 3365cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 33667f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 33675dc86ac1SFlorian Wechsung if (viewer) { 336806b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 336906b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 33707d197802SFlorian Wechsung } 33718b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 337241525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 3373240408d3SFlorian Wechsung #else 33745f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 337541525646SFlorian Wechsung #endif 3376cb87ef4cSFlorian Wechsung PetscFunctionReturn(0); 3377cb87ef4cSFlorian Wechsung } 3378