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 303c41b853SStefano Zampini PetscBool PTScotchPartitionercite = PETSC_FALSE; 313c41b853SStefano Zampini const char PTScotchPartitionerCitation[] = 323c41b853SStefano Zampini "@article{PTSCOTCH,\n" 333c41b853SStefano Zampini " author = {C. Chevalier and F. Pellegrini},\n" 343c41b853SStefano Zampini " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 353c41b853SStefano Zampini " journal = {Parallel Computing},\n" 363c41b853SStefano Zampini " volume = {34},\n" 373c41b853SStefano Zampini " number = {6},\n" 383c41b853SStefano Zampini " pages = {318--331},\n" 393c41b853SStefano Zampini " year = {2008},\n" 403c41b853SStefano Zampini " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 413c41b853SStefano Zampini "}\n"; 423c41b853SStefano Zampini 433c41b853SStefano Zampini 440134a67bSLisandro Dalcin PETSC_STATIC_INLINE PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); } 450134a67bSLisandro Dalcin 46bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 47532c4e7dSMichael Lange { 48ffbd6163SMatthew G. Knepley PetscInt dim, depth, p, pStart, pEnd, a, adjSize, idx, size; 49389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 508cfe4c1fSMichael Lange IS cellNumbering; 518cfe4c1fSMichael Lange const PetscInt *cellNum; 52532c4e7dSMichael Lange PetscBool useCone, useClosure; 53532c4e7dSMichael Lange PetscSection section; 54532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 558cfe4c1fSMichael Lange PetscSF sfPoint; 568f4e72b9SMatthew G. Knepley PetscInt *adjCells = NULL, *remoteCells = NULL; 578f4e72b9SMatthew G. Knepley const PetscInt *local; 588f4e72b9SMatthew G. Knepley PetscInt nroots, nleaves, l; 59532c4e7dSMichael Lange PetscMPIInt rank; 60532c4e7dSMichael Lange PetscErrorCode ierr; 61532c4e7dSMichael Lange 62532c4e7dSMichael Lange PetscFunctionBegin; 63532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 64ffbd6163SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 65ffbd6163SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 66ffbd6163SMatthew G. Knepley if (dim != depth) { 67ffbd6163SMatthew G. Knepley /* We do not handle the uninterpolated case here */ 68ffbd6163SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 69ffbd6163SMatthew G. Knepley /* DMPlexCreateNeighborCSR does not make a numbering */ 70ffbd6163SMatthew G. Knepley if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 71ffbd6163SMatthew G. Knepley /* Different behavior for empty graphs */ 72ffbd6163SMatthew G. Knepley if (!*numVertices) { 73ffbd6163SMatthew G. Knepley ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 74ffbd6163SMatthew G. Knepley (*offsets)[0] = 0; 75ffbd6163SMatthew G. Knepley } 76ffbd6163SMatthew G. Knepley /* Broken in parallel */ 77ffbd6163SMatthew G. Knepley if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 78ffbd6163SMatthew G. Knepley PetscFunctionReturn(0); 79ffbd6163SMatthew G. Knepley } 808cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 810134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 82532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 83532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 84532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 85532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 86532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 87b0441da4SMatthew G. Knepley ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 88b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 899886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr); 903fa7752dSToby Isaac if (globalNumbering) { 913fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 923fa7752dSToby Isaac *globalNumbering = cellNumbering; 933fa7752dSToby Isaac } 948cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 958f4e72b9SMatthew G. Knepley /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells 968f4e72b9SMatthew G. Knepley Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves) 978f4e72b9SMatthew G. Knepley */ 980134a67bSLisandro Dalcin ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr); 998f4e72b9SMatthew G. Knepley if (nroots >= 0) { 1008f4e72b9SMatthew G. Knepley PetscInt fStart, fEnd, f; 1018f4e72b9SMatthew G. Knepley 1028f4e72b9SMatthew G. Knepley ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr); 1030134a67bSLisandro Dalcin ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 1048f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) adjCells[l] = -3; 1058f4e72b9SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 1068f4e72b9SMatthew G. Knepley const PetscInt *support; 1078f4e72b9SMatthew G. Knepley PetscInt supportSize; 1088f4e72b9SMatthew G. Knepley 1098f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 1108f4e72b9SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 1110134a67bSLisandro Dalcin if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1128f4e72b9SMatthew G. Knepley else if (supportSize == 2) { 1138f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1140134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]); 1158f4e72b9SMatthew G. Knepley ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1160134a67bSLisandro Dalcin if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]); 1170134a67bSLisandro Dalcin } 1180134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1190134a67bSLisandro Dalcin if (supportSize > 2) { 1200134a67bSLisandro Dalcin PetscInt numChildren, i; 1210134a67bSLisandro Dalcin const PetscInt *children; 1220134a67bSLisandro Dalcin 1230134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr); 1240134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1250134a67bSLisandro Dalcin const PetscInt child = children[i]; 1260134a67bSLisandro Dalcin if (fStart <= child && child < fEnd) { 1270134a67bSLisandro Dalcin ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr); 1280134a67bSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr); 1290134a67bSLisandro Dalcin if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1300134a67bSLisandro Dalcin else if (supportSize == 2) { 1310134a67bSLisandro Dalcin ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr); 1320134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]); 1330134a67bSLisandro Dalcin ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr); 1340134a67bSLisandro Dalcin if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]); 1350134a67bSLisandro Dalcin } 1360134a67bSLisandro Dalcin } 1370134a67bSLisandro Dalcin } 1388f4e72b9SMatthew G. Knepley } 1398f4e72b9SMatthew G. Knepley } 1408f4e72b9SMatthew G. Knepley for (l = 0; l < nroots; ++l) remoteCells[l] = -1; 1418f4e72b9SMatthew G. Knepley ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1428f4e72b9SMatthew G. Knepley ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells);CHKERRQ(ierr); 1438f4e72b9SMatthew G. Knepley ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1448f4e72b9SMatthew G. Knepley ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr); 1458f4e72b9SMatthew G. Knepley } 1468f4e72b9SMatthew G. Knepley /* Combine local and global adjacencies */ 1478cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 1488cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 1498cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 1508f4e72b9SMatthew G. Knepley /* Add remote cells */ 1518f4e72b9SMatthew G. Knepley if (remoteCells) { 1520134a67bSLisandro Dalcin const PetscInt gp = DMPlex_GlobalID(cellNum[p]); 1530134a67bSLisandro Dalcin PetscInt coneSize, numChildren, c, i; 1540134a67bSLisandro Dalcin const PetscInt *cone, *children; 1550134a67bSLisandro Dalcin 1568f4e72b9SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1578f4e72b9SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1588f4e72b9SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1590134a67bSLisandro Dalcin const PetscInt point = cone[c]; 1600134a67bSLisandro Dalcin if (remoteCells[point] >= 0 && remoteCells[point] != gp) { 1618f4e72b9SMatthew G. Knepley PetscInt *PETSC_RESTRICT pBuf; 1628f4e72b9SMatthew G. Knepley ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1638f4e72b9SMatthew G. Knepley ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1640134a67bSLisandro Dalcin *pBuf = remoteCells[point]; 1650134a67bSLisandro Dalcin } 1660134a67bSLisandro Dalcin /* Handle non-conforming meshes */ 1670134a67bSLisandro Dalcin ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 1680134a67bSLisandro Dalcin for (i = 0; i < numChildren; ++i) { 1690134a67bSLisandro Dalcin const PetscInt child = children[i]; 1700134a67bSLisandro Dalcin if (remoteCells[child] >= 0 && remoteCells[child] != gp) { 1710134a67bSLisandro Dalcin PetscInt *PETSC_RESTRICT pBuf; 1720134a67bSLisandro Dalcin ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 1730134a67bSLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1740134a67bSLisandro Dalcin *pBuf = remoteCells[child]; 1750134a67bSLisandro Dalcin } 1768f4e72b9SMatthew G. Knepley } 1778f4e72b9SMatthew G. Knepley } 1788f4e72b9SMatthew G. Knepley } 1798f4e72b9SMatthew G. Knepley /* Add local cells */ 180532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 181532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 182532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 183532c4e7dSMichael Lange const PetscInt point = adj[a]; 184532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 185532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 186532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 187532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 1880134a67bSLisandro Dalcin *pBuf = DMPlex_GlobalID(cellNum[point]); 189532c4e7dSMichael Lange } 190532c4e7dSMichael Lange } 1918cfe4c1fSMichael Lange (*numVertices)++; 192532c4e7dSMichael Lange } 1934e468a93SLisandro Dalcin ierr = PetscFree(adj);CHKERRQ(ierr); 1948f4e72b9SMatthew G. Knepley ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr); 195b0441da4SMatthew G. Knepley ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr); 1964e468a93SLisandro Dalcin 197532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 198532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 199532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 200389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 20143f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 20243f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 20343f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 20443f7d02bSMichael Lange } 205532c4e7dSMichael Lange vOffsets[*numVertices] = size; 206389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 2074e468a93SLisandro Dalcin 2084e468a93SLisandro Dalcin if (nroots >= 0) { 2094e468a93SLisandro Dalcin /* Filter out duplicate edges using section/segbuffer */ 2104e468a93SLisandro Dalcin ierr = PetscSectionReset(section);CHKERRQ(ierr); 2114e468a93SLisandro Dalcin ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr); 2124e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2134e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2144e468a93SLisandro Dalcin PetscInt numEdges = end-start, *PETSC_RESTRICT edges; 2154e468a93SLisandro Dalcin ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr); 2164e468a93SLisandro Dalcin ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr); 2174e468a93SLisandro Dalcin ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr); 218580bdb30SBarry Smith ierr = PetscArraycpy(edges, &graph[start], numEdges);CHKERRQ(ierr); 2194e468a93SLisandro Dalcin } 2204e468a93SLisandro Dalcin ierr = PetscFree(vOffsets);CHKERRQ(ierr); 2214e468a93SLisandro Dalcin ierr = PetscFree(graph);CHKERRQ(ierr); 2224e468a93SLisandro Dalcin /* Derive CSR graph from section/segbuffer */ 2234e468a93SLisandro Dalcin ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 2244e468a93SLisandro Dalcin ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 2254e468a93SLisandro Dalcin ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 2264e468a93SLisandro Dalcin for (idx = 0, p = 0; p < *numVertices; p++) { 2274e468a93SLisandro Dalcin ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 2284e468a93SLisandro Dalcin } 2294e468a93SLisandro Dalcin vOffsets[*numVertices] = size; 2304e468a93SLisandro Dalcin ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 2314e468a93SLisandro Dalcin } else { 2324e468a93SLisandro Dalcin /* Sort adjacencies (not strictly necessary) */ 2334e468a93SLisandro Dalcin for (p = 0; p < *numVertices; p++) { 2344e468a93SLisandro Dalcin PetscInt start = vOffsets[p], end = vOffsets[p+1]; 2354e468a93SLisandro Dalcin ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr); 2364e468a93SLisandro Dalcin } 2374e468a93SLisandro Dalcin } 2384e468a93SLisandro Dalcin 2394e468a93SLisandro Dalcin if (offsets) *offsets = vOffsets; 240389e55d8SMichael Lange if (adjacency) *adjacency = graph; 2414e468a93SLisandro Dalcin 242532c4e7dSMichael Lange /* Cleanup */ 243532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 244532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 2454e468a93SLisandro Dalcin ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 2464e468a93SLisandro Dalcin ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 247532c4e7dSMichael Lange PetscFunctionReturn(0); 248532c4e7dSMichael Lange } 249532c4e7dSMichael Lange 250bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 251bbbc8e51SStefano Zampini { 252bbbc8e51SStefano Zampini Mat conn, CSR; 253bbbc8e51SStefano Zampini IS fis, cis, cis_own; 254bbbc8e51SStefano Zampini PetscSF sfPoint; 255bbbc8e51SStefano Zampini const PetscInt *rows, *cols, *ii, *jj; 256bbbc8e51SStefano Zampini PetscInt *idxs,*idxs2; 25783c5d788SMatthew G. Knepley PetscInt dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd; 258bbbc8e51SStefano Zampini PetscMPIInt rank; 259bbbc8e51SStefano Zampini PetscBool flg; 260bbbc8e51SStefano Zampini PetscErrorCode ierr; 261bbbc8e51SStefano Zampini 262bbbc8e51SStefano Zampini PetscFunctionBegin; 263bbbc8e51SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 264bbbc8e51SStefano Zampini ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 265bbbc8e51SStefano Zampini ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 266bbbc8e51SStefano Zampini if (dim != depth) { 267bbbc8e51SStefano Zampini /* We do not handle the uninterpolated case here */ 268bbbc8e51SStefano Zampini ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr); 269bbbc8e51SStefano Zampini /* DMPlexCreateNeighborCSR does not make a numbering */ 270bbbc8e51SStefano Zampini if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);} 271bbbc8e51SStefano Zampini /* Different behavior for empty graphs */ 272bbbc8e51SStefano Zampini if (!*numVertices) { 273bbbc8e51SStefano Zampini ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr); 274bbbc8e51SStefano Zampini (*offsets)[0] = 0; 275bbbc8e51SStefano Zampini } 276bbbc8e51SStefano Zampini /* Broken in parallel */ 277bbbc8e51SStefano Zampini if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported"); 278bbbc8e51SStefano Zampini PetscFunctionReturn(0); 279bbbc8e51SStefano Zampini } 280bbbc8e51SStefano Zampini /* Interpolated and parallel case */ 281bbbc8e51SStefano Zampini 282bbbc8e51SStefano Zampini /* numbering */ 283bbbc8e51SStefano Zampini ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 284bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr); 285bbbc8e51SStefano Zampini ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr); 2869886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr); 2879886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr); 288bbbc8e51SStefano Zampini if (globalNumbering) { 289bbbc8e51SStefano Zampini ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr); 290bbbc8e51SStefano Zampini } 291bbbc8e51SStefano Zampini 292bbbc8e51SStefano Zampini /* get positive global ids and local sizes for facets and cells */ 293bbbc8e51SStefano Zampini ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr); 294bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 295bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 296bbbc8e51SStefano Zampini for (i = 0, floc = 0; i < m; i++) { 297bbbc8e51SStefano Zampini const PetscInt p = rows[i]; 298bbbc8e51SStefano Zampini 299bbbc8e51SStefano Zampini if (p < 0) { 300bbbc8e51SStefano Zampini idxs[i] = -(p+1); 301bbbc8e51SStefano Zampini } else { 302bbbc8e51SStefano Zampini idxs[i] = p; 303bbbc8e51SStefano Zampini floc += 1; 304bbbc8e51SStefano Zampini } 305bbbc8e51SStefano Zampini } 306bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 307bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 308bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 309bbbc8e51SStefano Zampini 310bbbc8e51SStefano Zampini ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr); 311bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 312bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr); 313bbbc8e51SStefano Zampini ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr); 314bbbc8e51SStefano Zampini for (i = 0, cloc = 0; i < m; i++) { 315bbbc8e51SStefano Zampini const PetscInt p = cols[i]; 316bbbc8e51SStefano Zampini 317bbbc8e51SStefano Zampini if (p < 0) { 318bbbc8e51SStefano Zampini idxs[i] = -(p+1); 319bbbc8e51SStefano Zampini } else { 320bbbc8e51SStefano Zampini idxs[i] = p; 321bbbc8e51SStefano Zampini idxs2[cloc++] = p; 322bbbc8e51SStefano Zampini } 323bbbc8e51SStefano Zampini } 324bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 325bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 326bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 327bbbc8e51SStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr); 328bbbc8e51SStefano Zampini 329bbbc8e51SStefano Zampini /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */ 330bbbc8e51SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr); 331bbbc8e51SStefano Zampini ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr); 332bbbc8e51SStefano Zampini ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr); 33383c5d788SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, NULL, &lm);CHKERRQ(ierr); 33483c5d788SMatthew G. Knepley ierr = MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 335bbbc8e51SStefano Zampini ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr); 336bbbc8e51SStefano Zampini 337bbbc8e51SStefano Zampini /* Assemble matrix */ 338bbbc8e51SStefano Zampini ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr); 339bbbc8e51SStefano Zampini ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr); 340bbbc8e51SStefano Zampini for (c = cStart; c < cEnd; c++) { 341bbbc8e51SStefano Zampini const PetscInt *cone; 342bbbc8e51SStefano Zampini PetscInt coneSize, row, col, f; 343bbbc8e51SStefano Zampini 344bbbc8e51SStefano Zampini col = cols[c-cStart]; 345bbbc8e51SStefano Zampini ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 346bbbc8e51SStefano Zampini ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 347bbbc8e51SStefano Zampini for (f = 0; f < coneSize; f++) { 348bbbc8e51SStefano Zampini const PetscScalar v = 1.0; 349bbbc8e51SStefano Zampini const PetscInt *children; 350bbbc8e51SStefano Zampini PetscInt numChildren, ch; 351bbbc8e51SStefano Zampini 352bbbc8e51SStefano Zampini row = rows[cone[f]-fStart]; 353bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 354bbbc8e51SStefano Zampini 355bbbc8e51SStefano Zampini /* non-conforming meshes */ 356bbbc8e51SStefano Zampini ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr); 357bbbc8e51SStefano Zampini for (ch = 0; ch < numChildren; ch++) { 358bbbc8e51SStefano Zampini const PetscInt child = children[ch]; 359bbbc8e51SStefano Zampini 360bbbc8e51SStefano Zampini if (child < fStart || child >= fEnd) continue; 361bbbc8e51SStefano Zampini row = rows[child-fStart]; 362bbbc8e51SStefano Zampini ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr); 363bbbc8e51SStefano Zampini } 364bbbc8e51SStefano Zampini } 365bbbc8e51SStefano Zampini } 366bbbc8e51SStefano Zampini ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr); 367bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr); 368bbbc8e51SStefano Zampini ierr = ISDestroy(&fis);CHKERRQ(ierr); 369bbbc8e51SStefano Zampini ierr = ISDestroy(&cis);CHKERRQ(ierr); 370bbbc8e51SStefano Zampini ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 371bbbc8e51SStefano Zampini ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 372bbbc8e51SStefano Zampini 373bbbc8e51SStefano Zampini /* Get parallel CSR by doing conn^T * conn */ 374bbbc8e51SStefano Zampini ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr); 375bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 376bbbc8e51SStefano Zampini 377bbbc8e51SStefano Zampini /* extract local part of the CSR */ 378bbbc8e51SStefano Zampini ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr); 379bbbc8e51SStefano Zampini ierr = MatDestroy(&CSR);CHKERRQ(ierr); 380bbbc8e51SStefano Zampini ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 381bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 382bbbc8e51SStefano Zampini 383bbbc8e51SStefano Zampini /* get back requested output */ 384bbbc8e51SStefano Zampini if (numVertices) *numVertices = m; 385bbbc8e51SStefano Zampini if (offsets) { 386bbbc8e51SStefano Zampini ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr); 387bbbc8e51SStefano Zampini for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */ 388bbbc8e51SStefano Zampini *offsets = idxs; 389bbbc8e51SStefano Zampini } 390bbbc8e51SStefano Zampini if (adjacency) { 391bbbc8e51SStefano Zampini ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr); 392bbbc8e51SStefano Zampini ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr); 393bbbc8e51SStefano Zampini for (i = 0, c = 0; i < m; i++) { 394bbbc8e51SStefano Zampini PetscInt j, g = rows[i]; 395bbbc8e51SStefano Zampini 396bbbc8e51SStefano Zampini for (j = ii[i]; j < ii[i+1]; j++) { 397bbbc8e51SStefano Zampini if (jj[j] == g) continue; /* again, self-connectivity */ 398bbbc8e51SStefano Zampini idxs[c++] = jj[j]; 399bbbc8e51SStefano Zampini } 400bbbc8e51SStefano Zampini } 401bbbc8e51SStefano Zampini if (c != ii[m] - m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m); 402bbbc8e51SStefano Zampini ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr); 403bbbc8e51SStefano Zampini *adjacency = idxs; 404bbbc8e51SStefano Zampini } 405bbbc8e51SStefano Zampini 406bbbc8e51SStefano Zampini /* cleanup */ 407bbbc8e51SStefano Zampini ierr = ISDestroy(&cis_own);CHKERRQ(ierr); 408bbbc8e51SStefano Zampini ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr); 409bbbc8e51SStefano Zampini if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format"); 410bbbc8e51SStefano Zampini ierr = MatDestroy(&conn);CHKERRQ(ierr); 411bbbc8e51SStefano Zampini PetscFunctionReturn(0); 412bbbc8e51SStefano Zampini } 413bbbc8e51SStefano Zampini 414bbbc8e51SStefano Zampini /*@C 415bbbc8e51SStefano Zampini DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 416bbbc8e51SStefano Zampini 417bbbc8e51SStefano Zampini Input Parameters: 418bbbc8e51SStefano Zampini + dm - The mesh DM dm 419bbbc8e51SStefano Zampini - height - Height of the strata from which to construct the graph 420bbbc8e51SStefano Zampini 421bbbc8e51SStefano Zampini Output Parameter: 422bbbc8e51SStefano Zampini + numVertices - Number of vertices in the graph 423bbbc8e51SStefano Zampini . offsets - Point offsets in the graph 424bbbc8e51SStefano Zampini . adjacency - Point connectivity in the graph 425bbbc8e51SStefano 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. 426bbbc8e51SStefano Zampini 427bbbc8e51SStefano Zampini The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 428bbbc8e51SStefano Zampini representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree(). 429bbbc8e51SStefano Zampini 430bbbc8e51SStefano Zampini Level: developer 431bbbc8e51SStefano Zampini 432bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency() 433bbbc8e51SStefano Zampini @*/ 434bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 435bbbc8e51SStefano Zampini { 436bbbc8e51SStefano Zampini PetscErrorCode ierr; 437bbbc8e51SStefano Zampini PetscBool usemat = PETSC_FALSE; 438bbbc8e51SStefano Zampini 439bbbc8e51SStefano Zampini PetscFunctionBegin; 440bbbc8e51SStefano Zampini ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_via_mat", &usemat, NULL);CHKERRQ(ierr); 441bbbc8e51SStefano Zampini if (usemat) { 442bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 443bbbc8e51SStefano Zampini } else { 444bbbc8e51SStefano Zampini ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr); 445bbbc8e51SStefano Zampini } 446bbbc8e51SStefano Zampini PetscFunctionReturn(0); 447bbbc8e51SStefano Zampini } 448bbbc8e51SStefano Zampini 449d5577e40SMatthew G. Knepley /*@C 450d5577e40SMatthew G. Knepley DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format. 451d5577e40SMatthew G. Knepley 452fe2efc57SMark Collective on DM 453d5577e40SMatthew G. Knepley 454d5577e40SMatthew G. Knepley Input Arguments: 455d5577e40SMatthew G. Knepley + dm - The DMPlex 456d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0) 457d5577e40SMatthew G. Knepley 458d5577e40SMatthew G. Knepley Output Arguments: 459d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh. 460d5577e40SMatthew G. Knepley . offsets - The offset to the adjacency list for each cell 461d5577e40SMatthew G. Knepley - adjacency - The adjacency list for all cells 462d5577e40SMatthew G. Knepley 463d5577e40SMatthew G. Knepley Note: This is suitable for input to a mesh partitioner like ParMetis. 464d5577e40SMatthew G. Knepley 465d5577e40SMatthew G. Knepley Level: advanced 466d5577e40SMatthew G. Knepley 467d5577e40SMatthew G. Knepley .seealso: DMPlexCreate() 468d5577e40SMatthew G. Knepley @*/ 46970034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 47070034214SMatthew G. Knepley { 47170034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 47270034214SMatthew G. Knepley PetscInt numFaceCases = 0; 47370034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 47470034214SMatthew G. Knepley PetscInt *off, *adj; 47570034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 47670034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 47770034214SMatthew G. Knepley PetscErrorCode ierr; 47870034214SMatthew G. Knepley 47970034214SMatthew G. Knepley PetscFunctionBegin; 48070034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 481c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 48270034214SMatthew G. Knepley cellDim = dim - cellHeight; 48370034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 48470034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 48570034214SMatthew G. Knepley if (cEnd - cStart == 0) { 48670034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 48770034214SMatthew G. Knepley if (offsets) *offsets = NULL; 48870034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 48970034214SMatthew G. Knepley PetscFunctionReturn(0); 49070034214SMatthew G. Knepley } 49170034214SMatthew G. Knepley numCells = cEnd - cStart; 49270034214SMatthew G. Knepley faceDepth = depth - cellHeight; 49370034214SMatthew G. Knepley if (dim == depth) { 49470034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 49570034214SMatthew G. Knepley 49670034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 49770034214SMatthew G. Knepley /* Count neighboring cells */ 49870034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 49970034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 50070034214SMatthew G. Knepley const PetscInt *support; 50170034214SMatthew G. Knepley PetscInt supportSize; 50270034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 50370034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 50470034214SMatthew G. Knepley if (supportSize == 2) { 5059ffc88e4SToby Isaac PetscInt numChildren; 5069ffc88e4SToby Isaac 5079ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5089ffc88e4SToby Isaac if (!numChildren) { 50970034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 51070034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 51170034214SMatthew G. Knepley } 51270034214SMatthew G. Knepley } 5139ffc88e4SToby Isaac } 51470034214SMatthew G. Knepley /* Prefix sum */ 51570034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 51670034214SMatthew G. Knepley if (adjacency) { 51770034214SMatthew G. Knepley PetscInt *tmp; 51870034214SMatthew G. Knepley 51970034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 520854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 521580bdb30SBarry Smith ierr = PetscArraycpy(tmp, off, numCells+1);CHKERRQ(ierr); 52270034214SMatthew G. Knepley /* Get neighboring cells */ 52370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 52470034214SMatthew G. Knepley const PetscInt *support; 52570034214SMatthew G. Knepley PetscInt supportSize; 52670034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 52770034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 52870034214SMatthew G. Knepley if (supportSize == 2) { 5299ffc88e4SToby Isaac PetscInt numChildren; 5309ffc88e4SToby Isaac 5319ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 5329ffc88e4SToby Isaac if (!numChildren) { 53370034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 53470034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 53570034214SMatthew G. Knepley } 53670034214SMatthew G. Knepley } 5379ffc88e4SToby Isaac } 53870034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 53970034214SMatthew 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); 54070034214SMatthew G. Knepley #endif 54170034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 54270034214SMatthew G. Knepley } 54370034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 54470034214SMatthew G. Knepley if (offsets) *offsets = off; 54570034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 54670034214SMatthew G. Knepley PetscFunctionReturn(0); 54770034214SMatthew G. Knepley } 54870034214SMatthew G. Knepley /* Setup face recognition */ 54970034214SMatthew G. Knepley if (faceDepth == 1) { 55070034214SMatthew 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 */ 55170034214SMatthew G. Knepley 55270034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 55370034214SMatthew G. Knepley PetscInt corners; 55470034214SMatthew G. Knepley 55570034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 55670034214SMatthew G. Knepley if (!cornersSeen[corners]) { 55770034214SMatthew G. Knepley PetscInt nFV; 55870034214SMatthew G. Knepley 55970034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 56070034214SMatthew G. Knepley cornersSeen[corners] = 1; 56170034214SMatthew G. Knepley 56270034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 56370034214SMatthew G. Knepley 56470034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 56570034214SMatthew G. Knepley } 56670034214SMatthew G. Knepley } 56770034214SMatthew G. Knepley } 56870034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 56970034214SMatthew G. Knepley /* Count neighboring cells */ 57070034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 57170034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 57270034214SMatthew G. Knepley 5738b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 57470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 57570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 57670034214SMatthew G. Knepley PetscInt cellPair[2]; 57770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 57870034214SMatthew G. Knepley PetscInt meetSize = 0; 57970034214SMatthew G. Knepley const PetscInt *meet = NULL; 58070034214SMatthew G. Knepley 58170034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 58270034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 58370034214SMatthew G. Knepley if (!found) { 58470034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 58570034214SMatthew G. Knepley if (meetSize) { 58670034214SMatthew G. Knepley PetscInt f; 58770034214SMatthew G. Knepley 58870034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 58970034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 59070034214SMatthew G. Knepley found = PETSC_TRUE; 59170034214SMatthew G. Knepley break; 59270034214SMatthew G. Knepley } 59370034214SMatthew G. Knepley } 59470034214SMatthew G. Knepley } 59570034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 59670034214SMatthew G. Knepley } 59770034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 59870034214SMatthew G. Knepley } 59970034214SMatthew G. Knepley } 60070034214SMatthew G. Knepley /* Prefix sum */ 60170034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 60270034214SMatthew G. Knepley 60370034214SMatthew G. Knepley if (adjacency) { 60470034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 60570034214SMatthew G. Knepley /* Get neighboring cells */ 60670034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 60770034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 60870034214SMatthew G. Knepley PetscInt cellOffset = 0; 60970034214SMatthew G. Knepley 6108b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 61170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 61270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 61370034214SMatthew G. Knepley PetscInt cellPair[2]; 61470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 61570034214SMatthew G. Knepley PetscInt meetSize = 0; 61670034214SMatthew G. Knepley const PetscInt *meet = NULL; 61770034214SMatthew G. Knepley 61870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 61970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 62070034214SMatthew G. Knepley if (!found) { 62170034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 62270034214SMatthew G. Knepley if (meetSize) { 62370034214SMatthew G. Knepley PetscInt f; 62470034214SMatthew G. Knepley 62570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 62670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 62770034214SMatthew G. Knepley found = PETSC_TRUE; 62870034214SMatthew G. Knepley break; 62970034214SMatthew G. Knepley } 63070034214SMatthew G. Knepley } 63170034214SMatthew G. Knepley } 63270034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 63370034214SMatthew G. Knepley } 63470034214SMatthew G. Knepley if (found) { 63570034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 63670034214SMatthew G. Knepley ++cellOffset; 63770034214SMatthew G. Knepley } 63870034214SMatthew G. Knepley } 63970034214SMatthew G. Knepley } 64070034214SMatthew G. Knepley } 64170034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 64270034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 64370034214SMatthew G. Knepley if (offsets) *offsets = off; 64470034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 64570034214SMatthew G. Knepley PetscFunctionReturn(0); 64670034214SMatthew G. Knepley } 64770034214SMatthew G. Knepley 64877623264SMatthew G. Knepley /*@C 64977623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 65077623264SMatthew G. Knepley 65177623264SMatthew G. Knepley Not Collective 65277623264SMatthew G. Knepley 65377623264SMatthew G. Knepley Input Parameters: 65477623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 65577623264SMatthew G. Knepley - create_func - The creation routine itself 65677623264SMatthew G. Knepley 65777623264SMatthew G. Knepley Notes: 65877623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 65977623264SMatthew G. Knepley 66077623264SMatthew G. Knepley Sample usage: 66177623264SMatthew G. Knepley .vb 66277623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 66377623264SMatthew G. Knepley .ve 66477623264SMatthew G. Knepley 66577623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 66677623264SMatthew G. Knepley .vb 66777623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 66877623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 66977623264SMatthew G. Knepley .ve 67077623264SMatthew G. Knepley or at runtime via the option 67177623264SMatthew G. Knepley .vb 67277623264SMatthew G. Knepley -petscpartitioner_type my_part 67377623264SMatthew G. Knepley .ve 67477623264SMatthew G. Knepley 67577623264SMatthew G. Knepley Level: advanced 67677623264SMatthew G. Knepley 67777623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 67877623264SMatthew G. Knepley 67977623264SMatthew G. Knepley @*/ 68077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 68177623264SMatthew G. Knepley { 68277623264SMatthew G. Knepley PetscErrorCode ierr; 68377623264SMatthew G. Knepley 68477623264SMatthew G. Knepley PetscFunctionBegin; 68577623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 68677623264SMatthew G. Knepley PetscFunctionReturn(0); 68777623264SMatthew G. Knepley } 68877623264SMatthew G. Knepley 68977623264SMatthew G. Knepley /*@C 69077623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 69177623264SMatthew G. Knepley 692fe2efc57SMark Collective on PetscPartitioner 69377623264SMatthew G. Knepley 69477623264SMatthew G. Knepley Input Parameters: 69577623264SMatthew G. Knepley + part - The PetscPartitioner object 69677623264SMatthew G. Knepley - name - The kind of partitioner 69777623264SMatthew G. Knepley 69877623264SMatthew G. Knepley Options Database Key: 69977623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 70077623264SMatthew G. Knepley 70177623264SMatthew G. Knepley Level: intermediate 70277623264SMatthew G. Knepley 70377623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 70477623264SMatthew G. Knepley @*/ 70577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 70677623264SMatthew G. Knepley { 70777623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 70877623264SMatthew G. Knepley PetscBool match; 70977623264SMatthew G. Knepley PetscErrorCode ierr; 71077623264SMatthew G. Knepley 71177623264SMatthew G. Knepley PetscFunctionBegin; 71277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 71377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 71477623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 71577623264SMatthew G. Knepley 71677623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 71777623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 71877623264SMatthew G. Knepley 71977623264SMatthew G. Knepley if (part->ops->destroy) { 72077623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 72177623264SMatthew G. Knepley } 722074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 723d57f96a3SLisandro Dalcin ierr = PetscMemzero(part->ops, sizeof(*part->ops));CHKERRQ(ierr); 72477623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 725d57f96a3SLisandro Dalcin ierr = (*r)(part);CHKERRQ(ierr); 72677623264SMatthew G. Knepley PetscFunctionReturn(0); 72777623264SMatthew G. Knepley } 72877623264SMatthew G. Knepley 72977623264SMatthew G. Knepley /*@C 73077623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 73177623264SMatthew G. Knepley 73277623264SMatthew G. Knepley Not Collective 73377623264SMatthew G. Knepley 73477623264SMatthew G. Knepley Input Parameter: 73577623264SMatthew G. Knepley . part - The PetscPartitioner 73677623264SMatthew G. Knepley 73777623264SMatthew G. Knepley Output Parameter: 73877623264SMatthew G. Knepley . name - The PetscPartitioner type name 73977623264SMatthew G. Knepley 74077623264SMatthew G. Knepley Level: intermediate 74177623264SMatthew G. Knepley 74277623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 74377623264SMatthew G. Knepley @*/ 74477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 74577623264SMatthew G. Knepley { 74677623264SMatthew G. Knepley PetscFunctionBegin; 74777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 74877623264SMatthew G. Knepley PetscValidPointer(name, 2); 74977623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 75077623264SMatthew G. Knepley PetscFunctionReturn(0); 75177623264SMatthew G. Knepley } 75277623264SMatthew G. Knepley 75377623264SMatthew G. Knepley /*@C 754fe2efc57SMark PetscPartitionerViewFromOptions - View from Options 755fe2efc57SMark 756fe2efc57SMark Collective on PetscPartitioner 757fe2efc57SMark 758fe2efc57SMark Input Parameters: 759fe2efc57SMark + A - the PetscPartitioner object 760fe2efc57SMark . obj - Optional object 761fe2efc57SMark - name - command line option 762fe2efc57SMark 763fe2efc57SMark Level: intermediate 764fe2efc57SMark .seealso: PetscPartitionerView(), PetscObjectViewFromOptions() 765fe2efc57SMark @*/ 766fe2efc57SMark PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner A,PetscObject obj,const char name[]) 767fe2efc57SMark { 768fe2efc57SMark PetscErrorCode ierr; 769fe2efc57SMark 770fe2efc57SMark PetscFunctionBegin; 771fe2efc57SMark PetscValidHeaderSpecific(A,PETSCPARTITIONER_CLASSID,1); 772fe2efc57SMark ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 773fe2efc57SMark PetscFunctionReturn(0); 774fe2efc57SMark } 775fe2efc57SMark 776fe2efc57SMark /*@C 77777623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 77877623264SMatthew G. Knepley 779fe2efc57SMark Collective on PetscPartitioner 78077623264SMatthew G. Knepley 78177623264SMatthew G. Knepley Input Parameter: 78277623264SMatthew G. Knepley + part - the PetscPartitioner object to view 78377623264SMatthew G. Knepley - v - the viewer 78477623264SMatthew G. Knepley 78577623264SMatthew G. Knepley Level: developer 78677623264SMatthew G. Knepley 78777623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 78877623264SMatthew G. Knepley @*/ 78977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 79077623264SMatthew G. Knepley { 791ffc59708SMatthew G. Knepley PetscMPIInt size; 7922abdaa70SMatthew G. Knepley PetscBool isascii; 79377623264SMatthew G. Knepley PetscErrorCode ierr; 79477623264SMatthew G. Knepley 79577623264SMatthew G. Knepley PetscFunctionBegin; 79677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 79777623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 7982abdaa70SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 7992abdaa70SMatthew G. Knepley if (isascii) { 8002abdaa70SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 801ffc59708SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");CHKERRQ(ierr); 8022abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " type: %s\n", part->hdr.type_name);CHKERRQ(ierr); 8032abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " edge cut: %D\n", part->edgeCut);CHKERRQ(ierr); 8042abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(v, " balance: %.2g\n", part->balance);CHKERRQ(ierr); 8053c41b853SStefano Zampini ierr = PetscViewerASCIIPrintf(v, " use vertex weights: %d\n", part->usevwgt);CHKERRQ(ierr); 8062abdaa70SMatthew G. Knepley } 80777623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 80877623264SMatthew G. Knepley PetscFunctionReturn(0); 80977623264SMatthew G. Knepley } 81077623264SMatthew G. Knepley 811a0058e54SToby Isaac static PetscErrorCode PetscPartitionerGetDefaultType(const char *currentType, const char **defaultType) 812a0058e54SToby Isaac { 813a0058e54SToby Isaac PetscFunctionBegin; 814a0058e54SToby Isaac if (!currentType) { 81556bf5a81SLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 816a0058e54SToby Isaac *defaultType = PETSCPARTITIONERPARMETIS; 817137cd93aSLisandro Dalcin #elif defined(PETSC_HAVE_PTSCOTCH) 818137cd93aSLisandro Dalcin *defaultType = PETSCPARTITIONERPTSCOTCH; 81956bf5a81SLisandro Dalcin #elif defined(PETSC_HAVE_CHACO) 82056bf5a81SLisandro Dalcin *defaultType = PETSCPARTITIONERCHACO; 821a0058e54SToby Isaac #else 822a0058e54SToby Isaac *defaultType = PETSCPARTITIONERSIMPLE; 823a0058e54SToby Isaac #endif 824a0058e54SToby Isaac } else { 825a0058e54SToby Isaac *defaultType = currentType; 826a0058e54SToby Isaac } 827a0058e54SToby Isaac PetscFunctionReturn(0); 828a0058e54SToby Isaac } 829a0058e54SToby Isaac 83077623264SMatthew G. Knepley /*@ 83177623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 83277623264SMatthew G. Knepley 833fe2efc57SMark Collective on PetscPartitioner 83477623264SMatthew G. Knepley 83577623264SMatthew G. Knepley Input Parameter: 83677623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 83777623264SMatthew G. Knepley 8383c41b853SStefano Zampini Options Database Keys: 8393c41b853SStefano Zampini + -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 8403c41b853SStefano Zampini . -petscpartitioner_use_vertex_weights - Uses weights associated with the graph vertices 8413c41b853SStefano Zampini - -petscpartitioner_view_graph - View the graph each time PetscPartitionerPartition is called. Viewer can be customized, see PetscOptionsGetViewer() 8423c41b853SStefano Zampini 84377623264SMatthew G. Knepley Level: developer 84477623264SMatthew G. Knepley 8453c41b853SStefano Zampini .seealso: PetscPartitionerView(), PetscPartitionerSetType(), PetscPartitionerPartition() 84677623264SMatthew G. Knepley @*/ 84777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 84877623264SMatthew G. Knepley { 8496bb9daa8SLisandro Dalcin const char *defaultType; 8506bb9daa8SLisandro Dalcin char name[256]; 8516bb9daa8SLisandro Dalcin PetscBool flg; 85277623264SMatthew G. Knepley PetscErrorCode ierr; 85377623264SMatthew G. Knepley 85477623264SMatthew G. Knepley PetscFunctionBegin; 85577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8566bb9daa8SLisandro Dalcin ierr = PetscPartitionerGetDefaultType(((PetscObject) part)->type_name,&defaultType);CHKERRQ(ierr); 85777623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 8586bb9daa8SLisandro Dalcin ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, sizeof(name), &flg);CHKERRQ(ierr); 8596bb9daa8SLisandro Dalcin if (flg) { 8606bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 8616bb9daa8SLisandro Dalcin } else if (!((PetscObject) part)->type_name) { 8626bb9daa8SLisandro Dalcin ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 8636bb9daa8SLisandro Dalcin } 8643c41b853SStefano Zampini ierr = PetscOptionsBool("-petscpartitioner_use_vertex_weights","Use vertex weights","",part->usevwgt,&part->usevwgt,NULL);CHKERRQ(ierr); 8656bb9daa8SLisandro Dalcin if (part->ops->setfromoptions) { 8666bb9daa8SLisandro Dalcin ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr); 8676bb9daa8SLisandro Dalcin } 8683c41b853SStefano Zampini ierr = PetscViewerDestroy(&part->viewer);CHKERRQ(ierr); 869783e1fb6SStefano Zampini ierr = PetscViewerDestroy(&part->viewerGraph);CHKERRQ(ierr); 8703c41b853SStefano Zampini ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view", &part->viewer, NULL, NULL);CHKERRQ(ierr); 8713c41b853SStefano Zampini ierr = PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, NULL, &part->viewGraph);CHKERRQ(ierr); 87277623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 8730633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 87477623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 87577623264SMatthew G. Knepley PetscFunctionReturn(0); 87677623264SMatthew G. Knepley } 87777623264SMatthew G. Knepley 87877623264SMatthew G. Knepley /*@C 87977623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 88077623264SMatthew G. Knepley 881fe2efc57SMark Collective on PetscPartitioner 88277623264SMatthew G. Knepley 88377623264SMatthew G. Knepley Input Parameter: 88477623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 88577623264SMatthew G. Knepley 88677623264SMatthew G. Knepley Level: developer 88777623264SMatthew G. Knepley 88877623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 88977623264SMatthew G. Knepley @*/ 89077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 89177623264SMatthew G. Knepley { 89277623264SMatthew G. Knepley PetscErrorCode ierr; 89377623264SMatthew G. Knepley 89477623264SMatthew G. Knepley PetscFunctionBegin; 89577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 89677623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 89777623264SMatthew G. Knepley PetscFunctionReturn(0); 89877623264SMatthew G. Knepley } 89977623264SMatthew G. Knepley 90077623264SMatthew G. Knepley /*@ 90177623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 90277623264SMatthew G. Knepley 903fe2efc57SMark Collective on PetscPartitioner 90477623264SMatthew G. Knepley 90577623264SMatthew G. Knepley Input Parameter: 90677623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 90777623264SMatthew G. Knepley 90877623264SMatthew G. Knepley Level: developer 90977623264SMatthew G. Knepley 91077623264SMatthew G. Knepley .seealso: PetscPartitionerView() 91177623264SMatthew G. Knepley @*/ 91277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 91377623264SMatthew G. Knepley { 91477623264SMatthew G. Knepley PetscErrorCode ierr; 91577623264SMatthew G. Knepley 91677623264SMatthew G. Knepley PetscFunctionBegin; 91777623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 91877623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 91977623264SMatthew G. Knepley 92077623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 92177623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 92277623264SMatthew G. Knepley 9233c41b853SStefano Zampini ierr = PetscViewerDestroy(&(*part)->viewer);CHKERRQ(ierr); 9240358368aSMatthew G. Knepley ierr = PetscViewerDestroy(&(*part)->viewerGraph);CHKERRQ(ierr); 92577623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 92677623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 92777623264SMatthew G. Knepley PetscFunctionReturn(0); 92877623264SMatthew G. Knepley } 92977623264SMatthew G. Knepley 93077623264SMatthew G. Knepley /*@ 9313c41b853SStefano Zampini PetscPartitionerPartition - Partition a graph 9323c41b853SStefano Zampini 9333c41b853SStefano Zampini Collective on PetscPartitioner 9343c41b853SStefano Zampini 9353c41b853SStefano Zampini Input Parameters: 9363c41b853SStefano Zampini + part - The PetscPartitioner 9373c41b853SStefano Zampini . nparts - Number of partitions 9383c41b853SStefano Zampini . numVertices - Number of vertices in the local part of the graph 9393c41b853SStefano Zampini . start - row pointers for the local part of the graph (CSR style) 9403c41b853SStefano Zampini . adjacency - adjacency list (CSR style) 9413c41b853SStefano Zampini . vertexSection - PetscSection describing the absolute weight of each local vertex (can be NULL) 9423c41b853SStefano Zampini - targetSection - PetscSection describing the absolute weight of each partition (can be NULL) 9433c41b853SStefano Zampini 9443c41b853SStefano Zampini Output Parameters: 9453c41b853SStefano Zampini + partSection - The PetscSection giving the division of points by partition 9463c41b853SStefano Zampini - partition - The list of points by partition 9473c41b853SStefano Zampini 9483c41b853SStefano Zampini Options Database: 9493c41b853SStefano Zampini . -petscpartitioner_view - View the partitioner information 9503c41b853SStefano Zampini . -petscpartitioner_view_graph - View the graph we are partitioning 9513c41b853SStefano Zampini 9523c41b853SStefano Zampini Notes: 9533c41b853SStefano Zampini The chart of the vertexSection (if present) must contain [0,numVertices), with the number of dofs in the section specifying the absolute weight for each vertex. 9543c41b853SStefano Zampini The chart of the targetSection (if present) must contain [0,nparts), with the number of dofs in the section specifying the absolute weight for each partition. This information must be the same across processes, PETSc does not check it. 9553c41b853SStefano Zampini 9563c41b853SStefano Zampini Level: developer 9573c41b853SStefano Zampini 9583c41b853SStefano Zampini .seealso PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscSectionSetDof() 9593c41b853SStefano Zampini @*/ 9603c41b853SStefano Zampini PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection targetSection, PetscSection partSection, IS *partition) 9613c41b853SStefano Zampini { 9623c41b853SStefano Zampini PetscErrorCode ierr; 9633c41b853SStefano Zampini 9643c41b853SStefano Zampini PetscFunctionBegin; 9653c41b853SStefano Zampini PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 9663c41b853SStefano Zampini PetscValidLogicalCollectiveInt(part, nparts, 2); 9673c41b853SStefano Zampini if (nparts <= 0) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Number of parts must be positive"); 9683c41b853SStefano Zampini if (numVertices < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices must be non-negative"); 9693c41b853SStefano Zampini if (numVertices && !part->noGraph) { 9703c41b853SStefano Zampini PetscValidIntPointer(start, 4); 971*cf3b5a5fSLisandro Dalcin PetscValidIntPointer(start + numVertices, 4); 972e4ba4cd7SStefano Zampini if (start[numVertices]) PetscValidIntPointer(adjacency, 5); 9733c41b853SStefano Zampini } 9743c41b853SStefano Zampini if (vertexSection) { 9753c41b853SStefano Zampini PetscInt s,e; 9763c41b853SStefano Zampini 9773c41b853SStefano Zampini PetscValidHeaderSpecific(vertexSection, PETSC_SECTION_CLASSID, 6); 9783c41b853SStefano Zampini ierr = PetscSectionGetChart(vertexSection, &s, &e);CHKERRQ(ierr); 9793c41b853SStefano Zampini if (s > 0 || e < numVertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid vertexSection chart [%D,%D)",s,e); 9803c41b853SStefano Zampini } 9813c41b853SStefano Zampini if (targetSection) { 9823c41b853SStefano Zampini PetscInt s,e; 9833c41b853SStefano Zampini 9843c41b853SStefano Zampini PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 7); 9853c41b853SStefano Zampini ierr = PetscSectionGetChart(targetSection, &s, &e);CHKERRQ(ierr); 9863c41b853SStefano Zampini if (s > 0 || e < nparts) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid targetSection chart [%D,%D)",s,e); 9873c41b853SStefano Zampini } 9883c41b853SStefano Zampini PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 8); 9893c41b853SStefano Zampini PetscValidPointer(partition, 9); 9903c41b853SStefano Zampini 9913c41b853SStefano Zampini ierr = PetscSectionReset(partSection);CHKERRQ(ierr); 9923c41b853SStefano Zampini ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 9933c41b853SStefano Zampini if (nparts == 1) { /* quick */ 9943c41b853SStefano Zampini ierr = PetscSectionSetDof(partSection, 0, numVertices);CHKERRQ(ierr); 9953c41b853SStefano Zampini ierr = ISCreateStride(PetscObjectComm((PetscObject)part),numVertices,0,1,partition);CHKERRQ(ierr); 9963c41b853SStefano Zampini } else { 9973c41b853SStefano Zampini if (!part->ops->partition) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "PetscPartitioner %s has no partitioning method", ((PetscObject)part)->type_name); 9983c41b853SStefano Zampini ierr = (*part->ops->partition)(part, nparts, numVertices, start, adjacency, vertexSection, targetSection, partSection, partition);CHKERRQ(ierr); 9993c41b853SStefano Zampini } 10003c41b853SStefano Zampini ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 10013c41b853SStefano Zampini if (part->viewerGraph) { 10023c41b853SStefano Zampini PetscViewer viewer = part->viewerGraph; 10033c41b853SStefano Zampini PetscBool isascii; 10043c41b853SStefano Zampini PetscInt v, i; 10053c41b853SStefano Zampini PetscMPIInt rank; 10063c41b853SStefano Zampini 10073c41b853SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRQ(ierr); 10083c41b853SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 10093c41b853SStefano Zampini if (isascii) { 10103c41b853SStefano Zampini ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 10113c41b853SStefano Zampini ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);CHKERRQ(ierr); 10123c41b853SStefano Zampini for (v = 0; v < numVertices; ++v) { 10133c41b853SStefano Zampini const PetscInt s = start[v]; 10143c41b853SStefano Zampini const PetscInt e = start[v+1]; 10153c41b853SStefano Zampini 10163c41b853SStefano Zampini ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank);CHKERRQ(ierr); 10173c41b853SStefano Zampini for (i = s; i < e; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);CHKERRQ(ierr);} 10183c41b853SStefano Zampini ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);CHKERRQ(ierr); 10193c41b853SStefano Zampini } 10203c41b853SStefano Zampini ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 10213c41b853SStefano Zampini ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 10223c41b853SStefano Zampini } 10233c41b853SStefano Zampini } 10243c41b853SStefano Zampini if (part->viewer) { 10253c41b853SStefano Zampini ierr = PetscPartitionerView(part,part->viewer);CHKERRQ(ierr); 10263c41b853SStefano Zampini } 10273c41b853SStefano Zampini PetscFunctionReturn(0); 10283c41b853SStefano Zampini } 10293c41b853SStefano Zampini 10303c41b853SStefano Zampini /*@ 103177623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 103277623264SMatthew G. Knepley 1033d083f849SBarry Smith Collective 103477623264SMatthew G. Knepley 103577623264SMatthew G. Knepley Input Parameter: 103677623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 103777623264SMatthew G. Knepley 103877623264SMatthew G. Knepley Output Parameter: 103977623264SMatthew G. Knepley . part - The PetscPartitioner object 104077623264SMatthew G. Knepley 104177623264SMatthew G. Knepley Level: beginner 104277623264SMatthew G. Knepley 1043dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 104477623264SMatthew G. Knepley @*/ 104577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 104677623264SMatthew G. Knepley { 104777623264SMatthew G. Knepley PetscPartitioner p; 1048a0058e54SToby Isaac const char *partitionerType = NULL; 104977623264SMatthew G. Knepley PetscErrorCode ierr; 105077623264SMatthew G. Knepley 105177623264SMatthew G. Knepley PetscFunctionBegin; 105277623264SMatthew G. Knepley PetscValidPointer(part, 2); 105377623264SMatthew G. Knepley *part = NULL; 105483cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 105577623264SMatthew G. Knepley 105673107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 1057a0058e54SToby Isaac ierr = PetscPartitionerGetDefaultType(NULL,&partitionerType);CHKERRQ(ierr); 1058a0058e54SToby Isaac ierr = PetscPartitionerSetType(p,partitionerType);CHKERRQ(ierr); 105977623264SMatthew G. Knepley 106072379da4SMatthew G. Knepley p->edgeCut = 0; 106172379da4SMatthew G. Knepley p->balance = 0.0; 10623c41b853SStefano Zampini p->usevwgt = PETSC_TRUE; 106372379da4SMatthew G. Knepley 106477623264SMatthew G. Knepley *part = p; 106577623264SMatthew G. Knepley PetscFunctionReturn(0); 106677623264SMatthew G. Knepley } 106777623264SMatthew G. Knepley 106877623264SMatthew G. Knepley /*@ 10693c41b853SStefano Zampini PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh 107077623264SMatthew G. Knepley 1071fe2efc57SMark Collective on PetscPartitioner 107277623264SMatthew G. Knepley 107377623264SMatthew G. Knepley Input Parameters: 107477623264SMatthew G. Knepley + part - The PetscPartitioner 10753c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL) 1076f8987ae8SMichael Lange - dm - The mesh DM 107777623264SMatthew G. Knepley 107877623264SMatthew G. Knepley Output Parameters: 107977623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 1080f8987ae8SMichael Lange - partition - The list of points by partition 108177623264SMatthew G. Knepley 10823c41b853SStefano Zampini Notes: 10833c41b853SStefano Zampini If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified 10843c41b853SStefano Zampini by the section in the transitive closure of the point. 108577623264SMatthew G. Knepley 108677623264SMatthew G. Knepley Level: developer 108777623264SMatthew G. Knepley 10883c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition() 10894b15ede2SMatthew G. Knepley @*/ 10903c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition) 109177623264SMatthew G. Knepley { 109277623264SMatthew G. Knepley PetscMPIInt size; 10933c41b853SStefano Zampini PetscBool isplex; 109477623264SMatthew G. Knepley PetscErrorCode ierr; 10953c41b853SStefano Zampini PetscSection vertSection = NULL; 109677623264SMatthew G. Knepley 109777623264SMatthew G. Knepley PetscFunctionBegin; 109877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 109977623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 11003c41b853SStefano Zampini if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3); 110177623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 110277623264SMatthew G. Knepley PetscValidPointer(partition, 5); 11033c41b853SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr); 11043c41b853SStefano Zampini if (!isplex) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name); 110577623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 110677623264SMatthew G. Knepley if (size == 1) { 110777623264SMatthew G. Knepley PetscInt *points; 110877623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 110977623264SMatthew G. Knepley 111077623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 11113c41b853SStefano Zampini ierr = PetscSectionReset(partSection);CHKERRQ(ierr); 111277623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 111377623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 111477623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 111577623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 111677623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 111777623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 111877623264SMatthew G. Knepley PetscFunctionReturn(0); 111977623264SMatthew G. Knepley } 112077623264SMatthew G. Knepley if (part->height == 0) { 1121074d466cSStefano Zampini PetscInt numVertices = 0; 112277623264SMatthew G. Knepley PetscInt *start = NULL; 112377623264SMatthew G. Knepley PetscInt *adjacency = NULL; 11243fa7752dSToby Isaac IS globalNumbering; 112577623264SMatthew G. Knepley 1126074d466cSStefano Zampini if (!part->noGraph || part->viewGraph) { 1127074d466cSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 112813911537SStefano Zampini } else { /* only compute the number of owned local vertices */ 1129074d466cSStefano Zampini const PetscInt *idxs; 1130074d466cSStefano Zampini PetscInt p, pStart, pEnd; 1131074d466cSStefano Zampini 1132074d466cSStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 11339886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr); 1134074d466cSStefano Zampini ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr); 1135074d466cSStefano Zampini for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1; 1136074d466cSStefano Zampini ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr); 1137074d466cSStefano Zampini } 11383c41b853SStefano Zampini if (part->usevwgt) { 11393c41b853SStefano Zampini PetscSection section = dm->localSection, clSection = NULL; 11403c41b853SStefano Zampini IS clPoints = NULL; 11413c41b853SStefano Zampini const PetscInt *gid,*clIdx; 11423c41b853SStefano Zampini PetscInt v, p, pStart, pEnd; 11430358368aSMatthew G. Knepley 11443c41b853SStefano Zampini /* dm->localSection encodes degrees of freedom per point, not per cell. We need to get the closure index to properly specify cell weights (aka dofs) */ 11453c41b853SStefano Zampini /* We do this only if the local section has been set */ 11463c41b853SStefano Zampini if (section) { 11473c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL);CHKERRQ(ierr); 11483c41b853SStefano Zampini if (!clSection) { 11493c41b853SStefano Zampini ierr = DMPlexCreateClosureIndex(dm,NULL);CHKERRQ(ierr); 11503c41b853SStefano Zampini } 11513c41b853SStefano Zampini ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints);CHKERRQ(ierr); 11523c41b853SStefano Zampini ierr = ISGetIndices(clPoints,&clIdx);CHKERRQ(ierr); 11533c41b853SStefano Zampini } 11543c41b853SStefano Zampini ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr); 11553c41b853SStefano Zampini ierr = PetscSectionCreate(PETSC_COMM_SELF, &vertSection);CHKERRQ(ierr); 11563c41b853SStefano Zampini ierr = PetscSectionSetChart(vertSection, 0, numVertices);CHKERRQ(ierr); 11573c41b853SStefano Zampini if (globalNumbering) { 11583c41b853SStefano Zampini ierr = ISGetIndices(globalNumbering,&gid);CHKERRQ(ierr); 11593c41b853SStefano Zampini } else gid = NULL; 11603c41b853SStefano Zampini for (p = pStart, v = 0; p < pEnd; ++p) { 11613c41b853SStefano Zampini PetscInt dof = 1; 11620358368aSMatthew G. Knepley 11633c41b853SStefano Zampini /* skip cells in the overlap */ 11643c41b853SStefano Zampini if (gid && gid[p-pStart] < 0) continue; 11653c41b853SStefano Zampini 11663c41b853SStefano Zampini if (section) { 11673c41b853SStefano Zampini PetscInt cl, clSize, clOff; 11683c41b853SStefano Zampini 11693c41b853SStefano Zampini dof = 0; 11703c41b853SStefano Zampini ierr = PetscSectionGetDof(clSection, p, &clSize);CHKERRQ(ierr); 11713c41b853SStefano Zampini ierr = PetscSectionGetOffset(clSection, p, &clOff);CHKERRQ(ierr); 11723c41b853SStefano Zampini for (cl = 0; cl < clSize; cl+=2) { 11733c41b853SStefano Zampini PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */ 11743c41b853SStefano Zampini 11753c41b853SStefano Zampini ierr = PetscSectionGetDof(section, clPoint, &clDof);CHKERRQ(ierr); 11763c41b853SStefano Zampini dof += clDof; 11770358368aSMatthew G. Knepley } 11780358368aSMatthew G. Knepley } 11793c41b853SStefano Zampini if (!dof) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p); 11803c41b853SStefano Zampini ierr = PetscSectionSetDof(vertSection, v, dof);CHKERRQ(ierr); 11813c41b853SStefano Zampini v++; 11823c41b853SStefano Zampini } 11833c41b853SStefano Zampini if (globalNumbering) { 11843c41b853SStefano Zampini ierr = ISRestoreIndices(globalNumbering,&gid);CHKERRQ(ierr); 11853c41b853SStefano Zampini } 11863c41b853SStefano Zampini if (clPoints) { 11873c41b853SStefano Zampini ierr = ISRestoreIndices(clPoints,&clIdx);CHKERRQ(ierr); 11883c41b853SStefano Zampini } 11893c41b853SStefano Zampini ierr = PetscSectionSetUp(vertSection);CHKERRQ(ierr); 11903c41b853SStefano Zampini } 11913c41b853SStefano Zampini ierr = PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition);CHKERRQ(ierr); 119277623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 119377623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 11943fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 11953fa7752dSToby Isaac const PetscInt *globalNum; 11963fa7752dSToby Isaac const PetscInt *partIdx; 11973fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 11983fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 11993fa7752dSToby Isaac IS newPartition; 12003fa7752dSToby Isaac 12013fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 12023fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 12033fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 12043fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 12053fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 12063fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 12073fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 12083fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 12093fa7752dSToby Isaac } 12103fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 12113fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 12123fa7752dSToby Isaac } 12133fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 12143fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 12153fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 12163fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 12173fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 12183fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 12193fa7752dSToby Isaac *partition = newPartition; 12203fa7752dSToby Isaac } 122177623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 12223c41b853SStefano Zampini ierr = PetscSectionDestroy(&vertSection);CHKERRQ(ierr); 122377623264SMatthew G. Knepley PetscFunctionReturn(0); 122477623264SMatthew G. Knepley } 122577623264SMatthew G. Knepley 1226d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 122777623264SMatthew G. Knepley { 122877623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 122977623264SMatthew G. Knepley PetscErrorCode ierr; 123077623264SMatthew G. Knepley 123177623264SMatthew G. Knepley PetscFunctionBegin; 123277623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 123377623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 123477623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 123577623264SMatthew G. Knepley PetscFunctionReturn(0); 123677623264SMatthew G. Knepley } 123777623264SMatthew G. Knepley 1238d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 123977623264SMatthew G. Knepley { 1240077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 124177623264SMatthew G. Knepley PetscErrorCode ierr; 124277623264SMatthew G. Knepley 124377623264SMatthew G. Knepley PetscFunctionBegin; 1244077101c0SMatthew G. Knepley if (p->random) { 1245077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1246077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 1247077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1248077101c0SMatthew G. Knepley } 124977623264SMatthew G. Knepley PetscFunctionReturn(0); 125077623264SMatthew G. Knepley } 125177623264SMatthew G. Knepley 1252d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 125377623264SMatthew G. Knepley { 125477623264SMatthew G. Knepley PetscBool iascii; 125577623264SMatthew G. Knepley PetscErrorCode ierr; 125677623264SMatthew G. Knepley 125777623264SMatthew G. Knepley PetscFunctionBegin; 125877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 125977623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 126077623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 126177623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 126277623264SMatthew G. Knepley PetscFunctionReturn(0); 126377623264SMatthew G. Knepley } 126477623264SMatthew G. Knepley 1265d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 1266077101c0SMatthew G. Knepley { 1267077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1268077101c0SMatthew G. Knepley PetscErrorCode ierr; 1269077101c0SMatthew G. Knepley 1270077101c0SMatthew G. Knepley PetscFunctionBegin; 1271077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 1272077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 1273077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 1274077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1275077101c0SMatthew G. Knepley } 1276077101c0SMatthew G. Knepley 12773c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 127877623264SMatthew G. Knepley { 127977623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 128077623264SMatthew G. Knepley PetscInt np; 128177623264SMatthew G. Knepley PetscErrorCode ierr; 128277623264SMatthew G. Knepley 128377623264SMatthew G. Knepley PetscFunctionBegin; 1284077101c0SMatthew G. Knepley if (p->random) { 1285077101c0SMatthew G. Knepley PetscRandom r; 1286aa1d5631SMatthew G. Knepley PetscInt *sizes, *points, v, p; 1287aa1d5631SMatthew G. Knepley PetscMPIInt rank; 1288077101c0SMatthew G. Knepley 12893c41b853SStefano Zampini ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) part), &rank);CHKERRQ(ierr); 1290077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 1291c717d290SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 1292077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 1293077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 1294aa1d5631SMatthew G. Knepley for (v = 0; v < numVertices; ++v) {points[v] = v;} 1295ac9a96f1SMichael Lange for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 1296aa1d5631SMatthew G. Knepley for (v = numVertices-1; v > 0; --v) { 1297077101c0SMatthew G. Knepley PetscReal val; 1298aa1d5631SMatthew G. Knepley PetscInt w, tmp; 1299077101c0SMatthew G. Knepley 1300aa1d5631SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 1301077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 1302aa1d5631SMatthew G. Knepley w = PetscFloorReal(val); 1303aa1d5631SMatthew G. Knepley tmp = points[v]; 1304aa1d5631SMatthew G. Knepley points[v] = points[w]; 1305aa1d5631SMatthew G. Knepley points[w] = tmp; 1306077101c0SMatthew G. Knepley } 1307077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 1308077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 1309077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 1310077101c0SMatthew G. Knepley } 13113c41b853SStefano Zampini if (!p->section) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 131277623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 131377623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 131477623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 131577623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 13165680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 131777623264SMatthew G. Knepley *partition = p->partition; 131877623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 131977623264SMatthew G. Knepley PetscFunctionReturn(0); 132077623264SMatthew G. Knepley } 132177623264SMatthew G. Knepley 1322d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 132377623264SMatthew G. Knepley { 132477623264SMatthew G. Knepley PetscFunctionBegin; 1325074d466cSStefano Zampini part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 132677623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 1327077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 132877623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 132977623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 133077623264SMatthew G. Knepley PetscFunctionReturn(0); 133177623264SMatthew G. Knepley } 133277623264SMatthew G. Knepley 133377623264SMatthew G. Knepley /*MC 133477623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 133577623264SMatthew G. Knepley 133677623264SMatthew G. Knepley Level: intermediate 133777623264SMatthew G. Knepley 13383c41b853SStefano Zampini Options Database Keys: 13393c41b853SStefano Zampini . -petscpartitioner_shell_random - Use a random partition 13403c41b853SStefano Zampini 134177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 134277623264SMatthew G. Knepley M*/ 134377623264SMatthew G. Knepley 134477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 134577623264SMatthew G. Knepley { 134677623264SMatthew G. Knepley PetscPartitioner_Shell *p; 134777623264SMatthew G. Knepley PetscErrorCode ierr; 134877623264SMatthew G. Knepley 134977623264SMatthew G. Knepley PetscFunctionBegin; 135077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 135177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 135277623264SMatthew G. Knepley part->data = p; 135377623264SMatthew G. Knepley 135477623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 1355077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 135677623264SMatthew G. Knepley PetscFunctionReturn(0); 135777623264SMatthew G. Knepley } 135877623264SMatthew G. Knepley 13595680f57bSMatthew G. Knepley /*@C 13605680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 13615680f57bSMatthew G. Knepley 1362fe2efc57SMark Collective on PetscPartitioner 13635680f57bSMatthew G. Knepley 13645680f57bSMatthew G. Knepley Input Parameters: 13655680f57bSMatthew G. Knepley + part - The PetscPartitioner 13669852e123SBarry Smith . size - The number of partitions 13673c41b853SStefano Zampini . sizes - array of length size (or NULL) providing the number of points in each partition 13683c41b853SStefano Zampini - points - array of length 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.) 13695680f57bSMatthew G. Knepley 13705680f57bSMatthew G. Knepley Level: developer 13715680f57bSMatthew G. Knepley 1372b7e49471SLawrence Mitchell Notes: 1373b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 1374b7e49471SLawrence Mitchell 13755680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 13765680f57bSMatthew G. Knepley @*/ 13779852e123SBarry Smith PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 13785680f57bSMatthew G. Knepley { 13795680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 13805680f57bSMatthew G. Knepley PetscInt proc, numPoints; 13815680f57bSMatthew G. Knepley PetscErrorCode ierr; 13825680f57bSMatthew G. Knepley 13835680f57bSMatthew G. Knepley PetscFunctionBegin; 13845680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 13855680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 1386c717d290SMatthew G. Knepley if (points) {PetscValidPointer(points, 4);} 13875680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 13885680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 13895680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 13909852e123SBarry Smith ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 13915680f57bSMatthew G. Knepley if (sizes) { 13929852e123SBarry Smith for (proc = 0; proc < size; ++proc) { 13935680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 13945680f57bSMatthew G. Knepley } 13955680f57bSMatthew G. Knepley } 13965680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 13975680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 13985680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 13995680f57bSMatthew G. Knepley PetscFunctionReturn(0); 14005680f57bSMatthew G. Knepley } 14015680f57bSMatthew G. Knepley 1402077101c0SMatthew G. Knepley /*@ 1403077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 1404077101c0SMatthew G. Knepley 1405fe2efc57SMark Collective on PetscPartitioner 1406077101c0SMatthew G. Knepley 1407077101c0SMatthew G. Knepley Input Parameters: 1408077101c0SMatthew G. Knepley + part - The PetscPartitioner 1409077101c0SMatthew G. Knepley - random - The flag to use a random partition 1410077101c0SMatthew G. Knepley 1411077101c0SMatthew G. Knepley Level: intermediate 1412077101c0SMatthew G. Knepley 1413077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 1414077101c0SMatthew G. Knepley @*/ 1415077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 1416077101c0SMatthew G. Knepley { 1417077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1418077101c0SMatthew G. Knepley 1419077101c0SMatthew G. Knepley PetscFunctionBegin; 1420077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1421077101c0SMatthew G. Knepley p->random = random; 1422077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1423077101c0SMatthew G. Knepley } 1424077101c0SMatthew G. Knepley 1425077101c0SMatthew G. Knepley /*@ 1426077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 1427077101c0SMatthew G. Knepley 1428fe2efc57SMark Collective on PetscPartitioner 1429077101c0SMatthew G. Knepley 1430077101c0SMatthew G. Knepley Input Parameter: 1431077101c0SMatthew G. Knepley . part - The PetscPartitioner 1432077101c0SMatthew G. Knepley 1433077101c0SMatthew G. Knepley Output Parameter 1434077101c0SMatthew G. Knepley . random - The flag to use a random partition 1435077101c0SMatthew G. Knepley 1436077101c0SMatthew G. Knepley Level: intermediate 1437077101c0SMatthew G. Knepley 1438077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 1439077101c0SMatthew G. Knepley @*/ 1440077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 1441077101c0SMatthew G. Knepley { 1442077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 1443077101c0SMatthew G. Knepley 1444077101c0SMatthew G. Knepley PetscFunctionBegin; 1445077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1446077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 1447077101c0SMatthew G. Knepley *random = p->random; 1448077101c0SMatthew G. Knepley PetscFunctionReturn(0); 1449077101c0SMatthew G. Knepley } 1450077101c0SMatthew G. Knepley 1451d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 1452555a9cf8SMatthew G. Knepley { 1453555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 1454555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1455555a9cf8SMatthew G. Knepley 1456555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1457555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 1458555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1459555a9cf8SMatthew G. Knepley } 1460555a9cf8SMatthew G. Knepley 1461d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 1462555a9cf8SMatthew G. Knepley { 1463555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1464555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1465555a9cf8SMatthew G. Knepley } 1466555a9cf8SMatthew G. Knepley 1467d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 1468555a9cf8SMatthew G. Knepley { 1469555a9cf8SMatthew G. Knepley PetscBool iascii; 1470555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1471555a9cf8SMatthew G. Knepley 1472555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1473555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1474555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1475555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1476555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 1477555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1478555a9cf8SMatthew G. Knepley } 1479555a9cf8SMatthew G. Knepley 14803c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 1481555a9cf8SMatthew G. Knepley { 1482cead94edSToby Isaac MPI_Comm comm; 14833c41b853SStefano Zampini PetscInt np, *tpwgts = NULL, sumw = 0, numVerticesGlobal = 0; 1484cead94edSToby Isaac PetscMPIInt size; 1485555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1486555a9cf8SMatthew G. Knepley 1487555a9cf8SMatthew G. Knepley PetscFunctionBegin; 14883c41b853SStefano Zampini if (vertSection) { ierr = PetscInfo(part,"PETSCPARTITIONERSIMPLE ignores vertex weights\n");CHKERRQ(ierr); } 148904ba2274SStefano Zampini comm = PetscObjectComm((PetscObject)part); 1490cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 14913c41b853SStefano Zampini if (targetSection) { 14923c41b853SStefano Zampini ierr = MPIU_Allreduce(&numVertices, &numVerticesGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 14933c41b853SStefano Zampini ierr = PetscCalloc1(nparts,&tpwgts);CHKERRQ(ierr); 14943c41b853SStefano Zampini for (np = 0; np < nparts; ++np) { 14953c41b853SStefano Zampini ierr = PetscSectionGetDof(targetSection,np,&tpwgts[np]);CHKERRQ(ierr); 14963c41b853SStefano Zampini sumw += tpwgts[np]; 14973c41b853SStefano Zampini } 14983c41b853SStefano Zampini if (!sumw) { 14993c41b853SStefano Zampini ierr = PetscFree(tpwgts);CHKERRQ(ierr); 15003c41b853SStefano Zampini } else { 15013c41b853SStefano Zampini PetscInt m,mp; 15023c41b853SStefano Zampini for (np = 0; np < nparts; ++np) tpwgts[np] = (tpwgts[np]*numVerticesGlobal)/sumw; 15033c41b853SStefano Zampini for (np = 0, m = -1, mp = 0, sumw = 0; np < nparts; ++np) { 15043c41b853SStefano Zampini if (m < tpwgts[np]) { m = tpwgts[np]; mp = np; } 15053c41b853SStefano Zampini sumw += tpwgts[np]; 15063c41b853SStefano Zampini } 15073c41b853SStefano Zampini if (sumw != numVerticesGlobal) tpwgts[mp] += numVerticesGlobal - sumw; 15083c41b853SStefano Zampini } 15093c41b853SStefano Zampini } 15103c41b853SStefano Zampini 1511555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1512cead94edSToby Isaac if (size == 1) { 15133c41b853SStefano Zampini if (tpwgts) { 15143c41b853SStefano Zampini for (np = 0; np < nparts; ++np) { 15153c41b853SStefano Zampini ierr = PetscSectionSetDof(partSection, np, tpwgts[np]);CHKERRQ(ierr); 15163c41b853SStefano Zampini } 15173c41b853SStefano Zampini } else { 15183c41b853SStefano Zampini for (np = 0; np < nparts; ++np) { 15193c41b853SStefano Zampini ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr); 15203c41b853SStefano Zampini } 15213c41b853SStefano Zampini } 15223c41b853SStefano Zampini } else { 15233c41b853SStefano Zampini if (tpwgts) { 15243c41b853SStefano Zampini Vec v; 15253c41b853SStefano Zampini PetscScalar *array; 15263c41b853SStefano Zampini PetscInt st,j; 15273c41b853SStefano Zampini PetscMPIInt rank; 15283c41b853SStefano Zampini 15293c41b853SStefano Zampini ierr = VecCreate(comm,&v);CHKERRQ(ierr); 15303c41b853SStefano Zampini ierr = VecSetSizes(v,numVertices,numVerticesGlobal);CHKERRQ(ierr); 15313c41b853SStefano Zampini ierr = VecSetType(v,VECSTANDARD);CHKERRQ(ierr); 15323c41b853SStefano Zampini ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 15333c41b853SStefano Zampini for (np = 0,st = 0; np < nparts; ++np) { 15343c41b853SStefano Zampini if (rank == np || (rank == size-1 && size < nparts && np >= size)) { 15353c41b853SStefano Zampini for (j = 0; j < tpwgts[np]; j++) { 15363c41b853SStefano Zampini ierr = VecSetValue(v,st+j,np,INSERT_VALUES);CHKERRQ(ierr); 15373c41b853SStefano Zampini } 15383c41b853SStefano Zampini } 15393c41b853SStefano Zampini st += tpwgts[np]; 15403c41b853SStefano Zampini } 15413c41b853SStefano Zampini ierr = VecAssemblyBegin(v);CHKERRQ(ierr); 15423c41b853SStefano Zampini ierr = VecAssemblyEnd(v);CHKERRQ(ierr); 15433c41b853SStefano Zampini ierr = VecGetArray(v,&array);CHKERRQ(ierr); 15443c41b853SStefano Zampini for (j = 0; j < numVertices; ++j) { 15453c41b853SStefano Zampini ierr = PetscSectionAddDof(partSection,PetscRealPart(array[j]),1);CHKERRQ(ierr); 15463c41b853SStefano Zampini } 15473c41b853SStefano Zampini ierr = VecRestoreArray(v,&array);CHKERRQ(ierr); 15483c41b853SStefano Zampini ierr = VecDestroy(&v);CHKERRQ(ierr); 154904ba2274SStefano Zampini } else { 1550cead94edSToby Isaac PetscMPIInt rank; 1551cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 1552cead94edSToby Isaac 1553a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1554cead94edSToby Isaac offsets[0] = 0; 1555cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1556cead94edSToby Isaac for (np = 2; np <= size; np++) { 1557cead94edSToby Isaac offsets[np] += offsets[np-1]; 1558cead94edSToby Isaac } 1559cead94edSToby Isaac nvGlobal = offsets[size]; 1560cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1561cead94edSToby Isaac myFirst = offsets[rank]; 1562cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1563cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1564cead94edSToby Isaac if (numVertices) { 1565cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1566cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1567cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1568cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1569cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1570cead94edSToby Isaac 1571cead94edSToby Isaac if (rem) { 1572cead94edSToby Isaac firstLargePart = myFirst / pBig; 1573cead94edSToby Isaac lastLargePart = myLast / pBig; 1574cead94edSToby Isaac 1575cead94edSToby Isaac if (firstLargePart < rem) { 1576cead94edSToby Isaac firstPart = firstLargePart; 157704ba2274SStefano Zampini } else { 1578cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1579cead94edSToby Isaac } 1580cead94edSToby Isaac if (lastLargePart < rem) { 1581cead94edSToby Isaac lastPart = lastLargePart; 158204ba2274SStefano Zampini } else { 1583cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1584cead94edSToby Isaac } 158504ba2274SStefano Zampini } else { 1586cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1587cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1588cead94edSToby Isaac } 1589cead94edSToby Isaac 1590cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1591cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1592cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1593cead94edSToby Isaac 1594cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1595cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1596cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1597cead94edSToby Isaac } 1598cead94edSToby Isaac } 1599cead94edSToby Isaac } 16003c41b853SStefano Zampini } 16013c41b853SStefano Zampini ierr = PetscFree(tpwgts);CHKERRQ(ierr); 1602555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1603555a9cf8SMatthew G. Knepley } 1604555a9cf8SMatthew G. Knepley 1605d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1606555a9cf8SMatthew G. Knepley { 1607555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1608074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1609555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1610555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1611555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1612555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1613555a9cf8SMatthew G. Knepley } 1614555a9cf8SMatthew G. Knepley 1615555a9cf8SMatthew G. Knepley /*MC 1616555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1617555a9cf8SMatthew G. Knepley 1618555a9cf8SMatthew G. Knepley Level: intermediate 1619555a9cf8SMatthew G. Knepley 1620555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1621555a9cf8SMatthew G. Knepley M*/ 1622555a9cf8SMatthew G. Knepley 1623555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1624555a9cf8SMatthew G. Knepley { 1625555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1626555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1627555a9cf8SMatthew G. Knepley 1628555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1629555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1630555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1631555a9cf8SMatthew G. Knepley part->data = p; 1632555a9cf8SMatthew G. Knepley 1633555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1634555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1635555a9cf8SMatthew G. Knepley } 1636555a9cf8SMatthew G. Knepley 1637d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1638dae52e14SToby Isaac { 1639dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1640dae52e14SToby Isaac PetscErrorCode ierr; 1641dae52e14SToby Isaac 1642dae52e14SToby Isaac PetscFunctionBegin; 1643dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1644dae52e14SToby Isaac PetscFunctionReturn(0); 1645dae52e14SToby Isaac } 1646dae52e14SToby Isaac 1647d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1648dae52e14SToby Isaac { 1649dae52e14SToby Isaac PetscFunctionBegin; 1650dae52e14SToby Isaac PetscFunctionReturn(0); 1651dae52e14SToby Isaac } 1652dae52e14SToby Isaac 1653d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1654dae52e14SToby Isaac { 1655dae52e14SToby Isaac PetscBool iascii; 1656dae52e14SToby Isaac PetscErrorCode ierr; 1657dae52e14SToby Isaac 1658dae52e14SToby Isaac PetscFunctionBegin; 1659dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1660dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1661dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1662dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1663dae52e14SToby Isaac PetscFunctionReturn(0); 1664dae52e14SToby Isaac } 1665dae52e14SToby Isaac 16663c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 1667dae52e14SToby Isaac { 1668dae52e14SToby Isaac PetscInt np; 1669dae52e14SToby Isaac PetscErrorCode ierr; 1670dae52e14SToby Isaac 1671dae52e14SToby Isaac PetscFunctionBegin; 1672dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1673dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1674dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1675dae52e14SToby Isaac PetscFunctionReturn(0); 1676dae52e14SToby Isaac } 1677dae52e14SToby Isaac 1678d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1679dae52e14SToby Isaac { 1680dae52e14SToby Isaac PetscFunctionBegin; 1681074d466cSStefano Zampini part->noGraph = PETSC_TRUE; 1682dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1683dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1684dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1685dae52e14SToby Isaac PetscFunctionReturn(0); 1686dae52e14SToby Isaac } 1687dae52e14SToby Isaac 1688dae52e14SToby Isaac /*MC 1689dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1690dae52e14SToby Isaac 1691dae52e14SToby Isaac Level: intermediate 1692dae52e14SToby Isaac 1693dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1694dae52e14SToby Isaac M*/ 1695dae52e14SToby Isaac 1696dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1697dae52e14SToby Isaac { 1698dae52e14SToby Isaac PetscPartitioner_Gather *p; 1699dae52e14SToby Isaac PetscErrorCode ierr; 1700dae52e14SToby Isaac 1701dae52e14SToby Isaac PetscFunctionBegin; 1702dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1703dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1704dae52e14SToby Isaac part->data = p; 1705dae52e14SToby Isaac 1706dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1707dae52e14SToby Isaac PetscFunctionReturn(0); 1708dae52e14SToby Isaac } 1709dae52e14SToby Isaac 1710dae52e14SToby Isaac 1711d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 171277623264SMatthew G. Knepley { 171377623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 171477623264SMatthew G. Knepley PetscErrorCode ierr; 171577623264SMatthew G. Knepley 171677623264SMatthew G. Knepley PetscFunctionBegin; 171777623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 171877623264SMatthew G. Knepley PetscFunctionReturn(0); 171977623264SMatthew G. Knepley } 172077623264SMatthew G. Knepley 1721d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 172277623264SMatthew G. Knepley { 172377623264SMatthew G. Knepley PetscFunctionBegin; 172477623264SMatthew G. Knepley PetscFunctionReturn(0); 172577623264SMatthew G. Knepley } 172677623264SMatthew G. Knepley 1727d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 172877623264SMatthew G. Knepley { 172977623264SMatthew G. Knepley PetscBool iascii; 173077623264SMatthew G. Knepley PetscErrorCode ierr; 173177623264SMatthew G. Knepley 173277623264SMatthew G. Knepley PetscFunctionBegin; 173377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 173477623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 173577623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 173677623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 173777623264SMatthew G. Knepley PetscFunctionReturn(0); 173877623264SMatthew G. Knepley } 173977623264SMatthew G. Knepley 174070034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 174170034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 174270034214SMatthew G. Knepley #include <unistd.h> 174370034214SMatthew G. Knepley #endif 174411d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 174511d1e910SBarry Smith #include <chaco.h> 174611d1e910SBarry Smith #else 174711d1e910SBarry Smith /* Older versions of Chaco do not have an include file */ 174870034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 174970034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 175070034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 175170034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 175270034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 175311d1e910SBarry Smith #endif 175470034214SMatthew G. Knepley extern int FREE_GRAPH; 175577623264SMatthew G. Knepley #endif 175670034214SMatthew G. Knepley 17573c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 175870034214SMatthew G. Knepley { 175977623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 176070034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 176170034214SMatthew G. Knepley MPI_Comm comm; 176270034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 176370034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 176470034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 176570034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 176670034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 176770034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 176870034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 176970034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 177070034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 177170034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 177270034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 177370034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 177470034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 177570034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 177670034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 177770034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 177870034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 177911d1e910SBarry Smith #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) 178011d1e910SBarry Smith int *assignment; /* Output partition */ 178111d1e910SBarry Smith #else 178270034214SMatthew G. Knepley short int *assignment; /* Output partition */ 178311d1e910SBarry Smith #endif 178470034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 178570034214SMatthew G. Knepley PetscInt *points; 178670034214SMatthew G. Knepley int i, v, p; 178770034214SMatthew G. Knepley PetscErrorCode ierr; 178870034214SMatthew G. Knepley 178970034214SMatthew G. Knepley PetscFunctionBegin; 17903c41b853SStefano Zampini ierr = PetscObjectGetComm((PetscObject)part,&comm);CHKERRQ(ierr); 179107ed3857SLisandro Dalcin #if defined (PETSC_USE_DEBUG) 179207ed3857SLisandro Dalcin { 179307ed3857SLisandro Dalcin int ival,isum; 179407ed3857SLisandro Dalcin PetscBool distributed; 179507ed3857SLisandro Dalcin 179607ed3857SLisandro Dalcin ival = (numVertices > 0); 179707ed3857SLisandro Dalcin ierr = MPI_Allreduce(&ival, &isum, 1, MPI_INT, MPI_SUM, comm);CHKERRQ(ierr); 179807ed3857SLisandro Dalcin distributed = (isum > 1) ? PETSC_TRUE : PETSC_FALSE; 179907ed3857SLisandro Dalcin if (distributed) SETERRQ(comm, PETSC_ERR_SUP, "Chaco cannot partition a distributed graph"); 180007ed3857SLisandro Dalcin } 180107ed3857SLisandro Dalcin #endif 18023c41b853SStefano Zampini if (!numVertices) { /* distributed case, return if not holding the graph */ 180370034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 180470034214SMatthew G. Knepley PetscFunctionReturn(0); 180570034214SMatthew G. Knepley } 180670034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 180770034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 180870034214SMatthew G. Knepley 180970034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 181070034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 18113c41b853SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 181270034214SMatthew G. Knepley } 181377623264SMatthew G. Knepley mesh_dims[0] = nparts; 181470034214SMatthew G. Knepley mesh_dims[1] = 1; 181570034214SMatthew G. Knepley mesh_dims[2] = 1; 181670034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 181770034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 181870034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 181970034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 182070034214SMatthew G. Knepley { 182170034214SMatthew G. Knepley int piperet; 182270034214SMatthew G. Knepley piperet = pipe(fd_pipe); 18233c41b853SStefano Zampini if (piperet) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Could not create pipe"); 182470034214SMatthew G. Knepley fd_stdout = dup(1); 182570034214SMatthew G. Knepley close(1); 182670034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 182770034214SMatthew G. Knepley } 182870034214SMatthew G. Knepley #endif 18293c41b853SStefano Zampini if (part->usevwgt) { ierr = PetscInfo(part,"PETSCPARTITIONERCHACO ignores vertex weights\n");CHKERRQ(ierr); } 183070034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 183170034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 183270034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 183370034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 183470034214SMatthew G. Knepley { 183570034214SMatthew G. Knepley char msgLog[10000]; 183670034214SMatthew G. Knepley int count; 183770034214SMatthew G. Knepley 183870034214SMatthew G. Knepley fflush(stdout); 183970034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 184070034214SMatthew G. Knepley if (count < 0) count = 0; 184170034214SMatthew G. Knepley msgLog[count] = 0; 184270034214SMatthew G. Knepley close(1); 184370034214SMatthew G. Knepley dup2(fd_stdout, 1); 184470034214SMatthew G. Knepley close(fd_stdout); 184570034214SMatthew G. Knepley close(fd_pipe[0]); 184670034214SMatthew G. Knepley close(fd_pipe[1]); 18473c41b853SStefano Zampini if (ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 184870034214SMatthew G. Knepley } 184907ed3857SLisandro Dalcin #else 18503c41b853SStefano Zampini if (ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in Chaco library: %s", "error in stdout"); 185170034214SMatthew G. Knepley #endif 185270034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 185370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 185477623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 185570034214SMatthew G. Knepley } 185670034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 185777623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 185870034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 185970034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 186070034214SMatthew G. Knepley } 186170034214SMatthew G. Knepley } 18623c41b853SStefano Zampini if (i != nvtxs) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 186370034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 186470034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 186570034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 186670034214SMatthew G. Knepley } 186770034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 186870034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 186970034214SMatthew G. Knepley PetscFunctionReturn(0); 187077623264SMatthew G. Knepley #else 187177623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 187270034214SMatthew G. Knepley #endif 187377623264SMatthew G. Knepley } 187477623264SMatthew G. Knepley 1875d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 187677623264SMatthew G. Knepley { 187777623264SMatthew G. Knepley PetscFunctionBegin; 1878074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 187977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 188077623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 188177623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 188277623264SMatthew G. Knepley PetscFunctionReturn(0); 188377623264SMatthew G. Knepley } 188477623264SMatthew G. Knepley 188577623264SMatthew G. Knepley /*MC 188677623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 188777623264SMatthew G. Knepley 188877623264SMatthew G. Knepley Level: intermediate 188977623264SMatthew G. Knepley 189077623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 189177623264SMatthew G. Knepley M*/ 189277623264SMatthew G. Knepley 189377623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 189477623264SMatthew G. Knepley { 189577623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 189677623264SMatthew G. Knepley PetscErrorCode ierr; 189777623264SMatthew G. Knepley 189877623264SMatthew G. Knepley PetscFunctionBegin; 189977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 190077623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 190177623264SMatthew G. Knepley part->data = p; 190277623264SMatthew G. Knepley 190377623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 190477623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 190577623264SMatthew G. Knepley PetscFunctionReturn(0); 190677623264SMatthew G. Knepley } 190777623264SMatthew G. Knepley 19085b440754SMatthew G. Knepley static const char *ptypes[] = {"kway", "rb"}; 19095b440754SMatthew G. Knepley 1910d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 191177623264SMatthew G. Knepley { 191277623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 191377623264SMatthew G. Knepley PetscErrorCode ierr; 191477623264SMatthew G. Knepley 191577623264SMatthew G. Knepley PetscFunctionBegin; 19163c41b853SStefano Zampini ierr = MPI_Comm_free(&p->pcomm);CHKERRQ(ierr); 191777623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 191877623264SMatthew G. Knepley PetscFunctionReturn(0); 191977623264SMatthew G. Knepley } 192077623264SMatthew G. Knepley 1921d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 192277623264SMatthew G. Knepley { 19232abdaa70SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 192477623264SMatthew G. Knepley PetscErrorCode ierr; 192577623264SMatthew G. Knepley 192677623264SMatthew G. Knepley PetscFunctionBegin; 19272abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 19282abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 19292abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 19302abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 19319d459c0eSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer, "random seed %D\n", p->randomSeed);CHKERRQ(ierr); 19322abdaa70SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 193377623264SMatthew G. Knepley PetscFunctionReturn(0); 193477623264SMatthew G. Knepley } 193577623264SMatthew G. Knepley 1936d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 193777623264SMatthew G. Knepley { 193877623264SMatthew G. Knepley PetscBool iascii; 193977623264SMatthew G. Knepley PetscErrorCode ierr; 194077623264SMatthew G. Knepley 194177623264SMatthew G. Knepley PetscFunctionBegin; 194277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 194377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 194477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 194577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 194677623264SMatthew G. Knepley PetscFunctionReturn(0); 194777623264SMatthew G. Knepley } 194870034214SMatthew G. Knepley 194944d8be81SLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 195044d8be81SLisandro Dalcin { 195144d8be81SLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 195244d8be81SLisandro Dalcin PetscErrorCode ierr; 195344d8be81SLisandro Dalcin 195444d8be81SLisandro Dalcin PetscFunctionBegin; 195544d8be81SLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 195644d8be81SLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 19575b440754SMatthew G. Knepley ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 19585b440754SMatthew G. Knepley ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 19599d459c0eSStefano Zampini ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p->randomSeed, &p->randomSeed, NULL);CHKERRQ(ierr); 196044d8be81SLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 196144d8be81SLisandro Dalcin PetscFunctionReturn(0); 196244d8be81SLisandro Dalcin } 196344d8be81SLisandro Dalcin 196470034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 196570034214SMatthew G. Knepley #include <parmetis.h> 196677623264SMatthew G. Knepley #endif 196770034214SMatthew G. Knepley 19683c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 196970034214SMatthew G. Knepley { 197077623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 19715b440754SMatthew G. Knepley PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 197270034214SMatthew G. Knepley MPI_Comm comm; 197370034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 197470034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 197570034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 197670034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 197770034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 197870034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 197970034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 198070034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 198170034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 19825b440754SMatthew G. Knepley PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 1983fb83b9f2SMichael Gegg real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 1984fb83b9f2SMichael Gegg real_t *ubvec; /* The balance intolerance for vertex weights */ 1985b3ce585bSLisandro Dalcin PetscInt options[64]; /* Options */ 1986b3ce585bSLisandro Dalcin PetscInt v, i, *assignment, *points; 19873c41b853SStefano Zampini PetscMPIInt p, size, rank; 19883c41b853SStefano Zampini PetscBool hasempty = PETSC_FALSE; 198970034214SMatthew G. Knepley PetscErrorCode ierr; 199070034214SMatthew G. Knepley 199170034214SMatthew G. Knepley PetscFunctionBegin; 199277623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 1993b3ce585bSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 199470034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 199570034214SMatthew G. Knepley /* Calculate vertex distribution */ 19963c41b853SStefano Zampini ierr = PetscMalloc4(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 199770034214SMatthew G. Knepley vtxdist[0] = 0; 199870034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 1999b3ce585bSLisandro Dalcin for (p = 2; p <= size; ++p) { 20003c41b853SStefano Zampini hasempty = (PetscBool)(hasempty || !vtxdist[p-1] || !vtxdist[p]); 200170034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 200270034214SMatthew G. Knepley } 20033c41b853SStefano Zampini /* null graph */ 20043c41b853SStefano Zampini if (vtxdist[size] == 0) { 20053c41b853SStefano Zampini ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 20063c41b853SStefano Zampini ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 20073c41b853SStefano Zampini PetscFunctionReturn(0); 20083c41b853SStefano Zampini } 200944d8be81SLisandro Dalcin /* Calculate partition weights */ 20103c41b853SStefano Zampini if (targetSection) { 20113c41b853SStefano Zampini PetscInt p; 20123c41b853SStefano Zampini real_t sumt = 0.0; 20133c41b853SStefano Zampini 201470034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 20153c41b853SStefano Zampini PetscInt tpd; 20163c41b853SStefano Zampini 20173c41b853SStefano Zampini ierr = PetscSectionGetDof(targetSection,p,&tpd);CHKERRQ(ierr); 20183c41b853SStefano Zampini sumt += tpd; 20193c41b853SStefano Zampini tpwgts[p] = tpd; 20203c41b853SStefano Zampini } 20213c41b853SStefano Zampini if (sumt) { /* METIS/ParMETIS do not like exactly zero weight */ 20223c41b853SStefano Zampini for (p = 0, sumt = 0.0; p < nparts; ++p) { 20233c41b853SStefano Zampini tpwgts[p] = PetscMax(tpwgts[p],PETSC_SMALL); 20243c41b853SStefano Zampini sumt += tpwgts[p]; 20253c41b853SStefano Zampini } 20263c41b853SStefano Zampini for (p = 0; p < nparts; ++p) tpwgts[p] /= sumt; 20273c41b853SStefano Zampini for (p = 0, sumt = 0.0; p < nparts-1; ++p) sumt += tpwgts[p]; 20283c41b853SStefano Zampini tpwgts[nparts - 1] = 1. - sumt; 20293c41b853SStefano Zampini } 20303c41b853SStefano Zampini } else { 20313c41b853SStefano Zampini for (p = 0; p < nparts; ++p) tpwgts[p] = 1.0/nparts; 203270034214SMatthew G. Knepley } 20335b440754SMatthew G. Knepley ubvec[0] = pm->imbalanceRatio; 203470034214SMatthew G. Knepley 20353c41b853SStefano Zampini /* Weight cells */ 20363c41b853SStefano Zampini if (vertSection) { 20373c41b853SStefano Zampini ierr = PetscMalloc1(nvtxs,&vwgt);CHKERRQ(ierr); 20383c41b853SStefano Zampini for (v = 0; v < nvtxs; ++v) { 20393c41b853SStefano Zampini ierr = PetscSectionGetDof(vertSection, v, &vwgt[v]);CHKERRQ(ierr); 2040cd0de0f2SShri } 204144d8be81SLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 20423c41b853SStefano Zampini } 2043cd0de0f2SShri 2044b3ce585bSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 2045b3ce585bSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 2046b3ce585bSLisandro Dalcin if (rank == p) { 204744d8be81SLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 204842678178SLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 20499d459c0eSStefano Zampini options[METIS_OPTION_SEED] = pm->randomSeed; 205044d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 205144d8be81SLisandro Dalcin if (metis_ptype == 1) { 205244d8be81SLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 205372379da4SMatthew G. Knepley ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 205444d8be81SLisandro Dalcin PetscStackPop; 205544d8be81SLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 205644d8be81SLisandro Dalcin } else { 205744d8be81SLisandro Dalcin /* 205844d8be81SLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 205944d8be81SLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 206044d8be81SLisandro 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. 206144d8be81SLisandro Dalcin */ 206244d8be81SLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 206344d8be81SLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 206470034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 206572379da4SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 206670034214SMatthew G. Knepley PetscStackPop; 206770034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 206870034214SMatthew G. Knepley } 206944d8be81SLisandro Dalcin } 207070034214SMatthew G. Knepley } else { 20713c41b853SStefano Zampini MPI_Comm pcomm; 20723c41b853SStefano Zampini 207342678178SLisandro Dalcin options[0] = 1; /*use options */ 20745b440754SMatthew G. Knepley options[1] = pm->debugFlag; 20759d459c0eSStefano Zampini options[2] = (pm->randomSeed == -1) ? 15 : pm->randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 20763c41b853SStefano Zampini 20773c41b853SStefano Zampini if (hasempty) { /* parmetis does not support empty graphs on some of the processes */ 20783c41b853SStefano Zampini PetscInt cnt; 20793c41b853SStefano Zampini 20803c41b853SStefano Zampini ierr = MPI_Comm_split(pm->pcomm,!!nvtxs,rank,&pcomm);CHKERRQ(ierr); 20813c41b853SStefano Zampini for (p=0,cnt=0;p<size;p++) { 20823c41b853SStefano Zampini if (vtxdist[p+1] != vtxdist[p]) { 20833c41b853SStefano Zampini vtxdist[cnt+1] = vtxdist[p+1]; 20843c41b853SStefano Zampini cnt++; 20853c41b853SStefano Zampini } 20863c41b853SStefano Zampini } 20873c41b853SStefano Zampini } else pcomm = pm->pcomm; 20883c41b853SStefano Zampini if (nvtxs) { 208970034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 20903c41b853SStefano Zampini ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &pcomm); 209170034214SMatthew G. Knepley PetscStackPop; 2092c717d290SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 209370034214SMatthew G. Knepley } 20943c41b853SStefano Zampini if (hasempty) { 20953c41b853SStefano Zampini ierr = MPI_Comm_free(&pcomm);CHKERRQ(ierr); 209670034214SMatthew G. Knepley } 20973c41b853SStefano Zampini } 20983c41b853SStefano Zampini 209970034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 210077623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 210170034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 210277623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 210370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 210470034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 210570034214SMatthew G. Knepley } 210670034214SMatthew G. Knepley } 210770034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 210870034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 21093c41b853SStefano Zampini ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 21103c41b853SStefano Zampini ierr = PetscFree(vwgt);CHKERRQ(ierr); 21119b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 211270034214SMatthew G. Knepley #else 211377623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 211470034214SMatthew G. Knepley #endif 211570034214SMatthew G. Knepley } 211670034214SMatthew G. Knepley 2117d5577e40SMatthew G. Knepley static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 211877623264SMatthew G. Knepley { 211977623264SMatthew G. Knepley PetscFunctionBegin; 2120074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 212177623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 212244d8be81SLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 212377623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 212477623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 212577623264SMatthew G. Knepley PetscFunctionReturn(0); 212677623264SMatthew G. Knepley } 212777623264SMatthew G. Knepley 212877623264SMatthew G. Knepley /*MC 21293c41b853SStefano Zampini PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMETIS library 213077623264SMatthew G. Knepley 213177623264SMatthew G. Knepley Level: intermediate 213277623264SMatthew G. Knepley 21333c41b853SStefano Zampini Options Database Keys: 21343c41b853SStefano Zampini + -petscpartitioner_parmetis_type <string> - ParMETIS partitioning type. Either "kway" or "rb" (recursive bisection) 21353c41b853SStefano Zampini . -petscpartitioner_parmetis_imbalance_ratio <value> - Load imbalance ratio limit 21363c41b853SStefano Zampini . -petscpartitioner_parmetis_debug <int> - Debugging flag passed to ParMETIS/METIS routines 21373c41b853SStefano Zampini - -petscpartitioner_parmetis_seed <int> - Random seed 21383c41b853SStefano Zampini 21393c41b853SStefano Zampini Notes: when the graph is on a single process, this partitioner actually calls METIS and not ParMETIS 21403c41b853SStefano Zampini 214177623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 214277623264SMatthew G. Knepley M*/ 214377623264SMatthew G. Knepley 214477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 214577623264SMatthew G. Knepley { 214677623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 214777623264SMatthew G. Knepley PetscErrorCode ierr; 214877623264SMatthew G. Knepley 214977623264SMatthew G. Knepley PetscFunctionBegin; 215077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 215177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 215277623264SMatthew G. Knepley part->data = p; 215377623264SMatthew G. Knepley 21543c41b853SStefano Zampini ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)part),&p->pcomm);CHKERRQ(ierr); 21555b440754SMatthew G. Knepley p->ptype = 0; 21565b440754SMatthew G. Knepley p->imbalanceRatio = 1.05; 21575b440754SMatthew G. Knepley p->debugFlag = 0; 21589d459c0eSStefano Zampini p->randomSeed = -1; /* defaults to GLOBAL_SEED=15 from `libparmetis/defs.h` */ 21595b440754SMatthew G. Knepley 216077623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 216177623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 216270034214SMatthew G. Knepley PetscFunctionReturn(0); 216370034214SMatthew G. Knepley } 216470034214SMatthew G. Knepley 2165137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 2166137cd93aSLisandro Dalcin 2167137cd93aSLisandro Dalcin EXTERN_C_BEGIN 2168137cd93aSLisandro Dalcin #include <ptscotch.h> 2169137cd93aSLisandro Dalcin EXTERN_C_END 2170137cd93aSLisandro Dalcin 2171137cd93aSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 2172137cd93aSLisandro Dalcin 2173137cd93aSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 2174137cd93aSLisandro Dalcin { 2175137cd93aSLisandro Dalcin switch (strategy) { 2176137cd93aSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 2177137cd93aSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 2178137cd93aSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 2179137cd93aSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 2180137cd93aSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 2181137cd93aSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 2182137cd93aSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 2183137cd93aSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 2184137cd93aSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 2185137cd93aSLisandro Dalcin } 2186137cd93aSLisandro Dalcin } 2187137cd93aSLisandro Dalcin 2188137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 21893c41b853SStefano Zampini SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num tpart[], SCOTCH_Num part[]) 2190137cd93aSLisandro Dalcin { 2191137cd93aSLisandro Dalcin SCOTCH_Graph grafdat; 2192137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 2193137cd93aSLisandro Dalcin SCOTCH_Num vertnbr = n; 2194137cd93aSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 2195137cd93aSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 2196137cd93aSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 2197137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 2198137cd93aSLisandro Dalcin double kbalval = imbalance; 2199137cd93aSLisandro Dalcin PetscErrorCode ierr; 2200137cd93aSLisandro Dalcin 2201137cd93aSLisandro Dalcin PetscFunctionBegin; 2202d99a0000SVaclav Hapla { 2203d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 22043c41b853SStefano Zampini ierr = PetscOptionsDeprecatedNoObject("-petscpartititoner_ptscotch_vertex_weight",NULL,"3.13","Use -petscpartitioner_use_vertex_weights");CHKERRQ(ierr); 2205d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 2206d99a0000SVaclav Hapla if (!flg) velotab = NULL; 2207d99a0000SVaclav Hapla } 2208137cd93aSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 2209137cd93aSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 2210137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 2211137cd93aSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 22123c41b853SStefano Zampini if (tpart) { 22133c41b853SStefano Zampini SCOTCH_Arch archdat; 22143c41b853SStefano Zampini ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 22153c41b853SStefano Zampini ierr = SCOTCH_archCmpltw(&archdat, nparts, tpart);CHKERRPTSCOTCH(ierr); 22163c41b853SStefano Zampini ierr = SCOTCH_graphMap(&grafdat, &archdat, &stradat, part);CHKERRPTSCOTCH(ierr); 22173c41b853SStefano Zampini SCOTCH_archExit(&archdat); 22183c41b853SStefano Zampini } else { 2219137cd93aSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 22203c41b853SStefano Zampini } 2221137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 2222137cd93aSLisandro Dalcin SCOTCH_graphExit(&grafdat); 2223137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2224137cd93aSLisandro Dalcin } 2225137cd93aSLisandro Dalcin 2226137cd93aSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 22273c41b853SStefano Zampini SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num tpart[], SCOTCH_Num part[], MPI_Comm comm) 2228137cd93aSLisandro Dalcin { 2229137cd93aSLisandro Dalcin PetscMPIInt procglbnbr; 2230137cd93aSLisandro Dalcin PetscMPIInt proclocnum; 2231137cd93aSLisandro Dalcin SCOTCH_Arch archdat; 2232137cd93aSLisandro Dalcin SCOTCH_Dgraph grafdat; 2233137cd93aSLisandro Dalcin SCOTCH_Dmapping mappdat; 2234137cd93aSLisandro Dalcin SCOTCH_Strat stradat; 2235137cd93aSLisandro Dalcin SCOTCH_Num vertlocnbr; 2236137cd93aSLisandro Dalcin SCOTCH_Num edgelocnbr; 2237137cd93aSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 2238137cd93aSLisandro Dalcin SCOTCH_Num* edloloctab = adjwgt; 2239137cd93aSLisandro Dalcin SCOTCH_Num flagval = strategy; 2240137cd93aSLisandro Dalcin double kbalval = imbalance; 2241137cd93aSLisandro Dalcin PetscErrorCode ierr; 2242137cd93aSLisandro Dalcin 2243137cd93aSLisandro Dalcin PetscFunctionBegin; 2244d99a0000SVaclav Hapla { 2245d99a0000SVaclav Hapla PetscBool flg = PETSC_TRUE; 22463c41b853SStefano Zampini ierr = PetscOptionsDeprecatedNoObject("-petscpartititoner_ptscotch_vertex_weight",NULL,"3.13","Use -petscpartitioner_use_vertex_weights");CHKERRQ(ierr); 2247d99a0000SVaclav Hapla ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 2248d99a0000SVaclav Hapla if (!flg) veloloctab = NULL; 2249d99a0000SVaclav Hapla } 2250137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 2251137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 2252137cd93aSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 2253137cd93aSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 2254137cd93aSLisandro Dalcin 2255137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 2256137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 2257137cd93aSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 2258137cd93aSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 2259137cd93aSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 22603c41b853SStefano Zampini if (tpart) { /* target partition weights */ 22613c41b853SStefano Zampini ierr = SCOTCH_archCmpltw(&archdat, nparts, tpart);CHKERRPTSCOTCH(ierr); 22623c41b853SStefano Zampini } else { 2263137cd93aSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 22643c41b853SStefano Zampini } 2265137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 2266cb87ef4cSFlorian Wechsung 2267137cd93aSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 2268137cd93aSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 2269137cd93aSLisandro Dalcin SCOTCH_archExit(&archdat); 2270137cd93aSLisandro Dalcin SCOTCH_stratExit(&stradat); 2271137cd93aSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 2272137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2273137cd93aSLisandro Dalcin } 2274137cd93aSLisandro Dalcin 2275137cd93aSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 2276137cd93aSLisandro Dalcin 2277137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 2278137cd93aSLisandro Dalcin { 2279137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2280137cd93aSLisandro Dalcin PetscErrorCode ierr; 2281137cd93aSLisandro Dalcin 2282137cd93aSLisandro Dalcin PetscFunctionBegin; 22833c41b853SStefano Zampini ierr = MPI_Comm_free(&p->pcomm);CHKERRQ(ierr); 2284137cd93aSLisandro Dalcin ierr = PetscFree(p);CHKERRQ(ierr); 2285137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2286137cd93aSLisandro Dalcin } 2287137cd93aSLisandro Dalcin 2288137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_Ascii(PetscPartitioner part, PetscViewer viewer) 2289137cd93aSLisandro Dalcin { 2290137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2291137cd93aSLisandro Dalcin PetscErrorCode ierr; 2292137cd93aSLisandro Dalcin 2293137cd93aSLisandro Dalcin PetscFunctionBegin; 2294137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2295137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer,"using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 2296137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer,"using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 2297137cd93aSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2298137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2299137cd93aSLisandro Dalcin } 2300137cd93aSLisandro Dalcin 2301137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 2302137cd93aSLisandro Dalcin { 2303137cd93aSLisandro Dalcin PetscBool iascii; 2304137cd93aSLisandro Dalcin PetscErrorCode ierr; 2305137cd93aSLisandro Dalcin 2306137cd93aSLisandro Dalcin PetscFunctionBegin; 2307137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2308137cd93aSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2309137cd93aSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 2310137cd93aSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_Ascii(part, viewer);CHKERRQ(ierr);} 2311137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2312137cd93aSLisandro Dalcin } 2313137cd93aSLisandro Dalcin 2314137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 2315137cd93aSLisandro Dalcin { 2316137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 2317137cd93aSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 2318137cd93aSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 2319137cd93aSLisandro Dalcin PetscBool flag; 2320137cd93aSLisandro Dalcin PetscErrorCode ierr; 2321137cd93aSLisandro Dalcin 2322137cd93aSLisandro Dalcin PetscFunctionBegin; 2323137cd93aSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 2324137cd93aSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 2325137cd93aSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 2326137cd93aSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 2327137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2328137cd93aSLisandro Dalcin } 2329137cd93aSLisandro Dalcin 23303c41b853SStefano Zampini static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 2331137cd93aSLisandro Dalcin { 2332137cd93aSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 23333c41b853SStefano Zampini MPI_Comm comm; 2334137cd93aSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 2335137cd93aSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 2336137cd93aSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 2337137cd93aSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 2338137cd93aSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 2339137cd93aSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 2340137cd93aSLisandro Dalcin PetscInt v, i, *assignment, *points; 2341137cd93aSLisandro Dalcin PetscMPIInt size, rank, p; 23423c41b853SStefano Zampini PetscBool hasempty = PETSC_FALSE; 23433c41b853SStefano Zampini PetscInt *tpwgts = NULL; 2344137cd93aSLisandro Dalcin PetscErrorCode ierr; 2345137cd93aSLisandro Dalcin 2346137cd93aSLisandro Dalcin PetscFunctionBegin; 23473c41b853SStefano Zampini ierr = PetscObjectGetComm((PetscObject)part,&comm);CHKERRQ(ierr); 2348137cd93aSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2349137cd93aSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 235099b53901SStefano Zampini ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 2351137cd93aSLisandro Dalcin /* Calculate vertex distribution */ 2352137cd93aSLisandro Dalcin vtxdist[0] = 0; 2353137cd93aSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 2354137cd93aSLisandro Dalcin for (p = 2; p <= size; ++p) { 23553c41b853SStefano Zampini hasempty = (PetscBool)(hasempty || !vtxdist[p-1] || !vtxdist[p]); 2356137cd93aSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 2357137cd93aSLisandro Dalcin } 23583c41b853SStefano Zampini /* null graph */ 23593c41b853SStefano Zampini if (vtxdist[size] == 0) { 23603c41b853SStefano Zampini ierr = PetscFree2(vtxdist, assignment);CHKERRQ(ierr); 23613c41b853SStefano Zampini ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 23623c41b853SStefano Zampini PetscFunctionReturn(0); 23633c41b853SStefano Zampini } 2364137cd93aSLisandro Dalcin 23653c41b853SStefano Zampini /* Calculate vertex weights */ 23663c41b853SStefano Zampini if (vertSection) { 23673c41b853SStefano Zampini ierr = PetscMalloc1(nvtxs,&vwgt);CHKERRQ(ierr); 23683c41b853SStefano Zampini for (v = 0; v < nvtxs; ++v) { 23693c41b853SStefano Zampini ierr = PetscSectionGetDof(vertSection, v, &vwgt[v]);CHKERRQ(ierr); 2370137cd93aSLisandro Dalcin } 2371137cd93aSLisandro Dalcin } 23723c41b853SStefano Zampini 23733c41b853SStefano Zampini /* Calculate partition weights */ 23743c41b853SStefano Zampini if (targetSection) { 23753c41b853SStefano Zampini PetscInt sumw; 23763c41b853SStefano Zampini 23773c41b853SStefano Zampini ierr = PetscCalloc1(nparts,&tpwgts);CHKERRQ(ierr); 23783c41b853SStefano Zampini for (p = 0, sumw = 0; p < nparts; ++p) { 23793c41b853SStefano Zampini ierr = PetscSectionGetDof(targetSection,p,&tpwgts[p]);CHKERRQ(ierr); 23803c41b853SStefano Zampini sumw += tpwgts[p]; 23813c41b853SStefano Zampini } 23823c41b853SStefano Zampini if (!sumw) { 23833c41b853SStefano Zampini ierr = PetscFree(tpwgts);CHKERRQ(ierr); 23843c41b853SStefano Zampini } 23853c41b853SStefano Zampini } 23863c41b853SStefano Zampini 2387137cd93aSLisandro Dalcin { 2388137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 2389137cd93aSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 2390137cd93aSLisandro Dalcin double imbal = (double)pts->imbalance; 2391137cd93aSLisandro Dalcin 2392137cd93aSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 2393137cd93aSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 2394137cd93aSLisandro Dalcin if (rank == p) { 23953c41b853SStefano Zampini ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, tpwgts, assignment);CHKERRQ(ierr); 2396137cd93aSLisandro Dalcin } 2397137cd93aSLisandro Dalcin } else { 23983c41b853SStefano Zampini PetscInt cnt; 23993c41b853SStefano Zampini MPI_Comm pcomm; 24003c41b853SStefano Zampini 24013c41b853SStefano Zampini if (hasempty) { 24023c41b853SStefano Zampini ierr = MPI_Comm_split(pts->pcomm,!!nvtxs,rank,&pcomm);CHKERRQ(ierr); 24033c41b853SStefano Zampini for (p=0,cnt=0;p<size;p++) { 24043c41b853SStefano Zampini if (vtxdist[p+1] != vtxdist[p]) { 24053c41b853SStefano Zampini vtxdist[cnt+1] = vtxdist[p+1]; 24063c41b853SStefano Zampini cnt++; 24073c41b853SStefano Zampini } 24083c41b853SStefano Zampini } 24093c41b853SStefano Zampini } else pcomm = pts->pcomm; 24103c41b853SStefano Zampini if (nvtxs) { 24113c41b853SStefano Zampini ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, tpwgts, assignment, pcomm);CHKERRQ(ierr); 24123c41b853SStefano Zampini } 24133c41b853SStefano Zampini if (hasempty) { 24143c41b853SStefano Zampini ierr = MPI_Comm_free(&pcomm);CHKERRQ(ierr); 24153c41b853SStefano Zampini } 2416137cd93aSLisandro Dalcin } 2417137cd93aSLisandro Dalcin } 2418137cd93aSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 24193c41b853SStefano Zampini ierr = PetscFree(tpwgts);CHKERRQ(ierr); 2420137cd93aSLisandro Dalcin 2421137cd93aSLisandro Dalcin /* Convert to PetscSection+IS */ 2422137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 2423137cd93aSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 2424137cd93aSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 2425137cd93aSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 2426137cd93aSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 2427137cd93aSLisandro Dalcin } 2428137cd93aSLisandro Dalcin } 2429137cd93aSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2430137cd93aSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2431137cd93aSLisandro Dalcin 2432137cd93aSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 2433137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2434137cd93aSLisandro Dalcin #else 2435137cd93aSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 2436137cd93aSLisandro Dalcin #endif 2437137cd93aSLisandro Dalcin } 2438137cd93aSLisandro Dalcin 2439137cd93aSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 2440137cd93aSLisandro Dalcin { 2441137cd93aSLisandro Dalcin PetscFunctionBegin; 2442074d466cSStefano Zampini part->noGraph = PETSC_FALSE; 2443137cd93aSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 2444137cd93aSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 2445137cd93aSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 2446137cd93aSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 2447137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2448137cd93aSLisandro Dalcin } 2449137cd93aSLisandro Dalcin 2450137cd93aSLisandro Dalcin /*MC 2451137cd93aSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 2452137cd93aSLisandro Dalcin 2453137cd93aSLisandro Dalcin Level: intermediate 2454137cd93aSLisandro Dalcin 24553c41b853SStefano Zampini Options Database Keys: 24563c41b853SStefano Zampini + -petscpartitioner_ptscotch_strategy <string> - PT-Scotch strategy. Choose one of default quality speed balance safety scalability recursive remap 24573c41b853SStefano Zampini - -petscpartitioner_ptscotch_imbalance <val> - Load imbalance ratio 24583c41b853SStefano Zampini 24593c41b853SStefano Zampini Notes: when the graph is on a single process, this partitioner actually uses Scotch and not PT-Scotch 24603c41b853SStefano Zampini 2461137cd93aSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 2462137cd93aSLisandro Dalcin M*/ 2463137cd93aSLisandro Dalcin 2464137cd93aSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 2465137cd93aSLisandro Dalcin { 2466137cd93aSLisandro Dalcin PetscPartitioner_PTScotch *p; 2467137cd93aSLisandro Dalcin PetscErrorCode ierr; 2468137cd93aSLisandro Dalcin 2469137cd93aSLisandro Dalcin PetscFunctionBegin; 2470137cd93aSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 2471137cd93aSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 2472137cd93aSLisandro Dalcin part->data = p; 2473137cd93aSLisandro Dalcin 24743c41b853SStefano Zampini ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)part),&p->pcomm);CHKERRQ(ierr); 2475137cd93aSLisandro Dalcin p->strategy = 0; 2476137cd93aSLisandro Dalcin p->imbalance = 0.01; 2477137cd93aSLisandro Dalcin 2478137cd93aSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 2479137cd93aSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionercite);CHKERRQ(ierr); 2480137cd93aSLisandro Dalcin PetscFunctionReturn(0); 2481137cd93aSLisandro Dalcin } 2482137cd93aSLisandro Dalcin 24835680f57bSMatthew G. Knepley /*@ 24845680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 24855680f57bSMatthew G. Knepley 24865680f57bSMatthew G. Knepley Not collective 24875680f57bSMatthew G. Knepley 24885680f57bSMatthew G. Knepley Input Parameter: 24895680f57bSMatthew G. Knepley . dm - The DM 24905680f57bSMatthew G. Knepley 24915680f57bSMatthew G. Knepley Output Parameter: 24925680f57bSMatthew G. Knepley . part - The PetscPartitioner 24935680f57bSMatthew G. Knepley 24945680f57bSMatthew G. Knepley Level: developer 24955680f57bSMatthew G. Knepley 249698599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 249798599a47SLawrence Mitchell 24983c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate() 24995680f57bSMatthew G. Knepley @*/ 25005680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 25015680f57bSMatthew G. Knepley { 25025680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 25035680f57bSMatthew G. Knepley 25045680f57bSMatthew G. Knepley PetscFunctionBegin; 25055680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25065680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 25075680f57bSMatthew G. Knepley *part = mesh->partitioner; 25085680f57bSMatthew G. Knepley PetscFunctionReturn(0); 25095680f57bSMatthew G. Knepley } 25105680f57bSMatthew G. Knepley 251171bb2955SLawrence Mitchell /*@ 251271bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 251371bb2955SLawrence Mitchell 2514fe2efc57SMark logically collective on DM 251571bb2955SLawrence Mitchell 251671bb2955SLawrence Mitchell Input Parameters: 251771bb2955SLawrence Mitchell + dm - The DM 251871bb2955SLawrence Mitchell - part - The partitioner 251971bb2955SLawrence Mitchell 252071bb2955SLawrence Mitchell Level: developer 252171bb2955SLawrence Mitchell 252271bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 252371bb2955SLawrence Mitchell 252471bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 252571bb2955SLawrence Mitchell @*/ 252671bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 252771bb2955SLawrence Mitchell { 252871bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 252971bb2955SLawrence Mitchell PetscErrorCode ierr; 253071bb2955SLawrence Mitchell 253171bb2955SLawrence Mitchell PetscFunctionBegin; 253271bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 253371bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 253471bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 253571bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 253671bb2955SLawrence Mitchell mesh->partitioner = part; 253771bb2955SLawrence Mitchell PetscFunctionReturn(0); 253871bb2955SLawrence Mitchell } 253971bb2955SLawrence Mitchell 25408e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point) 25418e330a33SStefano Zampini { 25428e330a33SStefano Zampini const PetscInt *cone; 25438e330a33SStefano Zampini PetscInt coneSize, c; 25448e330a33SStefano Zampini PetscBool missing; 25458e330a33SStefano Zampini PetscErrorCode ierr; 25468e330a33SStefano Zampini 25478e330a33SStefano Zampini PetscFunctionBeginHot; 25488e330a33SStefano Zampini ierr = PetscHSetIQueryAdd(ht, point, &missing);CHKERRQ(ierr); 25498e330a33SStefano Zampini if (missing) { 25508e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 25518e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 25528e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 25538e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, cone[c]);CHKERRQ(ierr); 25548e330a33SStefano Zampini } 25558e330a33SStefano Zampini } 25568e330a33SStefano Zampini PetscFunctionReturn(0); 25578e330a33SStefano Zampini } 25588e330a33SStefano Zampini 25598e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down) 2560270bba0cSToby Isaac { 2561270bba0cSToby Isaac PetscErrorCode ierr; 2562270bba0cSToby Isaac 2563270bba0cSToby Isaac PetscFunctionBegin; 25646a5a2ffdSToby Isaac if (up) { 25656a5a2ffdSToby Isaac PetscInt parent; 25666a5a2ffdSToby Isaac 2567270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 25686a5a2ffdSToby Isaac if (parent != point) { 25696a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 25706a5a2ffdSToby Isaac 2571270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2572270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 2573270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 2574270bba0cSToby Isaac 2575e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 25761b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 2577270bba0cSToby Isaac } 2578270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 25796a5a2ffdSToby Isaac } 25806a5a2ffdSToby Isaac } 25816a5a2ffdSToby Isaac if (down) { 25826a5a2ffdSToby Isaac PetscInt numChildren; 25836a5a2ffdSToby Isaac const PetscInt *children; 25846a5a2ffdSToby Isaac 25856a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 25866a5a2ffdSToby Isaac if (numChildren) { 25876a5a2ffdSToby Isaac PetscInt i; 25886a5a2ffdSToby Isaac 25896a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 25906a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 25916a5a2ffdSToby Isaac 2592e8f14785SLisandro Dalcin ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr); 25931b807c88SLisandro Dalcin ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 25946a5a2ffdSToby Isaac } 25956a5a2ffdSToby Isaac } 25966a5a2ffdSToby Isaac } 2597270bba0cSToby Isaac PetscFunctionReturn(0); 2598270bba0cSToby Isaac } 2599270bba0cSToby Isaac 26008e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point) 26018e330a33SStefano Zampini { 26028e330a33SStefano Zampini PetscInt parent; 26038e330a33SStefano Zampini PetscErrorCode ierr; 2604825f8a23SLisandro Dalcin 26058e330a33SStefano Zampini PetscFunctionBeginHot; 26068e330a33SStefano Zampini ierr = DMPlexGetTreeParent(dm, point, &parent,NULL);CHKERRQ(ierr); 26078e330a33SStefano Zampini if (point != parent) { 26088e330a33SStefano Zampini const PetscInt *cone; 26098e330a33SStefano Zampini PetscInt coneSize, c; 26108e330a33SStefano Zampini 26118e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, parent);CHKERRQ(ierr); 26128e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, parent);CHKERRQ(ierr); 26138e330a33SStefano Zampini ierr = DMPlexGetCone(dm, parent, &cone);CHKERRQ(ierr); 26148e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, parent, &coneSize);CHKERRQ(ierr); 26158e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 26168e330a33SStefano Zampini const PetscInt cp = cone[c]; 26178e330a33SStefano Zampini 26188e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, cp);CHKERRQ(ierr); 26198e330a33SStefano Zampini } 26208e330a33SStefano Zampini } 26218e330a33SStefano Zampini PetscFunctionReturn(0); 26228e330a33SStefano Zampini } 26238e330a33SStefano Zampini 26248e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point) 26258e330a33SStefano Zampini { 26268e330a33SStefano Zampini PetscInt i, numChildren; 26278e330a33SStefano Zampini const PetscInt *children; 26288e330a33SStefano Zampini PetscErrorCode ierr; 26298e330a33SStefano Zampini 26308e330a33SStefano Zampini PetscFunctionBeginHot; 26318e330a33SStefano Zampini ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr); 26328e330a33SStefano Zampini for (i = 0; i < numChildren; i++) { 26338e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, children[i]);CHKERRQ(ierr); 26348e330a33SStefano Zampini } 26358e330a33SStefano Zampini PetscFunctionReturn(0); 26368e330a33SStefano Zampini } 26378e330a33SStefano Zampini 26388e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point) 26398e330a33SStefano Zampini { 26408e330a33SStefano Zampini const PetscInt *cone; 26418e330a33SStefano Zampini PetscInt coneSize, c; 26428e330a33SStefano Zampini PetscErrorCode ierr; 26438e330a33SStefano Zampini 26448e330a33SStefano Zampini PetscFunctionBeginHot; 26458e330a33SStefano Zampini ierr = PetscHSetIAdd(ht, point);CHKERRQ(ierr); 26468e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Up_Private(dm, ht, point);CHKERRQ(ierr); 26478e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Down_Private(dm, ht, point);CHKERRQ(ierr); 26488e330a33SStefano Zampini ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 26498e330a33SStefano Zampini ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 26508e330a33SStefano Zampini for (c = 0; c < coneSize; c++) { 26518e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, cone[c]);CHKERRQ(ierr); 26528e330a33SStefano Zampini } 26538e330a33SStefano Zampini PetscFunctionReturn(0); 26548e330a33SStefano Zampini } 26558e330a33SStefano Zampini 26568e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS) 2657825f8a23SLisandro Dalcin { 2658825f8a23SLisandro Dalcin DM_Plex *mesh = (DM_Plex *)dm->data; 26598e330a33SStefano Zampini const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE; 26608e330a33SStefano Zampini PetscInt nelems, *elems, off = 0, p; 2661825f8a23SLisandro Dalcin PetscHSetI ht; 2662825f8a23SLisandro Dalcin PetscErrorCode ierr; 2663825f8a23SLisandro Dalcin 2664825f8a23SLisandro Dalcin PetscFunctionBegin; 2665825f8a23SLisandro Dalcin ierr = PetscHSetICreate(&ht);CHKERRQ(ierr); 2666825f8a23SLisandro Dalcin ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr); 26678e330a33SStefano Zampini if (!hasTree) { 26688e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 26698e330a33SStefano Zampini ierr = DMPlexAddClosure_Private(dm, ht, points[p]);CHKERRQ(ierr); 26708e330a33SStefano Zampini } 26718e330a33SStefano Zampini } else { 26728e330a33SStefano Zampini #if 1 26738e330a33SStefano Zampini for (p = 0; p < numPoints; ++p) { 26748e330a33SStefano Zampini ierr = DMPlexAddClosureTree_Private(dm, ht, points[p]);CHKERRQ(ierr); 26758e330a33SStefano Zampini } 26768e330a33SStefano Zampini #else 26778e330a33SStefano Zampini PetscInt *closure = NULL, closureSize, c; 2678825f8a23SLisandro Dalcin for (p = 0; p < numPoints; ++p) { 2679825f8a23SLisandro Dalcin ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2680825f8a23SLisandro Dalcin for (c = 0; c < closureSize*2; c += 2) { 2681825f8a23SLisandro Dalcin ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr); 2682825f8a23SLisandro Dalcin if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);} 2683825f8a23SLisandro Dalcin } 2684825f8a23SLisandro Dalcin } 2685825f8a23SLisandro Dalcin if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);} 26868e330a33SStefano Zampini #endif 26878e330a33SStefano Zampini } 2688825f8a23SLisandro Dalcin ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr); 2689825f8a23SLisandro Dalcin ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr); 2690825f8a23SLisandro Dalcin ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr); 2691825f8a23SLisandro Dalcin ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr); 2692825f8a23SLisandro Dalcin ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr); 2693825f8a23SLisandro Dalcin ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr); 2694825f8a23SLisandro Dalcin PetscFunctionReturn(0); 2695825f8a23SLisandro Dalcin } 2696825f8a23SLisandro Dalcin 26975abbe4feSMichael Lange /*@ 26985abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 26995abbe4feSMichael Lange 27005abbe4feSMichael Lange Input Parameters: 27015abbe4feSMichael Lange + dm - The DM 27025abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 27035abbe4feSMichael Lange 27045abbe4feSMichael Lange Level: developer 27055abbe4feSMichael Lange 270630b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap() 27075abbe4feSMichael Lange @*/ 27085abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 27099ffc88e4SToby Isaac { 2710825f8a23SLisandro Dalcin IS rankIS, pointIS, closureIS; 27115abbe4feSMichael Lange const PetscInt *ranks, *points; 2712825f8a23SLisandro Dalcin PetscInt numRanks, numPoints, r; 27139ffc88e4SToby Isaac PetscErrorCode ierr; 27149ffc88e4SToby Isaac 27159ffc88e4SToby Isaac PetscFunctionBegin; 27165abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 27175abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 27185abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 27195abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 27205abbe4feSMichael Lange const PetscInt rank = ranks[r]; 27215abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 27225abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 27235abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 27248e330a33SStefano Zampini ierr = DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS);CHKERRQ(ierr); 27255abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 27265abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2727825f8a23SLisandro Dalcin ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr); 2728825f8a23SLisandro Dalcin ierr = ISDestroy(&closureIS);CHKERRQ(ierr); 27299ffc88e4SToby Isaac } 27305abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 27315abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 27329ffc88e4SToby Isaac PetscFunctionReturn(0); 27339ffc88e4SToby Isaac } 27349ffc88e4SToby Isaac 273524d039d7SMichael Lange /*@ 273624d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 273724d039d7SMichael Lange 273824d039d7SMichael Lange Input Parameters: 273924d039d7SMichael Lange + dm - The DM 274024d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 274124d039d7SMichael Lange 274224d039d7SMichael Lange Level: developer 274324d039d7SMichael Lange 274424d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 274524d039d7SMichael Lange @*/ 274624d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 274770034214SMatthew G. Knepley { 274824d039d7SMichael Lange IS rankIS, pointIS; 274924d039d7SMichael Lange const PetscInt *ranks, *points; 275024d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 275124d039d7SMichael Lange PetscInt *adj = NULL; 275270034214SMatthew G. Knepley PetscErrorCode ierr; 275370034214SMatthew G. Knepley 275470034214SMatthew G. Knepley PetscFunctionBegin; 275524d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 275624d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 275724d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 275824d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 275924d039d7SMichael Lange const PetscInt rank = ranks[r]; 276070034214SMatthew G. Knepley 276124d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 276224d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 276324d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 276470034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 276524d039d7SMichael Lange adjSize = PETSC_DETERMINE; 276624d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 276724d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 276870034214SMatthew G. Knepley } 276924d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 277024d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 277170034214SMatthew G. Knepley } 277224d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 277324d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 277424d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 277524d039d7SMichael Lange PetscFunctionReturn(0); 277670034214SMatthew G. Knepley } 277770034214SMatthew G. Knepley 2778be200f8dSMichael Lange /*@ 2779be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 2780be200f8dSMichael Lange 2781be200f8dSMichael Lange Input Parameters: 2782be200f8dSMichael Lange + dm - The DM 2783be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 2784be200f8dSMichael Lange 2785be200f8dSMichael Lange Level: developer 2786be200f8dSMichael Lange 2787be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 2788be200f8dSMichael Lange overlap points from non-neighbouring partitions. 2789be200f8dSMichael Lange 2790be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 2791be200f8dSMichael Lange @*/ 2792be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 2793be200f8dSMichael Lange { 2794be200f8dSMichael Lange MPI_Comm comm; 2795be200f8dSMichael Lange PetscMPIInt rank; 2796be200f8dSMichael Lange PetscSF sfPoint; 27975d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 2798be200f8dSMichael Lange IS rankIS, pointIS; 2799be200f8dSMichael Lange const PetscInt *ranks; 2800be200f8dSMichael Lange PetscInt numRanks, r; 2801be200f8dSMichael Lange PetscErrorCode ierr; 2802be200f8dSMichael Lange 2803be200f8dSMichael Lange PetscFunctionBegin; 2804be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2805be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2806be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 28075d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 28085d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 28095d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 28105d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 28115d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 28125d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 28135d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 28145d04f6ebSMichael Lange if (remoteRank == rank) continue; 28155d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 28165d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 28175d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 28185d04f6ebSMichael Lange } 28195d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 28205d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 28215d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 2822be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 2823be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 2824be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 2825be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 2826be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 2827be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 2828be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 2829be200f8dSMichael Lange if (remoteRank == rank) continue; 2830be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 2831be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 2832be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2833be200f8dSMichael Lange } 2834be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 2835be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 2836be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 2837be200f8dSMichael Lange PetscFunctionReturn(0); 2838be200f8dSMichael Lange } 2839be200f8dSMichael Lange 28401fd9873aSMichael Lange /*@ 28411fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 28421fd9873aSMichael Lange 28431fd9873aSMichael Lange Input Parameters: 28441fd9873aSMichael Lange + dm - The DM 28451fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 2846fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank 28471fd9873aSMichael Lange 28481fd9873aSMichael Lange Output Parameter: 2849fe2efc57SMark . leafLabel - DMLabel assinging ranks to remote roots 28501fd9873aSMichael Lange 28511fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 28521fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 28531fd9873aSMichael Lange 28541fd9873aSMichael Lange Level: developer 28551fd9873aSMichael Lange 28561fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 28571fd9873aSMichael Lange @*/ 28581fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 28591fd9873aSMichael Lange { 28601fd9873aSMichael Lange MPI_Comm comm; 2861874ddda9SLisandro Dalcin PetscMPIInt rank, size, r; 2862874ddda9SLisandro Dalcin PetscInt p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize; 28631fd9873aSMichael Lange PetscSF sfPoint; 2864874ddda9SLisandro Dalcin PetscSection rootSection; 28651fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 28661fd9873aSMichael Lange const PetscSFNode *remote; 28671fd9873aSMichael Lange const PetscInt *local, *neighbors; 28681fd9873aSMichael Lange IS valueIS; 2869874ddda9SLisandro Dalcin PetscBool mpiOverflow = PETSC_FALSE; 28701fd9873aSMichael Lange PetscErrorCode ierr; 28711fd9873aSMichael Lange 28721fd9873aSMichael Lange PetscFunctionBegin; 287330b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 28741fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 28751fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 28769852e123SBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 28771fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 28781fd9873aSMichael Lange 28791fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 28801fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 28819852e123SBarry Smith ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr); 28821fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 28831fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 28841fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 28851fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 28861fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 28871fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 28881fd9873aSMichael Lange } 28891fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 2890874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr); 2891874ddda9SLisandro Dalcin ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr); 28921fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 28931fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 28941fd9873aSMichael Lange IS pointIS; 28951fd9873aSMichael Lange const PetscInt *points; 28961fd9873aSMichael Lange 28971fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 28981fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 28991fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 29001fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 29011fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 2902f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 2903f8987ae8SMichael Lange else {l = -1;} 29041fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 29051fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 29061fd9873aSMichael Lange } 29071fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 29081fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 29091fd9873aSMichael Lange } 2910874ddda9SLisandro Dalcin 2911874ddda9SLisandro Dalcin /* Try to communicate overlap using All-to-All */ 2912874ddda9SLisandro Dalcin if (!processSF) { 2913874ddda9SLisandro Dalcin PetscInt64 counter = 0; 2914874ddda9SLisandro Dalcin PetscBool locOverflow = PETSC_FALSE; 2915874ddda9SLisandro Dalcin PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls; 2916874ddda9SLisandro Dalcin 2917874ddda9SLisandro Dalcin ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr); 2918874ddda9SLisandro Dalcin for (n = 0; n < numNeighbors; ++n) { 2919874ddda9SLisandro Dalcin ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr); 2920874ddda9SLisandro Dalcin ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 2921874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES) 2922874ddda9SLisandro Dalcin if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2923874ddda9SLisandro Dalcin if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;} 2924874ddda9SLisandro Dalcin #endif 2925874ddda9SLisandro Dalcin scounts[neighbors[n]] = (PetscMPIInt) dof; 2926874ddda9SLisandro Dalcin sdispls[neighbors[n]] = (PetscMPIInt) off; 2927874ddda9SLisandro Dalcin } 2928874ddda9SLisandro Dalcin ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRQ(ierr); 2929874ddda9SLisandro Dalcin for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; } 2930874ddda9SLisandro Dalcin if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE; 2931874ddda9SLisandro Dalcin ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr); 2932874ddda9SLisandro Dalcin if (!mpiOverflow) { 293394b10faeSStefano Zampini ierr = PetscInfo(dm,"Using Alltoallv for mesh distribution\n");CHKERRQ(ierr); 2934874ddda9SLisandro Dalcin leafSize = (PetscInt) counter; 2935874ddda9SLisandro Dalcin ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr); 2936874ddda9SLisandro Dalcin ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRQ(ierr); 2937874ddda9SLisandro Dalcin } 2938874ddda9SLisandro Dalcin ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr); 2939874ddda9SLisandro Dalcin } 2940874ddda9SLisandro Dalcin 2941874ddda9SLisandro Dalcin /* Communicate overlap using process star forest */ 2942874ddda9SLisandro Dalcin if (processSF || mpiOverflow) { 2943874ddda9SLisandro Dalcin PetscSF procSF; 2944874ddda9SLisandro Dalcin PetscSection leafSection; 2945874ddda9SLisandro Dalcin 2946874ddda9SLisandro Dalcin if (processSF) { 294794b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution\n");CHKERRQ(ierr); 2948874ddda9SLisandro Dalcin ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr); 2949874ddda9SLisandro Dalcin procSF = processSF; 2950874ddda9SLisandro Dalcin } else { 295194b10faeSStefano Zampini ierr = PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n");CHKERRQ(ierr); 2952874ddda9SLisandro Dalcin ierr = PetscSFCreate(comm,&procSF);CHKERRQ(ierr); 2953900e0f05SJunchao Zhang ierr = PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr); 2954874ddda9SLisandro Dalcin } 2955874ddda9SLisandro Dalcin 2956874ddda9SLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr); 2957900e0f05SJunchao Zhang ierr = DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 2958874ddda9SLisandro Dalcin ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr); 2959874ddda9SLisandro Dalcin ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 2960874ddda9SLisandro Dalcin ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr); 2961874ddda9SLisandro Dalcin } 2962874ddda9SLisandro Dalcin 2963874ddda9SLisandro Dalcin for (p = 0; p < leafSize; p++) { 29641fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 29651fd9873aSMichael Lange } 2966874ddda9SLisandro Dalcin 2967874ddda9SLisandro Dalcin ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 2968874ddda9SLisandro Dalcin ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 29691fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 2970874ddda9SLisandro Dalcin ierr = PetscFree(rootPoints);CHKERRQ(ierr); 29711fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 297230b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr); 29731fd9873aSMichael Lange PetscFunctionReturn(0); 29741fd9873aSMichael Lange } 29751fd9873aSMichael Lange 2976aa3148a8SMichael Lange /*@ 2977aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 2978aa3148a8SMichael Lange 2979aa3148a8SMichael Lange Input Parameters: 2980aa3148a8SMichael Lange + dm - The DM 2981aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 2982aa3148a8SMichael Lange 2983aa3148a8SMichael Lange Output Parameter: 2984fe2efc57SMark . sf - The star forest communication context encapsulating the defined mapping 2985aa3148a8SMichael Lange 2986aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 2987aa3148a8SMichael Lange 2988aa3148a8SMichael Lange Level: developer 2989aa3148a8SMichael Lange 299030b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap() 2991aa3148a8SMichael Lange @*/ 2992aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 2993aa3148a8SMichael Lange { 29946e203dd9SStefano Zampini PetscMPIInt rank; 29956e203dd9SStefano Zampini PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors; 2996aa3148a8SMichael Lange PetscSFNode *remotePoints; 29976e203dd9SStefano Zampini IS remoteRootIS, neighborsIS; 29986e203dd9SStefano Zampini const PetscInt *remoteRoots, *neighbors; 2999aa3148a8SMichael Lange PetscErrorCode ierr; 3000aa3148a8SMichael Lange 3001aa3148a8SMichael Lange PetscFunctionBegin; 300230b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 300343f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3004aa3148a8SMichael Lange 30056e203dd9SStefano Zampini ierr = DMLabelGetValueIS(label, &neighborsIS);CHKERRQ(ierr); 30066e203dd9SStefano Zampini #if 0 30076e203dd9SStefano Zampini { 30086e203dd9SStefano Zampini IS is; 30096e203dd9SStefano Zampini ierr = ISDuplicate(neighborsIS, &is);CHKERRQ(ierr); 30106e203dd9SStefano Zampini ierr = ISSort(is);CHKERRQ(ierr); 30116e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 30126e203dd9SStefano Zampini neighborsIS = is; 30136e203dd9SStefano Zampini } 30146e203dd9SStefano Zampini #endif 30156e203dd9SStefano Zampini ierr = ISGetLocalSize(neighborsIS, &nNeighbors);CHKERRQ(ierr); 30166e203dd9SStefano Zampini ierr = ISGetIndices(neighborsIS, &neighbors);CHKERRQ(ierr); 30176e203dd9SStefano Zampini for (numRemote = 0, n = 0; n < nNeighbors; ++n) { 30186e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, neighbors[n], &numPoints);CHKERRQ(ierr); 3019aa3148a8SMichael Lange numRemote += numPoints; 3020aa3148a8SMichael Lange } 3021aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 302243f7d02bSMichael Lange /* Put owned points first */ 302343f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 302443f7d02bSMichael Lange if (numPoints > 0) { 302543f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 302643f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 302743f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 302843f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 302943f7d02bSMichael Lange remotePoints[idx].rank = rank; 303043f7d02bSMichael Lange idx++; 303143f7d02bSMichael Lange } 303243f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 303343f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 303443f7d02bSMichael Lange } 303543f7d02bSMichael Lange /* Now add remote points */ 30366e203dd9SStefano Zampini for (n = 0; n < nNeighbors; ++n) { 30376e203dd9SStefano Zampini const PetscInt nn = neighbors[n]; 30386e203dd9SStefano Zampini 30396e203dd9SStefano Zampini ierr = DMLabelGetStratumSize(label, nn, &numPoints);CHKERRQ(ierr); 30406e203dd9SStefano Zampini if (nn == rank || numPoints <= 0) continue; 30416e203dd9SStefano Zampini ierr = DMLabelGetStratumIS(label, nn, &remoteRootIS);CHKERRQ(ierr); 3042aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 3043aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 3044aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 30456e203dd9SStefano Zampini remotePoints[idx].rank = nn; 3046aa3148a8SMichael Lange idx++; 3047aa3148a8SMichael Lange } 3048aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 3049aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 3050aa3148a8SMichael Lange } 3051aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 3052aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3053aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 305430b0ce1bSStefano Zampini ierr = PetscSFSetUp(*sf);CHKERRQ(ierr); 30556e203dd9SStefano Zampini ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr); 305630b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr); 305770034214SMatthew G. Knepley PetscFunctionReturn(0); 305870034214SMatthew G. Knepley } 3059cb87ef4cSFlorian Wechsung 30606a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors 30616a3739e5SFlorian Wechsung * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take 30626a3739e5SFlorian Wechsung * them out in that case. */ 30636a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 30647a82c785SFlorian Wechsung /*@C 30657f57c1a4SFlorian Wechsung 30667f57c1a4SFlorian Wechsung DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place). 30677f57c1a4SFlorian Wechsung 30687f57c1a4SFlorian Wechsung Input parameters: 30697f57c1a4SFlorian Wechsung + dm - The DMPlex object. 3070fe2efc57SMark . n - The number of points. 3071fe2efc57SMark . pointsToRewrite - The points in the SF whose ownership will change. 3072fe2efc57SMark . targetOwners - New owner for each element in pointsToRewrite. 3073fe2efc57SMark - degrees - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd. 30747f57c1a4SFlorian Wechsung 30757f57c1a4SFlorian Wechsung Level: developer 30767f57c1a4SFlorian Wechsung 30777f57c1a4SFlorian Wechsung @*/ 30787f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees) 30797f57c1a4SFlorian Wechsung { 30807f57c1a4SFlorian Wechsung PetscInt ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs; 30817f57c1a4SFlorian Wechsung PetscInt *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew; 30827f57c1a4SFlorian Wechsung PetscSFNode *leafLocationsNew; 30837f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 30847f57c1a4SFlorian Wechsung const PetscInt *ilocal; 30857f57c1a4SFlorian Wechsung PetscBool *isLeaf; 30867f57c1a4SFlorian Wechsung PetscSF sf; 30877f57c1a4SFlorian Wechsung MPI_Comm comm; 30885a30b08bSFlorian Wechsung PetscMPIInt rank, size; 30897f57c1a4SFlorian Wechsung 30907f57c1a4SFlorian Wechsung PetscFunctionBegin; 30917f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 30927f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 30937f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 30947f57c1a4SFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 30957f57c1a4SFlorian Wechsung 30967f57c1a4SFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 30977f57c1a4SFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 30987f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 30997f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31007f57c1a4SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 31017f57c1a4SFlorian Wechsung } 31027f57c1a4SFlorian Wechsung for (i=0; i<nleafs; i++) { 31037f57c1a4SFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 31047f57c1a4SFlorian Wechsung } 31057f57c1a4SFlorian Wechsung 31067f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr); 31077f57c1a4SFlorian Wechsung cumSumDegrees[0] = 0; 31087f57c1a4SFlorian Wechsung for (i=1; i<=pEnd-pStart; i++) { 31097f57c1a4SFlorian Wechsung cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1]; 31107f57c1a4SFlorian Wechsung } 31117f57c1a4SFlorian Wechsung sumDegrees = cumSumDegrees[pEnd-pStart]; 31127f57c1a4SFlorian Wechsung /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */ 31137f57c1a4SFlorian Wechsung 31147f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr); 31157f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr); 31167f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31177f57c1a4SFlorian Wechsung rankOnLeafs[i] = rank; 31187f57c1a4SFlorian Wechsung } 31197f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 31207f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr); 31217f57c1a4SFlorian Wechsung ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr); 31227f57c1a4SFlorian Wechsung 31237f57c1a4SFlorian Wechsung /* get the remote local points of my leaves */ 31247f57c1a4SFlorian Wechsung ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr); 31257f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr); 31267f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31277f57c1a4SFlorian Wechsung points[i] = pStart+i; 31287f57c1a4SFlorian Wechsung } 31297f57c1a4SFlorian Wechsung ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 31307f57c1a4SFlorian Wechsung ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr); 31317f57c1a4SFlorian Wechsung ierr = PetscFree(points);CHKERRQ(ierr); 31327f57c1a4SFlorian Wechsung /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */ 31337f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr); 31347f57c1a4SFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr); 31357f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31367f57c1a4SFlorian Wechsung newOwners[i] = -1; 31377f57c1a4SFlorian Wechsung newNumbers[i] = -1; 31387f57c1a4SFlorian Wechsung } 31397f57c1a4SFlorian Wechsung { 31407f57c1a4SFlorian Wechsung PetscInt oldNumber, newNumber, oldOwner, newOwner; 31417f57c1a4SFlorian Wechsung for (i=0; i<n; i++) { 31427f57c1a4SFlorian Wechsung oldNumber = pointsToRewrite[i]; 31437f57c1a4SFlorian Wechsung newNumber = -1; 31447f57c1a4SFlorian Wechsung oldOwner = rank; 31457f57c1a4SFlorian Wechsung newOwner = targetOwners[i]; 31467f57c1a4SFlorian Wechsung if (oldOwner == newOwner) { 31477f57c1a4SFlorian Wechsung newNumber = oldNumber; 31487f57c1a4SFlorian Wechsung } else { 31497f57c1a4SFlorian Wechsung for (j=0; j<degrees[oldNumber]; j++) { 31507f57c1a4SFlorian Wechsung if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) { 31517f57c1a4SFlorian Wechsung newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j]; 31527f57c1a4SFlorian Wechsung break; 31537f57c1a4SFlorian Wechsung } 31547f57c1a4SFlorian Wechsung } 31557f57c1a4SFlorian Wechsung } 31567f57c1a4SFlorian Wechsung if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex."); 31577f57c1a4SFlorian Wechsung 31587f57c1a4SFlorian Wechsung newOwners[oldNumber] = newOwner; 31597f57c1a4SFlorian Wechsung newNumbers[oldNumber] = newNumber; 31607f57c1a4SFlorian Wechsung } 31617f57c1a4SFlorian Wechsung } 31627f57c1a4SFlorian Wechsung ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr); 31637f57c1a4SFlorian Wechsung ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr); 31647f57c1a4SFlorian Wechsung ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr); 31657f57c1a4SFlorian Wechsung 31667f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 31677f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners);CHKERRQ(ierr); 31687f57c1a4SFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 31697f57c1a4SFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers);CHKERRQ(ierr); 31707f57c1a4SFlorian Wechsung 31717f57c1a4SFlorian Wechsung /* Now count how many leafs we have on each processor. */ 31727f57c1a4SFlorian Wechsung leafCounter=0; 31737f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31747f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 31757f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 31767f57c1a4SFlorian Wechsung leafCounter++; 31777f57c1a4SFlorian Wechsung } 31787f57c1a4SFlorian Wechsung } else { 31797f57c1a4SFlorian Wechsung if (isLeaf[i]) { 31807f57c1a4SFlorian Wechsung leafCounter++; 31817f57c1a4SFlorian Wechsung } 31827f57c1a4SFlorian Wechsung } 31837f57c1a4SFlorian Wechsung } 31847f57c1a4SFlorian Wechsung 31857f57c1a4SFlorian Wechsung /* Now set up the new sf by creating the leaf arrays */ 31867f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr); 31877f57c1a4SFlorian Wechsung ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr); 31887f57c1a4SFlorian Wechsung 31897f57c1a4SFlorian Wechsung leafCounter = 0; 31907f57c1a4SFlorian Wechsung counter = 0; 31917f57c1a4SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 31927f57c1a4SFlorian Wechsung if (newOwners[i] >= 0) { 31937f57c1a4SFlorian Wechsung if (newOwners[i] != rank) { 31947f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 31957f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = newOwners[i]; 31967f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = newNumbers[i]; 31977f57c1a4SFlorian Wechsung leafCounter++; 31987f57c1a4SFlorian Wechsung } 31997f57c1a4SFlorian Wechsung } else { 32007f57c1a4SFlorian Wechsung if (isLeaf[i]) { 32017f57c1a4SFlorian Wechsung leafsNew[leafCounter] = i; 32027f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].rank = iremote[counter].rank; 32037f57c1a4SFlorian Wechsung leafLocationsNew[leafCounter].index = iremote[counter].index; 32047f57c1a4SFlorian Wechsung leafCounter++; 32057f57c1a4SFlorian Wechsung } 32067f57c1a4SFlorian Wechsung } 32077f57c1a4SFlorian Wechsung if (isLeaf[i]) { 32087f57c1a4SFlorian Wechsung counter++; 32097f57c1a4SFlorian Wechsung } 32107f57c1a4SFlorian Wechsung } 32117f57c1a4SFlorian Wechsung 32127f57c1a4SFlorian Wechsung ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 32137f57c1a4SFlorian Wechsung ierr = PetscFree(newOwners);CHKERRQ(ierr); 32147f57c1a4SFlorian Wechsung ierr = PetscFree(newNumbers);CHKERRQ(ierr); 32157f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 32167f57c1a4SFlorian Wechsung PetscFunctionReturn(0); 32177f57c1a4SFlorian Wechsung } 32187f57c1a4SFlorian Wechsung 3219125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer) 3220125d2a8fSFlorian Wechsung { 32215a30b08bSFlorian Wechsung PetscInt *distribution, min, max, sum, i, ierr; 32225a30b08bSFlorian Wechsung PetscMPIInt rank, size; 3223125d2a8fSFlorian Wechsung PetscFunctionBegin; 3224125d2a8fSFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3225125d2a8fSFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3226125d2a8fSFlorian Wechsung ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr); 3227125d2a8fSFlorian Wechsung for (i=0; i<n; i++) { 3228125d2a8fSFlorian Wechsung if (part) distribution[part[i]] += vtxwgt[skip*i]; 3229125d2a8fSFlorian Wechsung else distribution[rank] += vtxwgt[skip*i]; 3230125d2a8fSFlorian Wechsung } 3231125d2a8fSFlorian Wechsung ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 3232125d2a8fSFlorian Wechsung min = distribution[0]; 3233125d2a8fSFlorian Wechsung max = distribution[0]; 3234125d2a8fSFlorian Wechsung sum = distribution[0]; 3235125d2a8fSFlorian Wechsung for (i=1; i<size; i++) { 3236125d2a8fSFlorian Wechsung if (distribution[i]<min) min=distribution[i]; 3237125d2a8fSFlorian Wechsung if (distribution[i]>max) max=distribution[i]; 3238125d2a8fSFlorian Wechsung sum += distribution[i]; 3239125d2a8fSFlorian Wechsung } 3240125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr); 3241125d2a8fSFlorian Wechsung ierr = PetscFree(distribution);CHKERRQ(ierr); 3242125d2a8fSFlorian Wechsung PetscFunctionReturn(0); 3243125d2a8fSFlorian Wechsung } 3244125d2a8fSFlorian Wechsung 32456a3739e5SFlorian Wechsung #endif 32466a3739e5SFlorian Wechsung 3247cb87ef4cSFlorian Wechsung /*@ 32485dc86ac1SFlorian 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. 3249cb87ef4cSFlorian Wechsung 3250cb87ef4cSFlorian Wechsung Input parameters: 3251ed44d270SFlorian Wechsung + dm - The DMPlex object. 3252fe2efc57SMark . entityDepth - depth of the entity to balance (0 -> balance vertices). 3253fe2efc57SMark . useInitialGuess - whether to use the current distribution as initial guess (only used by ParMETIS). 3254fe2efc57SMark - parallel - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS. 3255cb87ef4cSFlorian Wechsung 32568b879b41SFlorian Wechsung Output parameters: 3257fe2efc57SMark . success - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True. 32588b879b41SFlorian Wechsung 325990ea27d8SSatish Balay Level: intermediate 3260cb87ef4cSFlorian Wechsung 3261cb87ef4cSFlorian Wechsung @*/ 3262cb87ef4cSFlorian Wechsung 32638b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success) 3264cb87ef4cSFlorian Wechsung { 326541525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS) 3266cb87ef4cSFlorian Wechsung PetscSF sf; 32670faf6628SFlorian Wechsung PetscInt ierr, i, j, idx, jdx; 32687f57c1a4SFlorian Wechsung PetscInt eBegin, eEnd, nroots, nleafs, pStart, pEnd; 32697f57c1a4SFlorian Wechsung const PetscInt *degrees, *ilocal; 32707f57c1a4SFlorian Wechsung const PetscSFNode *iremote; 3271cb87ef4cSFlorian Wechsung PetscBool *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned; 3272cf818975SFlorian Wechsung PetscInt numExclusivelyOwned, numNonExclusivelyOwned; 3273cb87ef4cSFlorian Wechsung PetscMPIInt rank, size; 32747f57c1a4SFlorian Wechsung PetscInt *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers; 32755dc86ac1SFlorian Wechsung const PetscInt *cumSumVertices; 3276cb87ef4cSFlorian Wechsung PetscInt offset, counter; 32777f57c1a4SFlorian Wechsung PetscInt lenadjncy; 3278cb87ef4cSFlorian Wechsung PetscInt *xadj, *adjncy, *vtxwgt; 3279cb87ef4cSFlorian Wechsung PetscInt lenxadj; 3280cb87ef4cSFlorian Wechsung PetscInt *adjwgt = NULL; 3281cb87ef4cSFlorian Wechsung PetscInt *part, *options; 3282cf818975SFlorian Wechsung PetscInt nparts, wgtflag, numflag, ncon, edgecut; 3283cb87ef4cSFlorian Wechsung real_t *ubvec; 3284cb87ef4cSFlorian Wechsung PetscInt *firstVertices, *renumbering; 3285cb87ef4cSFlorian Wechsung PetscInt failed, failedGlobal; 3286cb87ef4cSFlorian Wechsung MPI_Comm comm; 32874baf1206SFlorian Wechsung Mat A, Apre; 328812617df9SFlorian Wechsung const char *prefix = NULL; 32897d197802SFlorian Wechsung PetscViewer viewer; 32907d197802SFlorian Wechsung PetscViewerFormat format; 32915a30b08bSFlorian Wechsung PetscLayout layout; 329212617df9SFlorian Wechsung 329312617df9SFlorian Wechsung PetscFunctionBegin; 32948b879b41SFlorian Wechsung if (success) *success = PETSC_FALSE; 32957f57c1a4SFlorian Wechsung ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 32967f57c1a4SFlorian Wechsung ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 32977f57c1a4SFlorian Wechsung ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 32987f57c1a4SFlorian Wechsung if (size==1) PetscFunctionReturn(0); 32997f57c1a4SFlorian Wechsung 330041525646SFlorian Wechsung ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 330141525646SFlorian Wechsung 33025a30b08bSFlorian Wechsung ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr); 33035dc86ac1SFlorian Wechsung if (viewer) { 33045a30b08bSFlorian Wechsung ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 33057d197802SFlorian Wechsung } 33067d197802SFlorian Wechsung 3307ed44d270SFlorian Wechsung /* Figure out all points in the plex that we are interested in balancing. */ 3308d5528e35SFlorian Wechsung ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr); 3309cb87ef4cSFlorian Wechsung ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3310cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr); 3311cf818975SFlorian Wechsung 3312cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 33135a7e692eSFlorian Wechsung toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd); 3314cb87ef4cSFlorian Wechsung } 3315cb87ef4cSFlorian Wechsung 3316cf818975SFlorian Wechsung /* There are three types of points: 3317cf818975SFlorian Wechsung * exclusivelyOwned: points that are owned by this process and only seen by this process 3318cf818975SFlorian Wechsung * nonExclusivelyOwned: points that are owned by this process but seen by at least another process 3319cf818975SFlorian Wechsung * leaf: a point that is seen by this process but owned by a different process 3320cf818975SFlorian Wechsung */ 3321cb87ef4cSFlorian Wechsung ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 3322cb87ef4cSFlorian Wechsung ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote); CHKERRQ(ierr); 3323cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr); 3324cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr); 3325cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr); 3326cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3327cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_FALSE; 3328cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_FALSE; 3329cf818975SFlorian Wechsung isLeaf[i] = PETSC_FALSE; 3330cb87ef4cSFlorian Wechsung } 3331cf818975SFlorian Wechsung 3332cf818975SFlorian Wechsung /* start by marking all the leafs */ 3333cb87ef4cSFlorian Wechsung for (i=0; i<nleafs; i++) { 3334cb87ef4cSFlorian Wechsung isLeaf[ilocal[i]-pStart] = PETSC_TRUE; 3335cb87ef4cSFlorian Wechsung } 3336cb87ef4cSFlorian Wechsung 3337cf818975SFlorian Wechsung /* for an owned point, we can figure out whether another processor sees it or 3338cf818975SFlorian Wechsung * not by calculating its degree */ 33397f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeBegin(sf, °rees);CHKERRQ(ierr); 33407f57c1a4SFlorian Wechsung ierr = PetscSFComputeDegreeEnd(sf, °rees);CHKERRQ(ierr); 3341cf818975SFlorian Wechsung 3342cb87ef4cSFlorian Wechsung numExclusivelyOwned = 0; 3343cb87ef4cSFlorian Wechsung numNonExclusivelyOwned = 0; 3344cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3345cb87ef4cSFlorian Wechsung if (toBalance[i]) { 33467f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 3347cb87ef4cSFlorian Wechsung isNonExclusivelyOwned[i] = PETSC_TRUE; 3348cb87ef4cSFlorian Wechsung numNonExclusivelyOwned += 1; 3349cb87ef4cSFlorian Wechsung } else { 3350cb87ef4cSFlorian Wechsung if (!isLeaf[i]) { 3351cb87ef4cSFlorian Wechsung isExclusivelyOwned[i] = PETSC_TRUE; 3352cb87ef4cSFlorian Wechsung numExclusivelyOwned += 1; 3353cb87ef4cSFlorian Wechsung } 3354cb87ef4cSFlorian Wechsung } 3355cb87ef4cSFlorian Wechsung } 3356cb87ef4cSFlorian Wechsung } 3357cb87ef4cSFlorian Wechsung 3358cf818975SFlorian Wechsung /* We are going to build a graph with one vertex per core representing the 3359cf818975SFlorian Wechsung * exclusively owned points and then one vertex per nonExclusively owned 3360cf818975SFlorian Wechsung * point. */ 3361cb87ef4cSFlorian Wechsung 33625dc86ac1SFlorian Wechsung ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 33635dc86ac1SFlorian Wechsung ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr); 33645dc86ac1SFlorian Wechsung ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 33655dc86ac1SFlorian Wechsung ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr); 33665dc86ac1SFlorian Wechsung 3367cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 33685a427404SJunchao Zhang for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;} 3369cb87ef4cSFlorian Wechsung offset = cumSumVertices[rank]; 3370cb87ef4cSFlorian Wechsung counter = 0; 3371cb87ef4cSFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 3372cb87ef4cSFlorian Wechsung if (toBalance[i]) { 33737f57c1a4SFlorian Wechsung if (degrees[i] > 0) { 3374cb87ef4cSFlorian Wechsung globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset; 3375cb87ef4cSFlorian Wechsung counter++; 3376cb87ef4cSFlorian Wechsung } 3377cb87ef4cSFlorian Wechsung } 3378cb87ef4cSFlorian Wechsung } 3379cb87ef4cSFlorian Wechsung 3380cb87ef4cSFlorian Wechsung /* send the global numbers of vertices I own to the leafs so that they know to connect to it */ 3381cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr); 3382cb87ef4cSFlorian Wechsung ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3383cb87ef4cSFlorian Wechsung ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers);CHKERRQ(ierr); 3384cb87ef4cSFlorian Wechsung 33850faf6628SFlorian Wechsung /* Now start building the data structure for ParMETIS */ 3386cb87ef4cSFlorian Wechsung 33874baf1206SFlorian Wechsung ierr = MatCreate(comm, &Apre);CHKERRQ(ierr); 33884baf1206SFlorian Wechsung ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr); 33894baf1206SFlorian Wechsung ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 33904baf1206SFlorian Wechsung ierr = MatSetUp(Apre);CHKERRQ(ierr); 33918c9a1619SFlorian Wechsung 33928c9a1619SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 33938c9a1619SFlorian Wechsung if (toBalance[i]) { 33940faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 33950faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 33960faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 33970faf6628SFlorian Wechsung else continue; 33980faf6628SFlorian Wechsung ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 33990faf6628SFlorian Wechsung ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 34004baf1206SFlorian Wechsung } 34014baf1206SFlorian Wechsung } 34024baf1206SFlorian Wechsung 34034baf1206SFlorian Wechsung ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 34044baf1206SFlorian Wechsung ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 34054baf1206SFlorian Wechsung 34064baf1206SFlorian Wechsung ierr = MatCreate(comm, &A);CHKERRQ(ierr); 34074baf1206SFlorian Wechsung ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr); 34084baf1206SFlorian Wechsung ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr); 34094baf1206SFlorian Wechsung ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr); 34104baf1206SFlorian Wechsung ierr = MatDestroy(&Apre);CHKERRQ(ierr); 34114baf1206SFlorian Wechsung 34124baf1206SFlorian Wechsung for (i=0; i<pEnd-pStart; i++) { 34134baf1206SFlorian Wechsung if (toBalance[i]) { 34140faf6628SFlorian Wechsung idx = cumSumVertices[rank]; 34150faf6628SFlorian Wechsung if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i]; 34160faf6628SFlorian Wechsung else if (isLeaf[i]) jdx = leafGlobalNumbers[i]; 34170faf6628SFlorian Wechsung else continue; 34180faf6628SFlorian Wechsung ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr); 34190faf6628SFlorian Wechsung ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr); 34200941debbSFlorian Wechsung } 34210941debbSFlorian Wechsung } 34228c9a1619SFlorian Wechsung 34238c9a1619SFlorian Wechsung ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 34248c9a1619SFlorian Wechsung ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 34254baf1206SFlorian Wechsung ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr); 34264baf1206SFlorian Wechsung ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr); 34274baf1206SFlorian Wechsung 342841525646SFlorian Wechsung nparts = size; 342941525646SFlorian Wechsung wgtflag = 2; 343041525646SFlorian Wechsung numflag = 0; 343141525646SFlorian Wechsung ncon = 2; 343241525646SFlorian Wechsung real_t *tpwgts; 343341525646SFlorian Wechsung ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr); 343441525646SFlorian Wechsung for (i=0; i<ncon*nparts; i++) { 343541525646SFlorian Wechsung tpwgts[i] = 1./(nparts); 343641525646SFlorian Wechsung } 343741525646SFlorian Wechsung 343841525646SFlorian Wechsung ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr); 343941525646SFlorian Wechsung ubvec[0] = 1.01; 34405a30b08bSFlorian Wechsung ubvec[1] = 1.01; 34418c9a1619SFlorian Wechsung lenadjncy = 0; 34428c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 34438c9a1619SFlorian Wechsung PetscInt temp=0; 34448c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 34458c9a1619SFlorian Wechsung lenadjncy += temp; 34468c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr); 34478c9a1619SFlorian Wechsung } 34488c9a1619SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr); 34497407ba93SFlorian Wechsung lenxadj = 2 + numNonExclusivelyOwned; 34500941debbSFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr); 34510941debbSFlorian Wechsung xadj[0] = 0; 34528c9a1619SFlorian Wechsung counter = 0; 34538c9a1619SFlorian Wechsung for (i=0; i<1+numNonExclusivelyOwned; i++) { 34542953a68cSFlorian Wechsung PetscInt temp=0; 34552953a68cSFlorian Wechsung const PetscInt *cols; 34568c9a1619SFlorian Wechsung ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 3457580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy[counter], cols, temp);CHKERRQ(ierr); 34588c9a1619SFlorian Wechsung counter += temp; 34590941debbSFlorian Wechsung xadj[i+1] = counter; 34608c9a1619SFlorian Wechsung ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr); 34618c9a1619SFlorian Wechsung } 34628c9a1619SFlorian Wechsung 3463cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr); 346441525646SFlorian Wechsung ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr); 346541525646SFlorian Wechsung vtxwgt[0] = numExclusivelyOwned; 346641525646SFlorian Wechsung if (ncon>1) vtxwgt[1] = 1; 346741525646SFlorian Wechsung for (i=0; i<numNonExclusivelyOwned; i++) { 346841525646SFlorian Wechsung vtxwgt[ncon*(i+1)] = 1; 346941525646SFlorian Wechsung if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0; 347041525646SFlorian Wechsung } 34718c9a1619SFlorian Wechsung 34725dc86ac1SFlorian Wechsung if (viewer) { 34737d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr); 34747d197802SFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr); 347512617df9SFlorian Wechsung } 347641525646SFlorian Wechsung if (parallel) { 34775a30b08bSFlorian Wechsung ierr = PetscMalloc1(4, &options);CHKERRQ(ierr); 34785a30b08bSFlorian Wechsung options[0] = 1; 34795a30b08bSFlorian Wechsung options[1] = 0; /* Verbosity */ 34805a30b08bSFlorian Wechsung options[2] = 0; /* Seed */ 34815a30b08bSFlorian Wechsung options[3] = PARMETIS_PSR_COUPLED; /* Seed */ 34825dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); } 34838c9a1619SFlorian Wechsung if (useInitialGuess) { 34845dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); } 34858c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_RefineKway"); 34865dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 348706b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()"); 34888c9a1619SFlorian Wechsung PetscStackPop; 34898c9a1619SFlorian Wechsung } else { 34908c9a1619SFlorian Wechsung PetscStackPush("ParMETIS_V3_PartKway"); 34915dc86ac1SFlorian Wechsung ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); 34928c9a1619SFlorian Wechsung PetscStackPop; 349306b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 34948c9a1619SFlorian Wechsung } 3495ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 349641525646SFlorian Wechsung } else { 34975dc86ac1SFlorian Wechsung if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); } 349841525646SFlorian Wechsung Mat As; 349941525646SFlorian Wechsung PetscInt numRows; 350041525646SFlorian Wechsung PetscInt *partGlobal; 350141525646SFlorian Wechsung ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr); 3502cb87ef4cSFlorian Wechsung 350341525646SFlorian Wechsung PetscInt *numExclusivelyOwnedAll; 350441525646SFlorian Wechsung ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr); 350541525646SFlorian Wechsung numExclusivelyOwnedAll[rank] = numExclusivelyOwned; 35062953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRQ(ierr); 3507cb87ef4cSFlorian Wechsung 350841525646SFlorian Wechsung ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr); 350941525646SFlorian Wechsung ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr); 35105dc86ac1SFlorian Wechsung if (!rank) { 351141525646SFlorian Wechsung PetscInt *adjncy_g, *xadj_g, *vtxwgt_g; 351241525646SFlorian Wechsung lenadjncy = 0; 351341525646SFlorian Wechsung 351441525646SFlorian Wechsung for (i=0; i<numRows; i++) { 351541525646SFlorian Wechsung PetscInt temp=0; 351641525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 351741525646SFlorian Wechsung lenadjncy += temp; 351841525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr); 351941525646SFlorian Wechsung } 352041525646SFlorian Wechsung ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr); 352141525646SFlorian Wechsung lenxadj = 1 + numRows; 352241525646SFlorian Wechsung ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr); 352341525646SFlorian Wechsung xadj_g[0] = 0; 352441525646SFlorian Wechsung counter = 0; 352541525646SFlorian Wechsung for (i=0; i<numRows; i++) { 35262953a68cSFlorian Wechsung PetscInt temp=0; 35272953a68cSFlorian Wechsung const PetscInt *cols; 352841525646SFlorian Wechsung ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 3529580bdb30SBarry Smith ierr = PetscArraycpy(&adjncy_g[counter], cols, temp);CHKERRQ(ierr); 353041525646SFlorian Wechsung counter += temp; 353141525646SFlorian Wechsung xadj_g[i+1] = counter; 353241525646SFlorian Wechsung ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr); 353341525646SFlorian Wechsung } 353441525646SFlorian Wechsung ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr); 353541525646SFlorian Wechsung for (i=0; i<size; i++){ 353641525646SFlorian Wechsung vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i]; 353741525646SFlorian Wechsung if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1; 353841525646SFlorian Wechsung for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) { 353941525646SFlorian Wechsung vtxwgt_g[ncon*j] = 1; 354041525646SFlorian Wechsung if (ncon>1) vtxwgt_g[2*j+1] = 0; 354141525646SFlorian Wechsung } 354241525646SFlorian Wechsung } 354341525646SFlorian Wechsung ierr = PetscMalloc1(64, &options);CHKERRQ(ierr); 354441525646SFlorian Wechsung ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 354506b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 354641525646SFlorian Wechsung options[METIS_OPTION_CONTIG] = 1; 354741525646SFlorian Wechsung PetscStackPush("METIS_PartGraphKway"); 354806b3913eSFlorian Wechsung ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal); 354941525646SFlorian Wechsung PetscStackPop; 355006b3913eSFlorian Wechsung if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 3551ef74bcceSFlorian Wechsung ierr = PetscFree(options);CHKERRQ(ierr); 355241525646SFlorian Wechsung ierr = PetscFree(xadj_g);CHKERRQ(ierr); 355341525646SFlorian Wechsung ierr = PetscFree(adjncy_g);CHKERRQ(ierr); 355441525646SFlorian Wechsung ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr); 355541525646SFlorian Wechsung } 355641525646SFlorian Wechsung ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr); 355741525646SFlorian Wechsung 35585dc86ac1SFlorian Wechsung /* Now scatter the parts array. */ 35595dc86ac1SFlorian Wechsung { 356081a13b52SFlorian Wechsung PetscMPIInt *counts, *mpiCumSumVertices; 35615dc86ac1SFlorian Wechsung ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr); 356281a13b52SFlorian Wechsung ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr); 35635dc86ac1SFlorian Wechsung for(i=0; i<size; i++) { 356481a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr); 356541525646SFlorian Wechsung } 356681a13b52SFlorian Wechsung for(i=0; i<=size; i++) { 356781a13b52SFlorian Wechsung ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr); 356881a13b52SFlorian Wechsung } 356981a13b52SFlorian Wechsung ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRQ(ierr); 35705dc86ac1SFlorian Wechsung ierr = PetscFree(counts);CHKERRQ(ierr); 357181a13b52SFlorian Wechsung ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr); 35725dc86ac1SFlorian Wechsung } 35735dc86ac1SFlorian Wechsung 357441525646SFlorian Wechsung ierr = PetscFree(partGlobal);CHKERRQ(ierr); 35752953a68cSFlorian Wechsung ierr = MatDestroy(&As);CHKERRQ(ierr); 357641525646SFlorian Wechsung } 3577cb87ef4cSFlorian Wechsung 35782953a68cSFlorian Wechsung ierr = MatDestroy(&A);CHKERRQ(ierr); 3579cb87ef4cSFlorian Wechsung ierr = PetscFree(ubvec);CHKERRQ(ierr); 3580cb87ef4cSFlorian Wechsung ierr = PetscFree(tpwgts);CHKERRQ(ierr); 3581cb87ef4cSFlorian Wechsung 3582cb87ef4cSFlorian Wechsung /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */ 3583cb87ef4cSFlorian Wechsung 3584cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr); 3585cb87ef4cSFlorian Wechsung ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr); 3586cb87ef4cSFlorian Wechsung firstVertices[rank] = part[0]; 35872953a68cSFlorian Wechsung ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRQ(ierr); 3588cb87ef4cSFlorian Wechsung for (i=0; i<size; i++) { 3589cb87ef4cSFlorian Wechsung renumbering[firstVertices[i]] = i; 3590cb87ef4cSFlorian Wechsung } 3591cb87ef4cSFlorian Wechsung for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) { 3592cb87ef4cSFlorian Wechsung part[i] = renumbering[part[i]]; 3593cb87ef4cSFlorian Wechsung } 3594cb87ef4cSFlorian Wechsung /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */ 3595cb87ef4cSFlorian Wechsung failed = (PetscInt)(part[0] != rank); 35962953a68cSFlorian Wechsung ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRQ(ierr); 3597cb87ef4cSFlorian Wechsung 35987f57c1a4SFlorian Wechsung ierr = PetscFree(firstVertices);CHKERRQ(ierr); 35997f57c1a4SFlorian Wechsung ierr = PetscFree(renumbering);CHKERRQ(ierr); 36007f57c1a4SFlorian Wechsung 3601cb87ef4cSFlorian Wechsung if (failedGlobal > 0) { 36027f57c1a4SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 36037f57c1a4SFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 36047f57c1a4SFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 36057f57c1a4SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 36067f57c1a4SFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 36077f57c1a4SFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 36087f57c1a4SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 36097f57c1a4SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 36107f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 36117f57c1a4SFlorian Wechsung if (viewer) { 361206b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 361306b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 36147f57c1a4SFlorian Wechsung } 36157f57c1a4SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 36168b879b41SFlorian Wechsung PetscFunctionReturn(0); 3617cb87ef4cSFlorian Wechsung } 3618cb87ef4cSFlorian Wechsung 36197407ba93SFlorian Wechsung /*Let's check how well we did distributing points*/ 36205dc86ac1SFlorian Wechsung if (viewer) { 36217d197802SFlorian 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); 3622125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Initial. ");CHKERRQ(ierr); 3623125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr); 3624125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced. ");CHKERRQ(ierr); 3625125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 36267407ba93SFlorian Wechsung } 36277407ba93SFlorian Wechsung 3628cb87ef4cSFlorian Wechsung /* Now check that every vertex is owned by a process that it is actually connected to. */ 362941525646SFlorian Wechsung for (i=1; i<=numNonExclusivelyOwned; i++) { 3630cb87ef4cSFlorian Wechsung PetscInt loc = 0; 363141525646SFlorian Wechsung ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr); 36327407ba93SFlorian Wechsung /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */ 3633cb87ef4cSFlorian Wechsung if (loc<0) { 363441525646SFlorian Wechsung part[i] = rank; 3635cb87ef4cSFlorian Wechsung } 3636cb87ef4cSFlorian Wechsung } 3637cb87ef4cSFlorian Wechsung 36387407ba93SFlorian Wechsung /* Let's see how significant the influences of the previous fixing up step was.*/ 36395dc86ac1SFlorian Wechsung if (viewer) { 3640125d2a8fSFlorian Wechsung ierr = PetscViewerASCIIPrintf(viewer, "After. ");CHKERRQ(ierr); 3641125d2a8fSFlorian Wechsung ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr); 36427407ba93SFlorian Wechsung } 36437407ba93SFlorian Wechsung 36445dc86ac1SFlorian Wechsung ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3645cb87ef4cSFlorian Wechsung ierr = PetscFree(xadj);CHKERRQ(ierr); 3646cb87ef4cSFlorian Wechsung ierr = PetscFree(adjncy);CHKERRQ(ierr); 364741525646SFlorian Wechsung ierr = PetscFree(vtxwgt);CHKERRQ(ierr); 3648cb87ef4cSFlorian Wechsung 36497f57c1a4SFlorian Wechsung /* Almost done, now rewrite the SF to reflect the new ownership. */ 3650cf818975SFlorian Wechsung { 36517f57c1a4SFlorian Wechsung PetscInt *pointsToRewrite; 365206b3913eSFlorian Wechsung ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr); 36537f57c1a4SFlorian Wechsung counter = 0; 3654cb87ef4cSFlorian Wechsung for(i=0; i<pEnd-pStart; i++) { 3655cb87ef4cSFlorian Wechsung if (toBalance[i]) { 3656cb87ef4cSFlorian Wechsung if (isNonExclusivelyOwned[i]) { 36577f57c1a4SFlorian Wechsung pointsToRewrite[counter] = i + pStart; 3658cb87ef4cSFlorian Wechsung counter++; 3659cb87ef4cSFlorian Wechsung } 3660cb87ef4cSFlorian Wechsung } 3661cb87ef4cSFlorian Wechsung } 36627f57c1a4SFlorian Wechsung ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr); 36637f57c1a4SFlorian Wechsung ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr); 3664cf818975SFlorian Wechsung } 3665cb87ef4cSFlorian Wechsung 3666cb87ef4cSFlorian Wechsung ierr = PetscFree(toBalance);CHKERRQ(ierr); 3667cb87ef4cSFlorian Wechsung ierr = PetscFree(isLeaf);CHKERRQ(ierr); 3668cf818975SFlorian Wechsung ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr); 3669cf818975SFlorian Wechsung ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr); 36707f57c1a4SFlorian Wechsung ierr = PetscFree(part);CHKERRQ(ierr); 36715dc86ac1SFlorian Wechsung if (viewer) { 367206b3913eSFlorian Wechsung ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 367306b3913eSFlorian Wechsung ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 36747d197802SFlorian Wechsung } 36758b879b41SFlorian Wechsung if (success) *success = PETSC_TRUE; 367641525646SFlorian Wechsung ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr); 3677240408d3SFlorian Wechsung #else 36785f441e9bSFlorian Wechsung SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 367941525646SFlorian Wechsung #endif 3680cb87ef4cSFlorian Wechsung PetscFunctionReturn(0); 3681cb87ef4cSFlorian Wechsung } 3682