1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 270034214SMatthew G. Knepley 377623264SMatthew G. Knepley PetscClassId PETSCPARTITIONER_CLASSID = 0; 477623264SMatthew G. Knepley 577623264SMatthew G. Knepley PetscFunctionList PetscPartitionerList = NULL; 677623264SMatthew G. Knepley PetscBool PetscPartitionerRegisterAllCalled = PETSC_FALSE; 777623264SMatthew G. Knepley 877623264SMatthew G. Knepley PetscBool ChacoPartitionercite = PETSC_FALSE; 977623264SMatthew G. Knepley const char ChacoPartitionerCitation[] = "@inproceedings{Chaco95,\n" 1077623264SMatthew G. Knepley " author = {Bruce Hendrickson and Robert Leland},\n" 1177623264SMatthew G. Knepley " title = {A multilevel algorithm for partitioning graphs},\n" 1277623264SMatthew G. Knepley " booktitle = {Supercomputing '95: Proceedings of the 1995 ACM/IEEE Conference on Supercomputing (CDROM)}," 1377623264SMatthew G. Knepley " isbn = {0-89791-816-9},\n" 1477623264SMatthew G. Knepley " pages = {28},\n" 1577623264SMatthew G. Knepley " doi = {http://doi.acm.org/10.1145/224170.224228},\n" 1677623264SMatthew G. Knepley " publisher = {ACM Press},\n" 1777623264SMatthew G. Knepley " address = {New York},\n" 1877623264SMatthew G. Knepley " year = {1995}\n}\n"; 1977623264SMatthew G. Knepley 2077623264SMatthew G. Knepley PetscBool ParMetisPartitionercite = PETSC_FALSE; 2177623264SMatthew G. Knepley const char ParMetisPartitionerCitation[] = "@article{KarypisKumar98,\n" 2277623264SMatthew G. Knepley " author = {George Karypis and Vipin Kumar},\n" 2377623264SMatthew G. Knepley " title = {A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering},\n" 2477623264SMatthew G. Knepley " journal = {Journal of Parallel and Distributed Computing},\n" 2577623264SMatthew G. Knepley " volume = {48},\n" 2677623264SMatthew G. Knepley " pages = {71--85},\n" 2777623264SMatthew G. Knepley " year = {1998}\n}\n"; 2877623264SMatthew G. Knepley 2970034214SMatthew G. Knepley #undef __FUNCT__ 30532c4e7dSMichael Lange #define __FUNCT__ "DMPlexCreatePartitionerGraph" 31532c4e7dSMichael Lange /*@C 32532c4e7dSMichael Lange DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 33532c4e7dSMichael Lange 34532c4e7dSMichael Lange Input Parameters: 35532c4e7dSMichael Lange + dm - The mesh DM dm 36532c4e7dSMichael Lange - height - Height of the strata from which to construct the graph 37532c4e7dSMichael Lange 38532c4e7dSMichael Lange Output Parameter: 39532c4e7dSMichael Lange + numVertices - Number of vertices in the graph 40532c4e7dSMichael Lange - offsets - Point offsets in the graph 41532c4e7dSMichael Lange - adjacency - Point connectivity in the graph 42532c4e7dSMichael Lange 43532c4e7dSMichael Lange The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and 44532c4e7dSMichael Lange DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function 45532c4e7dSMichael Lange representation on the mesh. 46532c4e7dSMichael Lange 47532c4e7dSMichael Lange Level: developer 48532c4e7dSMichael Lange 49532c4e7dSMichael Lange .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure() 50532c4e7dSMichael Lange @*/ 51532c4e7dSMichael Lange PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 52532c4e7dSMichael Lange { 5343f7d02bSMichael Lange PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 54389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 558cfe4c1fSMichael Lange IS cellNumbering; 568cfe4c1fSMichael Lange const PetscInt *cellNum; 57532c4e7dSMichael Lange PetscBool useCone, useClosure; 58532c4e7dSMichael Lange PetscSection section; 59532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 608cfe4c1fSMichael Lange PetscSF sfPoint; 61532c4e7dSMichael Lange PetscMPIInt rank; 62532c4e7dSMichael Lange PetscErrorCode ierr; 63532c4e7dSMichael Lange 64532c4e7dSMichael Lange PetscFunctionBegin; 65532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 66532c4e7dSMichael Lange ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 678cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 688cfe4c1fSMichael Lange ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 69532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 70532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 71532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 72532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 73532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 74532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 75532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 76532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 77532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr); 78f0927f4eSMatthew G. Knepley ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &cellNumbering);CHKERRQ(ierr); 798cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 808cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 818cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 828cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 83532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 84532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 85532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 86532c4e7dSMichael Lange const PetscInt point = adj[a]; 87532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 88532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 89532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 90532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 91532c4e7dSMichael Lange *pBuf = point; 92532c4e7dSMichael Lange } 93532c4e7dSMichael Lange } 948cfe4c1fSMichael Lange (*numVertices)++; 95532c4e7dSMichael Lange } 96532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 97532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr); 98532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 99532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 100532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 101389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 10243f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 10343f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 10443f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 10543f7d02bSMichael Lange } 106532c4e7dSMichael Lange vOffsets[*numVertices] = size; 107532c4e7dSMichael Lange if (offsets) *offsets = vOffsets; 108389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 109bf4602e4SToby Isaac { 1108cfe4c1fSMichael Lange ISLocalToGlobalMapping ltogCells; 1118cfe4c1fSMichael Lange PetscInt n, size, *cells_arr; 1128cfe4c1fSMichael Lange /* In parallel, apply a global cell numbering to the graph */ 1138cfe4c1fSMichael Lange ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 1148cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingCreateIS(cellNumbering, <ogCells);CHKERRQ(ierr); 1158cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetSize(ltogCells, &size);CHKERRQ(ierr); 1168cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 1178cfe4c1fSMichael Lange /* Convert to positive global cell numbers */ 1188cfe4c1fSMichael Lange for (n=0; n<size; n++) {if (cells_arr[n] < 0) cells_arr[n] = -(cells_arr[n]+1);} 1198cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingRestoreIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 120389e55d8SMichael Lange ierr = ISLocalToGlobalMappingApplyBlock(ltogCells, vOffsets[*numVertices], graph, graph);CHKERRQ(ierr); 1218cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingDestroy(<ogCells);CHKERRQ(ierr); 122f0927f4eSMatthew G. Knepley ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 1238cfe4c1fSMichael Lange } 124389e55d8SMichael Lange if (adjacency) *adjacency = graph; 125532c4e7dSMichael Lange /* Clean up */ 126532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 127532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 128532c4e7dSMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 129532c4e7dSMichael Lange PetscFunctionReturn(0); 130532c4e7dSMichael Lange } 131532c4e7dSMichael Lange 132532c4e7dSMichael Lange #undef __FUNCT__ 13370034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 13470034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 13570034214SMatthew G. Knepley { 13670034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 13770034214SMatthew G. Knepley PetscInt numFaceCases = 0; 13870034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 13970034214SMatthew G. Knepley PetscInt *off, *adj; 14070034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 14170034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 14270034214SMatthew G. Knepley PetscErrorCode ierr; 14370034214SMatthew G. Knepley 14470034214SMatthew G. Knepley PetscFunctionBegin; 14570034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 146c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 14770034214SMatthew G. Knepley cellDim = dim - cellHeight; 14870034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 14970034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 15070034214SMatthew G. Knepley if (cEnd - cStart == 0) { 15170034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 15270034214SMatthew G. Knepley if (offsets) *offsets = NULL; 15370034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 15470034214SMatthew G. Knepley PetscFunctionReturn(0); 15570034214SMatthew G. Knepley } 15670034214SMatthew G. Knepley numCells = cEnd - cStart; 15770034214SMatthew G. Knepley faceDepth = depth - cellHeight; 15870034214SMatthew G. Knepley if (dim == depth) { 15970034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 16070034214SMatthew G. Knepley 16170034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 16270034214SMatthew G. Knepley /* Count neighboring cells */ 16370034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 16470034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 16570034214SMatthew G. Knepley const PetscInt *support; 16670034214SMatthew G. Knepley PetscInt supportSize; 16770034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 16870034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 16970034214SMatthew G. Knepley if (supportSize == 2) { 1709ffc88e4SToby Isaac PetscInt numChildren; 1719ffc88e4SToby Isaac 1729ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1739ffc88e4SToby Isaac if (!numChildren) { 17470034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 17570034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 17670034214SMatthew G. Knepley } 17770034214SMatthew G. Knepley } 1789ffc88e4SToby Isaac } 17970034214SMatthew G. Knepley /* Prefix sum */ 18070034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 18170034214SMatthew G. Knepley if (adjacency) { 18270034214SMatthew G. Knepley PetscInt *tmp; 18370034214SMatthew G. Knepley 18470034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 185854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 18670034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 18770034214SMatthew G. Knepley /* Get neighboring cells */ 18870034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 18970034214SMatthew G. Knepley const PetscInt *support; 19070034214SMatthew G. Knepley PetscInt supportSize; 19170034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 19270034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 19370034214SMatthew G. Knepley if (supportSize == 2) { 1949ffc88e4SToby Isaac PetscInt numChildren; 1959ffc88e4SToby Isaac 1969ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1979ffc88e4SToby Isaac if (!numChildren) { 19870034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 19970034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 20070034214SMatthew G. Knepley } 20170034214SMatthew G. Knepley } 2029ffc88e4SToby Isaac } 20370034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 20470034214SMatthew 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); 20570034214SMatthew G. Knepley #endif 20670034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 20770034214SMatthew G. Knepley } 20870034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 20970034214SMatthew G. Knepley if (offsets) *offsets = off; 21070034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 21170034214SMatthew G. Knepley PetscFunctionReturn(0); 21270034214SMatthew G. Knepley } 21370034214SMatthew G. Knepley /* Setup face recognition */ 21470034214SMatthew G. Knepley if (faceDepth == 1) { 21570034214SMatthew 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 */ 21670034214SMatthew G. Knepley 21770034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 21870034214SMatthew G. Knepley PetscInt corners; 21970034214SMatthew G. Knepley 22070034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 22170034214SMatthew G. Knepley if (!cornersSeen[corners]) { 22270034214SMatthew G. Knepley PetscInt nFV; 22370034214SMatthew G. Knepley 22470034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 22570034214SMatthew G. Knepley cornersSeen[corners] = 1; 22670034214SMatthew G. Knepley 22770034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 22870034214SMatthew G. Knepley 22970034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 23070034214SMatthew G. Knepley } 23170034214SMatthew G. Knepley } 23270034214SMatthew G. Knepley } 23370034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 23470034214SMatthew G. Knepley /* Count neighboring cells */ 23570034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 23670034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 23770034214SMatthew G. Knepley 2388b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 23970034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 24070034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 24170034214SMatthew G. Knepley PetscInt cellPair[2]; 24270034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 24370034214SMatthew G. Knepley PetscInt meetSize = 0; 24470034214SMatthew G. Knepley const PetscInt *meet = NULL; 24570034214SMatthew G. Knepley 24670034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 24770034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 24870034214SMatthew G. Knepley if (!found) { 24970034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 25070034214SMatthew G. Knepley if (meetSize) { 25170034214SMatthew G. Knepley PetscInt f; 25270034214SMatthew G. Knepley 25370034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 25470034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 25570034214SMatthew G. Knepley found = PETSC_TRUE; 25670034214SMatthew G. Knepley break; 25770034214SMatthew G. Knepley } 25870034214SMatthew G. Knepley } 25970034214SMatthew G. Knepley } 26070034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 26170034214SMatthew G. Knepley } 26270034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 26370034214SMatthew G. Knepley } 26470034214SMatthew G. Knepley } 26570034214SMatthew G. Knepley /* Prefix sum */ 26670034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 26770034214SMatthew G. Knepley 26870034214SMatthew G. Knepley if (adjacency) { 26970034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 27070034214SMatthew G. Knepley /* Get neighboring cells */ 27170034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 27270034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 27370034214SMatthew G. Knepley PetscInt cellOffset = 0; 27470034214SMatthew G. Knepley 2758b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 27670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 27770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 27870034214SMatthew G. Knepley PetscInt cellPair[2]; 27970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 28070034214SMatthew G. Knepley PetscInt meetSize = 0; 28170034214SMatthew G. Knepley const PetscInt *meet = NULL; 28270034214SMatthew G. Knepley 28370034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 28470034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 28570034214SMatthew G. Knepley if (!found) { 28670034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 28770034214SMatthew G. Knepley if (meetSize) { 28870034214SMatthew G. Knepley PetscInt f; 28970034214SMatthew G. Knepley 29070034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 29170034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 29270034214SMatthew G. Knepley found = PETSC_TRUE; 29370034214SMatthew G. Knepley break; 29470034214SMatthew G. Knepley } 29570034214SMatthew G. Knepley } 29670034214SMatthew G. Knepley } 29770034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 29870034214SMatthew G. Knepley } 29970034214SMatthew G. Knepley if (found) { 30070034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 30170034214SMatthew G. Knepley ++cellOffset; 30270034214SMatthew G. Knepley } 30370034214SMatthew G. Knepley } 30470034214SMatthew G. Knepley } 30570034214SMatthew G. Knepley } 30670034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 30770034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 30870034214SMatthew G. Knepley if (offsets) *offsets = off; 30970034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 31070034214SMatthew G. Knepley PetscFunctionReturn(0); 31170034214SMatthew G. Knepley } 31270034214SMatthew G. Knepley 31377623264SMatthew G. Knepley #undef __FUNCT__ 31477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerRegister" 31577623264SMatthew G. Knepley /*@C 31677623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 31777623264SMatthew G. Knepley 31877623264SMatthew G. Knepley Not Collective 31977623264SMatthew G. Knepley 32077623264SMatthew G. Knepley Input Parameters: 32177623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 32277623264SMatthew G. Knepley - create_func - The creation routine itself 32377623264SMatthew G. Knepley 32477623264SMatthew G. Knepley Notes: 32577623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 32677623264SMatthew G. Knepley 32777623264SMatthew G. Knepley Sample usage: 32877623264SMatthew G. Knepley .vb 32977623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 33077623264SMatthew G. Knepley .ve 33177623264SMatthew G. Knepley 33277623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 33377623264SMatthew G. Knepley .vb 33477623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 33577623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 33677623264SMatthew G. Knepley .ve 33777623264SMatthew G. Knepley or at runtime via the option 33877623264SMatthew G. Knepley .vb 33977623264SMatthew G. Knepley -petscpartitioner_type my_part 34077623264SMatthew G. Knepley .ve 34177623264SMatthew G. Knepley 34277623264SMatthew G. Knepley Level: advanced 34377623264SMatthew G. Knepley 34477623264SMatthew G. Knepley .keywords: PetscPartitioner, register 34577623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 34677623264SMatthew G. Knepley 34777623264SMatthew G. Knepley @*/ 34877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 34977623264SMatthew G. Knepley { 35077623264SMatthew G. Knepley PetscErrorCode ierr; 35177623264SMatthew G. Knepley 35277623264SMatthew G. Knepley PetscFunctionBegin; 35377623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 35477623264SMatthew G. Knepley PetscFunctionReturn(0); 35577623264SMatthew G. Knepley } 35677623264SMatthew G. Knepley 35777623264SMatthew G. Knepley #undef __FUNCT__ 35877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetType" 35977623264SMatthew G. Knepley /*@C 36077623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 36177623264SMatthew G. Knepley 36277623264SMatthew G. Knepley Collective on PetscPartitioner 36377623264SMatthew G. Knepley 36477623264SMatthew G. Knepley Input Parameters: 36577623264SMatthew G. Knepley + part - The PetscPartitioner object 36677623264SMatthew G. Knepley - name - The kind of partitioner 36777623264SMatthew G. Knepley 36877623264SMatthew G. Knepley Options Database Key: 36977623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 37077623264SMatthew G. Knepley 37177623264SMatthew G. Knepley Level: intermediate 37277623264SMatthew G. Knepley 37377623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 37477623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 37577623264SMatthew G. Knepley @*/ 37677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 37777623264SMatthew G. Knepley { 37877623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 37977623264SMatthew G. Knepley PetscBool match; 38077623264SMatthew G. Knepley PetscErrorCode ierr; 38177623264SMatthew G. Knepley 38277623264SMatthew G. Knepley PetscFunctionBegin; 38377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 38477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 38577623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 38677623264SMatthew G. Knepley 3870f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 38877623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 38977623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 39077623264SMatthew G. Knepley 39177623264SMatthew G. Knepley if (part->ops->destroy) { 39277623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 39377623264SMatthew G. Knepley part->ops->destroy = NULL; 39477623264SMatthew G. Knepley } 39577623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 39677623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 39777623264SMatthew G. Knepley PetscFunctionReturn(0); 39877623264SMatthew G. Knepley } 39977623264SMatthew G. Knepley 40077623264SMatthew G. Knepley #undef __FUNCT__ 40177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerGetType" 40277623264SMatthew G. Knepley /*@C 40377623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 40477623264SMatthew G. Knepley 40577623264SMatthew G. Knepley Not Collective 40677623264SMatthew G. Knepley 40777623264SMatthew G. Knepley Input Parameter: 40877623264SMatthew G. Knepley . part - The PetscPartitioner 40977623264SMatthew G. Knepley 41077623264SMatthew G. Knepley Output Parameter: 41177623264SMatthew G. Knepley . name - The PetscPartitioner type name 41277623264SMatthew G. Knepley 41377623264SMatthew G. Knepley Level: intermediate 41477623264SMatthew G. Knepley 41577623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 41677623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 41777623264SMatthew G. Knepley @*/ 41877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 41977623264SMatthew G. Knepley { 42077623264SMatthew G. Knepley PetscErrorCode ierr; 42177623264SMatthew G. Knepley 42277623264SMatthew G. Knepley PetscFunctionBegin; 42377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 42477623264SMatthew G. Knepley PetscValidPointer(name, 2); 4250f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 42677623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 42777623264SMatthew G. Knepley PetscFunctionReturn(0); 42877623264SMatthew G. Knepley } 42977623264SMatthew G. Knepley 43077623264SMatthew G. Knepley #undef __FUNCT__ 43177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView" 43277623264SMatthew G. Knepley /*@C 43377623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 43477623264SMatthew G. Knepley 43577623264SMatthew G. Knepley Collective on PetscPartitioner 43677623264SMatthew G. Knepley 43777623264SMatthew G. Knepley Input Parameter: 43877623264SMatthew G. Knepley + part - the PetscPartitioner object to view 43977623264SMatthew G. Knepley - v - the viewer 44077623264SMatthew G. Knepley 44177623264SMatthew G. Knepley Level: developer 44277623264SMatthew G. Knepley 44377623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 44477623264SMatthew G. Knepley @*/ 44577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 44677623264SMatthew G. Knepley { 44777623264SMatthew G. Knepley PetscErrorCode ierr; 44877623264SMatthew G. Knepley 44977623264SMatthew G. Knepley PetscFunctionBegin; 45077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 45177623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 45277623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 45377623264SMatthew G. Knepley PetscFunctionReturn(0); 45477623264SMatthew G. Knepley } 45577623264SMatthew G. Knepley 45677623264SMatthew G. Knepley #undef __FUNCT__ 45777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetTypeFromOptions_Internal" 45877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetTypeFromOptions_Internal(PetscPartitioner part) 45977623264SMatthew G. Knepley { 46077623264SMatthew G. Knepley const char *defaultType; 46177623264SMatthew G. Knepley char name[256]; 46277623264SMatthew G. Knepley PetscBool flg; 46377623264SMatthew G. Knepley PetscErrorCode ierr; 46477623264SMatthew G. Knepley 46577623264SMatthew G. Knepley PetscFunctionBegin; 46677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 467*7cf71cfdSLisandro Dalcin if (!((PetscObject) part)->type_name) 468*7cf71cfdSLisandro Dalcin #if defined(PETSC_HAVE_CHACO) 469*7cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERCHACO; 470*7cf71cfdSLisandro Dalcin #elif defined(PETSC_HAVE_PARMETIS) 471*7cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERPARMETIS; 472*7cf71cfdSLisandro Dalcin #else 473*7cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERSIMPLE; 474*7cf71cfdSLisandro Dalcin #endif 475*7cf71cfdSLisandro Dalcin else 476*7cf71cfdSLisandro Dalcin defaultType = ((PetscObject) part)->type_name; 4770f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 47877623264SMatthew G. Knepley 47977623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 48077623264SMatthew G. Knepley ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, 256, &flg);CHKERRQ(ierr); 48177623264SMatthew G. Knepley if (flg) { 48277623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 48377623264SMatthew G. Knepley } else if (!((PetscObject) part)->type_name) { 48477623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 48577623264SMatthew G. Knepley } 48677623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 48777623264SMatthew G. Knepley PetscFunctionReturn(0); 48877623264SMatthew G. Knepley } 48977623264SMatthew G. Knepley 49077623264SMatthew G. Knepley #undef __FUNCT__ 49177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions" 49277623264SMatthew G. Knepley /*@ 49377623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 49477623264SMatthew G. Knepley 49577623264SMatthew G. Knepley Collective on PetscPartitioner 49677623264SMatthew G. Knepley 49777623264SMatthew G. Knepley Input Parameter: 49877623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 49977623264SMatthew G. Knepley 50077623264SMatthew G. Knepley Level: developer 50177623264SMatthew G. Knepley 50277623264SMatthew G. Knepley .seealso: PetscPartitionerView() 50377623264SMatthew G. Knepley @*/ 50477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 50577623264SMatthew G. Knepley { 50677623264SMatthew G. Knepley PetscErrorCode ierr; 50777623264SMatthew G. Knepley 50877623264SMatthew G. Knepley PetscFunctionBegin; 50977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 51077623264SMatthew G. Knepley ierr = PetscPartitionerSetTypeFromOptions_Internal(part);CHKERRQ(ierr); 51177623264SMatthew G. Knepley 51277623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 51377623264SMatthew G. Knepley if (part->ops->setfromoptions) {ierr = (*part->ops->setfromoptions)(part);CHKERRQ(ierr);} 51477623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 5150633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 51677623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 51777623264SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 51877623264SMatthew G. Knepley PetscFunctionReturn(0); 51977623264SMatthew G. Knepley } 52077623264SMatthew G. Knepley 52177623264SMatthew G. Knepley #undef __FUNCT__ 52277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetUp" 52377623264SMatthew G. Knepley /*@C 52477623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 52577623264SMatthew G. Knepley 52677623264SMatthew G. Knepley Collective on PetscPartitioner 52777623264SMatthew G. Knepley 52877623264SMatthew G. Knepley Input Parameter: 52977623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 53077623264SMatthew G. Knepley 53177623264SMatthew G. Knepley Level: developer 53277623264SMatthew G. Knepley 53377623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 53477623264SMatthew G. Knepley @*/ 53577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 53677623264SMatthew G. Knepley { 53777623264SMatthew G. Knepley PetscErrorCode ierr; 53877623264SMatthew G. Knepley 53977623264SMatthew G. Knepley PetscFunctionBegin; 54077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 54177623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 54277623264SMatthew G. Knepley PetscFunctionReturn(0); 54377623264SMatthew G. Knepley } 54477623264SMatthew G. Knepley 54577623264SMatthew G. Knepley #undef __FUNCT__ 54677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy" 54777623264SMatthew G. Knepley /*@ 54877623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 54977623264SMatthew G. Knepley 55077623264SMatthew G. Knepley Collective on PetscPartitioner 55177623264SMatthew G. Knepley 55277623264SMatthew G. Knepley Input Parameter: 55377623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 55477623264SMatthew G. Knepley 55577623264SMatthew G. Knepley Level: developer 55677623264SMatthew G. Knepley 55777623264SMatthew G. Knepley .seealso: PetscPartitionerView() 55877623264SMatthew G. Knepley @*/ 55977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 56077623264SMatthew G. Knepley { 56177623264SMatthew G. Knepley PetscErrorCode ierr; 56277623264SMatthew G. Knepley 56377623264SMatthew G. Knepley PetscFunctionBegin; 56477623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 56577623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 56677623264SMatthew G. Knepley 56777623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 56877623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 56977623264SMatthew G. Knepley 57077623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 57177623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 57277623264SMatthew G. Knepley PetscFunctionReturn(0); 57377623264SMatthew G. Knepley } 57477623264SMatthew G. Knepley 57577623264SMatthew G. Knepley #undef __FUNCT__ 57677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate" 57777623264SMatthew G. Knepley /*@ 57877623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 57977623264SMatthew G. Knepley 58077623264SMatthew G. Knepley Collective on MPI_Comm 58177623264SMatthew G. Knepley 58277623264SMatthew G. Knepley Input Parameter: 58377623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 58477623264SMatthew G. Knepley 58577623264SMatthew G. Knepley Output Parameter: 58677623264SMatthew G. Knepley . part - The PetscPartitioner object 58777623264SMatthew G. Knepley 58877623264SMatthew G. Knepley Level: beginner 58977623264SMatthew G. Knepley 590dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 59177623264SMatthew G. Knepley @*/ 59277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 59377623264SMatthew G. Knepley { 59477623264SMatthew G. Knepley PetscPartitioner p; 59577623264SMatthew G. Knepley PetscErrorCode ierr; 59677623264SMatthew G. Knepley 59777623264SMatthew G. Knepley PetscFunctionBegin; 59877623264SMatthew G. Knepley PetscValidPointer(part, 2); 59977623264SMatthew G. Knepley *part = NULL; 60077623264SMatthew G. Knepley ierr = PetscFVInitializePackage();CHKERRQ(ierr); 60177623264SMatthew G. Knepley 60273107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 60377623264SMatthew G. Knepley 60477623264SMatthew G. Knepley *part = p; 60577623264SMatthew G. Knepley PetscFunctionReturn(0); 60677623264SMatthew G. Knepley } 60777623264SMatthew G. Knepley 60877623264SMatthew G. Knepley #undef __FUNCT__ 60977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition" 61077623264SMatthew G. Knepley /*@ 61177623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 61277623264SMatthew G. Knepley 61377623264SMatthew G. Knepley Collective on DM 61477623264SMatthew G. Knepley 61577623264SMatthew G. Knepley Input Parameters: 61677623264SMatthew G. Knepley + part - The PetscPartitioner 617f8987ae8SMichael Lange - dm - The mesh DM 61877623264SMatthew G. Knepley 61977623264SMatthew G. Knepley Output Parameters: 62077623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 621f8987ae8SMichael Lange - partition - The list of points by partition 62277623264SMatthew G. Knepley 62377623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 62477623264SMatthew G. Knepley 62577623264SMatthew G. Knepley Level: developer 62677623264SMatthew G. Knepley 62777623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 6284b15ede2SMatthew G. Knepley @*/ 629f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 63077623264SMatthew G. Knepley { 63177623264SMatthew G. Knepley PetscMPIInt size; 63277623264SMatthew G. Knepley PetscErrorCode ierr; 63377623264SMatthew G. Knepley 63477623264SMatthew G. Knepley PetscFunctionBegin; 63577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 63677623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 63777623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 63877623264SMatthew G. Knepley PetscValidPointer(partition, 5); 63977623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 64077623264SMatthew G. Knepley if (size == 1) { 64177623264SMatthew G. Knepley PetscInt *points; 64277623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 64377623264SMatthew G. Knepley 64477623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 64577623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 64677623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 64777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 64877623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 64977623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 65077623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 65177623264SMatthew G. Knepley PetscFunctionReturn(0); 65277623264SMatthew G. Knepley } 65377623264SMatthew G. Knepley if (part->height == 0) { 65477623264SMatthew G. Knepley PetscInt numVertices; 65577623264SMatthew G. Knepley PetscInt *start = NULL; 65677623264SMatthew G. Knepley PetscInt *adjacency = NULL; 65777623264SMatthew G. Knepley 658532c4e7dSMichael Lange ierr = DMPlexCreatePartitionerGraph(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 65977623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 66077623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 66177623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 66277623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 66377623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 66477623264SMatthew G. Knepley PetscFunctionReturn(0); 66577623264SMatthew G. Knepley } 66677623264SMatthew G. Knepley 66777623264SMatthew G. Knepley #undef __FUNCT__ 66877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Shell" 66977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 67077623264SMatthew G. Knepley { 67177623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 67277623264SMatthew G. Knepley PetscErrorCode ierr; 67377623264SMatthew G. Knepley 67477623264SMatthew G. Knepley PetscFunctionBegin; 67577623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 67677623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 67777623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 67877623264SMatthew G. Knepley PetscFunctionReturn(0); 67977623264SMatthew G. Knepley } 68077623264SMatthew G. Knepley 68177623264SMatthew G. Knepley #undef __FUNCT__ 68277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell_Ascii" 68377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 68477623264SMatthew G. Knepley { 68577623264SMatthew G. Knepley PetscViewerFormat format; 68677623264SMatthew G. Knepley PetscErrorCode ierr; 68777623264SMatthew G. Knepley 68877623264SMatthew G. Knepley PetscFunctionBegin; 68977623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 69077623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Shell Graph Partitioner:\n");CHKERRQ(ierr); 69177623264SMatthew G. Knepley PetscFunctionReturn(0); 69277623264SMatthew G. Knepley } 69377623264SMatthew G. Knepley 69477623264SMatthew G. Knepley #undef __FUNCT__ 69577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell" 69677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 69777623264SMatthew G. Knepley { 69877623264SMatthew G. Knepley PetscBool iascii; 69977623264SMatthew G. Knepley PetscErrorCode ierr; 70077623264SMatthew G. Knepley 70177623264SMatthew G. Knepley PetscFunctionBegin; 70277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 70377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 70477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 70577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 70677623264SMatthew G. Knepley PetscFunctionReturn(0); 70777623264SMatthew G. Knepley } 70877623264SMatthew G. Knepley 70977623264SMatthew G. Knepley #undef __FUNCT__ 71077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Shell" 71177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 71277623264SMatthew G. Knepley { 71377623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 71477623264SMatthew G. Knepley PetscInt np; 71577623264SMatthew G. Knepley PetscErrorCode ierr; 71677623264SMatthew G. Knepley 71777623264SMatthew G. Knepley PetscFunctionBegin; 71877623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 71977623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 72077623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 72177623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 7225680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 72377623264SMatthew G. Knepley *partition = p->partition; 72477623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 72577623264SMatthew G. Knepley PetscFunctionReturn(0); 72677623264SMatthew G. Knepley } 72777623264SMatthew G. Knepley 72877623264SMatthew G. Knepley #undef __FUNCT__ 72977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Shell" 73077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 73177623264SMatthew G. Knepley { 73277623264SMatthew G. Knepley PetscFunctionBegin; 73377623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 73477623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 73577623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 73677623264SMatthew G. Knepley PetscFunctionReturn(0); 73777623264SMatthew G. Knepley } 73877623264SMatthew G. Knepley 73977623264SMatthew G. Knepley /*MC 74077623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 74177623264SMatthew G. Knepley 74277623264SMatthew G. Knepley Level: intermediate 74377623264SMatthew G. Knepley 74477623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 74577623264SMatthew G. Knepley M*/ 74677623264SMatthew G. Knepley 74777623264SMatthew G. Knepley #undef __FUNCT__ 74877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Shell" 74977623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 75077623264SMatthew G. Knepley { 75177623264SMatthew G. Knepley PetscPartitioner_Shell *p; 75277623264SMatthew G. Knepley PetscErrorCode ierr; 75377623264SMatthew G. Knepley 75477623264SMatthew G. Knepley PetscFunctionBegin; 75577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 75677623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 75777623264SMatthew G. Knepley part->data = p; 75877623264SMatthew G. Knepley 75977623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 76077623264SMatthew G. Knepley PetscFunctionReturn(0); 76177623264SMatthew G. Knepley } 76277623264SMatthew G. Knepley 76377623264SMatthew G. Knepley #undef __FUNCT__ 7645680f57bSMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellSetPartition" 7655680f57bSMatthew G. Knepley /*@C 7665680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 7675680f57bSMatthew G. Knepley 768b7e49471SLawrence Mitchell Collective on PART 7695680f57bSMatthew G. Knepley 7705680f57bSMatthew G. Knepley Input Parameters: 7715680f57bSMatthew G. Knepley + part - The PetscPartitioner 772b7e49471SLawrence Mitchell . numProcs - The number of partitions 773b7e49471SLawrence Mitchell . sizes - array of size numProcs (or NULL) providing the number of points in each partition 774b7e49471SLawrence Mitchell - points - array of size sum(sizes) (may be NULL iff sizes is NULL) providing the partition each point belongs to 7755680f57bSMatthew G. Knepley 7765680f57bSMatthew G. Knepley Level: developer 7775680f57bSMatthew G. Knepley 778b7e49471SLawrence Mitchell Notes: 779b7e49471SLawrence Mitchell 780b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 781b7e49471SLawrence Mitchell 7825680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 7835680f57bSMatthew G. Knepley @*/ 7845680f57bSMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt numProcs, const PetscInt sizes[], const PetscInt points[]) 7855680f57bSMatthew G. Knepley { 7865680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 7875680f57bSMatthew G. Knepley PetscInt proc, numPoints; 7885680f57bSMatthew G. Knepley PetscErrorCode ierr; 7895680f57bSMatthew G. Knepley 7905680f57bSMatthew G. Knepley PetscFunctionBegin; 7915680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 7925680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 7935680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(points, 4);} 7945680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 7955680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 7965680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 7975680f57bSMatthew G. Knepley ierr = PetscSectionSetChart(p->section, 0, numProcs);CHKERRQ(ierr); 7985680f57bSMatthew G. Knepley if (sizes) { 7995680f57bSMatthew G. Knepley for (proc = 0; proc < numProcs; ++proc) { 8005680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 8015680f57bSMatthew G. Knepley } 8025680f57bSMatthew G. Knepley } 8035680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 8045680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 8055680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 8065680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8075680f57bSMatthew G. Knepley } 8085680f57bSMatthew G. Knepley 8095680f57bSMatthew G. Knepley #undef __FUNCT__ 810555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Simple" 811555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 812555a9cf8SMatthew G. Knepley { 813555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 814555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 815555a9cf8SMatthew G. Knepley 816555a9cf8SMatthew G. Knepley PetscFunctionBegin; 817555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 818555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 819555a9cf8SMatthew G. Knepley } 820555a9cf8SMatthew G. Knepley 821555a9cf8SMatthew G. Knepley #undef __FUNCT__ 822555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Simple_Ascii" 823555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 824555a9cf8SMatthew G. Knepley { 825555a9cf8SMatthew G. Knepley PetscViewerFormat format; 826555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 827555a9cf8SMatthew G. Knepley 828555a9cf8SMatthew G. Knepley PetscFunctionBegin; 829555a9cf8SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 830555a9cf8SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Simple Graph Partitioner:\n");CHKERRQ(ierr); 831555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 832555a9cf8SMatthew G. Knepley } 833555a9cf8SMatthew G. Knepley 834555a9cf8SMatthew G. Knepley #undef __FUNCT__ 835555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Simple" 836555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 837555a9cf8SMatthew G. Knepley { 838555a9cf8SMatthew G. Knepley PetscBool iascii; 839555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 840555a9cf8SMatthew G. Knepley 841555a9cf8SMatthew G. Knepley PetscFunctionBegin; 842555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 843555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 844555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 845555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 846555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 847555a9cf8SMatthew G. Knepley } 848555a9cf8SMatthew G. Knepley 849555a9cf8SMatthew G. Knepley #undef __FUNCT__ 850555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Simple" 851555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 852555a9cf8SMatthew G. Knepley { 853cead94edSToby Isaac MPI_Comm comm; 854555a9cf8SMatthew G. Knepley PetscInt np; 855cead94edSToby Isaac PetscMPIInt size; 856555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 857555a9cf8SMatthew G. Knepley 858555a9cf8SMatthew G. Knepley PetscFunctionBegin; 859cead94edSToby Isaac comm = PetscObjectComm((PetscObject)dm); 860cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 861555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 862555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 863cead94edSToby Isaac if (size == 1) { 864cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 865cead94edSToby Isaac } 866cead94edSToby Isaac else { 867cead94edSToby Isaac PetscMPIInt rank; 868cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 869cead94edSToby Isaac 870a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 871cead94edSToby Isaac offsets[0] = 0; 872cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 873cead94edSToby Isaac for (np = 2; np <= size; np++) { 874cead94edSToby Isaac offsets[np] += offsets[np-1]; 875cead94edSToby Isaac } 876cead94edSToby Isaac nvGlobal = offsets[size]; 877cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 878cead94edSToby Isaac myFirst = offsets[rank]; 879cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 880cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 881cead94edSToby Isaac if (numVertices) { 882cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 883cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 884cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 885cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 886cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 887cead94edSToby Isaac 888cead94edSToby Isaac 889cead94edSToby Isaac if (rem) { 890cead94edSToby Isaac firstLargePart = myFirst / pBig; 891cead94edSToby Isaac lastLargePart = myLast / pBig; 892cead94edSToby Isaac 893cead94edSToby Isaac if (firstLargePart < rem) { 894cead94edSToby Isaac firstPart = firstLargePart; 895cead94edSToby Isaac } 896cead94edSToby Isaac else { 897cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 898cead94edSToby Isaac } 899cead94edSToby Isaac if (lastLargePart < rem) { 900cead94edSToby Isaac lastPart = lastLargePart; 901cead94edSToby Isaac } 902cead94edSToby Isaac else { 903cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 904cead94edSToby Isaac } 905cead94edSToby Isaac } 906cead94edSToby Isaac else { 907cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 908cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 909cead94edSToby Isaac } 910cead94edSToby Isaac 911cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 912cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 913cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 914cead94edSToby Isaac 915cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 916cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 917cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 918cead94edSToby Isaac } 919cead94edSToby Isaac } 920cead94edSToby Isaac } 921cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 922555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 923555a9cf8SMatthew G. Knepley } 924555a9cf8SMatthew G. Knepley 925555a9cf8SMatthew G. Knepley #undef __FUNCT__ 926555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Simple" 927555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 928555a9cf8SMatthew G. Knepley { 929555a9cf8SMatthew G. Knepley PetscFunctionBegin; 930555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 931555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 932555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 933555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 934555a9cf8SMatthew G. Knepley } 935555a9cf8SMatthew G. Knepley 936555a9cf8SMatthew G. Knepley /*MC 937555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 938555a9cf8SMatthew G. Knepley 939555a9cf8SMatthew G. Knepley Level: intermediate 940555a9cf8SMatthew G. Knepley 941555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 942555a9cf8SMatthew G. Knepley M*/ 943555a9cf8SMatthew G. Knepley 944555a9cf8SMatthew G. Knepley #undef __FUNCT__ 945555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Simple" 946555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 947555a9cf8SMatthew G. Knepley { 948555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 949555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 950555a9cf8SMatthew G. Knepley 951555a9cf8SMatthew G. Knepley PetscFunctionBegin; 952555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 953555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 954555a9cf8SMatthew G. Knepley part->data = p; 955555a9cf8SMatthew G. Knepley 956555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 957555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 958555a9cf8SMatthew G. Knepley } 959555a9cf8SMatthew G. Knepley 960555a9cf8SMatthew G. Knepley #undef __FUNCT__ 961dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerDestroy_Gather" 962dae52e14SToby Isaac PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 963dae52e14SToby Isaac { 964dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 965dae52e14SToby Isaac PetscErrorCode ierr; 966dae52e14SToby Isaac 967dae52e14SToby Isaac PetscFunctionBegin; 968dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 969dae52e14SToby Isaac PetscFunctionReturn(0); 970dae52e14SToby Isaac } 971dae52e14SToby Isaac 972dae52e14SToby Isaac #undef __FUNCT__ 973dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerView_Gather_Ascii" 974dae52e14SToby Isaac PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 975dae52e14SToby Isaac { 976dae52e14SToby Isaac PetscViewerFormat format; 977dae52e14SToby Isaac PetscErrorCode ierr; 978dae52e14SToby Isaac 979dae52e14SToby Isaac PetscFunctionBegin; 980dae52e14SToby Isaac ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 981dae52e14SToby Isaac ierr = PetscViewerASCIIPrintf(viewer, "Gather Graph Partitioner:\n");CHKERRQ(ierr); 982dae52e14SToby Isaac PetscFunctionReturn(0); 983dae52e14SToby Isaac } 984dae52e14SToby Isaac 985dae52e14SToby Isaac #undef __FUNCT__ 986dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerView_Gather" 987dae52e14SToby Isaac PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 988dae52e14SToby Isaac { 989dae52e14SToby Isaac PetscBool iascii; 990dae52e14SToby Isaac PetscErrorCode ierr; 991dae52e14SToby Isaac 992dae52e14SToby Isaac PetscFunctionBegin; 993dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 994dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 995dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 996dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 997dae52e14SToby Isaac PetscFunctionReturn(0); 998dae52e14SToby Isaac } 999dae52e14SToby Isaac 1000dae52e14SToby Isaac #undef __FUNCT__ 1001dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerPartition_Gather" 1002dae52e14SToby Isaac PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1003dae52e14SToby Isaac { 1004dae52e14SToby Isaac PetscInt np; 1005dae52e14SToby Isaac PetscErrorCode ierr; 1006dae52e14SToby Isaac 1007dae52e14SToby Isaac PetscFunctionBegin; 1008dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1009dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1010dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1011dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1012dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1013dae52e14SToby Isaac PetscFunctionReturn(0); 1014dae52e14SToby Isaac } 1015dae52e14SToby Isaac 1016dae52e14SToby Isaac #undef __FUNCT__ 1017dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerInitialize_Gather" 1018dae52e14SToby Isaac PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1019dae52e14SToby Isaac { 1020dae52e14SToby Isaac PetscFunctionBegin; 1021dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1022dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1023dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1024dae52e14SToby Isaac PetscFunctionReturn(0); 1025dae52e14SToby Isaac } 1026dae52e14SToby Isaac 1027dae52e14SToby Isaac /*MC 1028dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1029dae52e14SToby Isaac 1030dae52e14SToby Isaac Level: intermediate 1031dae52e14SToby Isaac 1032dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1033dae52e14SToby Isaac M*/ 1034dae52e14SToby Isaac 1035dae52e14SToby Isaac #undef __FUNCT__ 1036dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerCreate_Gather" 1037dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1038dae52e14SToby Isaac { 1039dae52e14SToby Isaac PetscPartitioner_Gather *p; 1040dae52e14SToby Isaac PetscErrorCode ierr; 1041dae52e14SToby Isaac 1042dae52e14SToby Isaac PetscFunctionBegin; 1043dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1044dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1045dae52e14SToby Isaac part->data = p; 1046dae52e14SToby Isaac 1047dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1048dae52e14SToby Isaac PetscFunctionReturn(0); 1049dae52e14SToby Isaac } 1050dae52e14SToby Isaac 1051dae52e14SToby Isaac 1052dae52e14SToby Isaac #undef __FUNCT__ 105377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Chaco" 105477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 105577623264SMatthew G. Knepley { 105677623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 105777623264SMatthew G. Knepley PetscErrorCode ierr; 105877623264SMatthew G. Knepley 105977623264SMatthew G. Knepley PetscFunctionBegin; 106077623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 106177623264SMatthew G. Knepley PetscFunctionReturn(0); 106277623264SMatthew G. Knepley } 106377623264SMatthew G. Knepley 106477623264SMatthew G. Knepley #undef __FUNCT__ 106577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco_Ascii" 106677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 106777623264SMatthew G. Knepley { 106877623264SMatthew G. Knepley PetscViewerFormat format; 106977623264SMatthew G. Knepley PetscErrorCode ierr; 107077623264SMatthew G. Knepley 107177623264SMatthew G. Knepley PetscFunctionBegin; 107277623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 107377623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Chaco Graph Partitioner:\n");CHKERRQ(ierr); 107477623264SMatthew G. Knepley PetscFunctionReturn(0); 107577623264SMatthew G. Knepley } 107677623264SMatthew G. Knepley 107777623264SMatthew G. Knepley #undef __FUNCT__ 107877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco" 107977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 108077623264SMatthew G. Knepley { 108177623264SMatthew G. Knepley PetscBool iascii; 108277623264SMatthew G. Knepley PetscErrorCode ierr; 108377623264SMatthew G. Knepley 108477623264SMatthew G. Knepley PetscFunctionBegin; 108577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 108677623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 108777623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 108877623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 108977623264SMatthew G. Knepley PetscFunctionReturn(0); 109077623264SMatthew G. Knepley } 109177623264SMatthew G. Knepley 109270034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 109370034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 109470034214SMatthew G. Knepley #include <unistd.h> 109570034214SMatthew G. Knepley #endif 109670034214SMatthew G. Knepley /* Chaco does not have an include file */ 109770034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 109870034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 109970034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 110070034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 110170034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 110270034214SMatthew G. Knepley 110370034214SMatthew G. Knepley extern int FREE_GRAPH; 110477623264SMatthew G. Knepley #endif 110570034214SMatthew G. Knepley 110670034214SMatthew G. Knepley #undef __FUNCT__ 110777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Chaco" 110877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 110970034214SMatthew G. Knepley { 111077623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 111170034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 111270034214SMatthew G. Knepley MPI_Comm comm; 111370034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 111470034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 111570034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 111670034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 111770034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 111870034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 111970034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 112070034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 112170034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 112270034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 112370034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 112470034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 112570034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 112670034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 112770034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 112870034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 112970034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 113070034214SMatthew G. Knepley short int *assignment; /* Output partition */ 113170034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 113270034214SMatthew G. Knepley PetscInt *points; 113370034214SMatthew G. Knepley int i, v, p; 113470034214SMatthew G. Knepley PetscErrorCode ierr; 113570034214SMatthew G. Knepley 113670034214SMatthew G. Knepley PetscFunctionBegin; 113770034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 113870034214SMatthew G. Knepley if (!numVertices) { 113977623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 114077623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 114170034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 114270034214SMatthew G. Knepley PetscFunctionReturn(0); 114370034214SMatthew G. Knepley } 114470034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 114570034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 114670034214SMatthew G. Knepley 114770034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 114870034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 114970034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 115070034214SMatthew G. Knepley } 115177623264SMatthew G. Knepley mesh_dims[0] = nparts; 115270034214SMatthew G. Knepley mesh_dims[1] = 1; 115370034214SMatthew G. Knepley mesh_dims[2] = 1; 115470034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 115570034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 115670034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 115770034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 115870034214SMatthew G. Knepley { 115970034214SMatthew G. Knepley int piperet; 116070034214SMatthew G. Knepley piperet = pipe(fd_pipe); 116170034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 116270034214SMatthew G. Knepley fd_stdout = dup(1); 116370034214SMatthew G. Knepley close(1); 116470034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 116570034214SMatthew G. Knepley } 116670034214SMatthew G. Knepley #endif 116770034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 116870034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 116970034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 117070034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 117170034214SMatthew G. Knepley { 117270034214SMatthew G. Knepley char msgLog[10000]; 117370034214SMatthew G. Knepley int count; 117470034214SMatthew G. Knepley 117570034214SMatthew G. Knepley fflush(stdout); 117670034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 117770034214SMatthew G. Knepley if (count < 0) count = 0; 117870034214SMatthew G. Knepley msgLog[count] = 0; 117970034214SMatthew G. Knepley close(1); 118070034214SMatthew G. Knepley dup2(fd_stdout, 1); 118170034214SMatthew G. Knepley close(fd_stdout); 118270034214SMatthew G. Knepley close(fd_pipe[0]); 118370034214SMatthew G. Knepley close(fd_pipe[1]); 118470034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 118570034214SMatthew G. Knepley } 118670034214SMatthew G. Knepley #endif 118770034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 118877623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 118970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 119077623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 119170034214SMatthew G. Knepley } 119277623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 119370034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 119477623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 119570034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 119670034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 119770034214SMatthew G. Knepley } 119870034214SMatthew G. Knepley } 119970034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 120070034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 120170034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 120270034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 120370034214SMatthew G. Knepley } 120470034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 120570034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 120670034214SMatthew G. Knepley PetscFunctionReturn(0); 120777623264SMatthew G. Knepley #else 120877623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 120970034214SMatthew G. Knepley #endif 121077623264SMatthew G. Knepley } 121177623264SMatthew G. Knepley 121277623264SMatthew G. Knepley #undef __FUNCT__ 121377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Chaco" 121477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 121577623264SMatthew G. Knepley { 121677623264SMatthew G. Knepley PetscFunctionBegin; 121777623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 121877623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 121977623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 122077623264SMatthew G. Knepley PetscFunctionReturn(0); 122177623264SMatthew G. Knepley } 122277623264SMatthew G. Knepley 122377623264SMatthew G. Knepley /*MC 122477623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 122577623264SMatthew G. Knepley 122677623264SMatthew G. Knepley Level: intermediate 122777623264SMatthew G. Knepley 122877623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 122977623264SMatthew G. Knepley M*/ 123077623264SMatthew G. Knepley 123177623264SMatthew G. Knepley #undef __FUNCT__ 123277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Chaco" 123377623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 123477623264SMatthew G. Knepley { 123577623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 123677623264SMatthew G. Knepley PetscErrorCode ierr; 123777623264SMatthew G. Knepley 123877623264SMatthew G. Knepley PetscFunctionBegin; 123977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 124077623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 124177623264SMatthew G. Knepley part->data = p; 124277623264SMatthew G. Knepley 124377623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 124477623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 124577623264SMatthew G. Knepley PetscFunctionReturn(0); 124677623264SMatthew G. Knepley } 124777623264SMatthew G. Knepley 124877623264SMatthew G. Knepley #undef __FUNCT__ 124977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_ParMetis" 125077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 125177623264SMatthew G. Knepley { 125277623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 125377623264SMatthew G. Knepley PetscErrorCode ierr; 125477623264SMatthew G. Knepley 125577623264SMatthew G. Knepley PetscFunctionBegin; 125677623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 125777623264SMatthew G. Knepley PetscFunctionReturn(0); 125877623264SMatthew G. Knepley } 125977623264SMatthew G. Knepley 126077623264SMatthew G. Knepley #undef __FUNCT__ 126177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis_Ascii" 126277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 126377623264SMatthew G. Knepley { 126477623264SMatthew G. Knepley PetscViewerFormat format; 126577623264SMatthew G. Knepley PetscErrorCode ierr; 126677623264SMatthew G. Knepley 126777623264SMatthew G. Knepley PetscFunctionBegin; 126877623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126977623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis Graph Partitioner:\n");CHKERRQ(ierr); 127077623264SMatthew G. Knepley PetscFunctionReturn(0); 127177623264SMatthew G. Knepley } 127277623264SMatthew G. Knepley 127377623264SMatthew G. Knepley #undef __FUNCT__ 127477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis" 127577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 127677623264SMatthew G. Knepley { 127777623264SMatthew G. Knepley PetscBool iascii; 127877623264SMatthew G. Knepley PetscErrorCode ierr; 127977623264SMatthew G. Knepley 128077623264SMatthew G. Knepley PetscFunctionBegin; 128177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 128277623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 128377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 128477623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 128577623264SMatthew G. Knepley PetscFunctionReturn(0); 128677623264SMatthew G. Knepley } 128770034214SMatthew G. Knepley 128870034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 128970034214SMatthew G. Knepley #include <parmetis.h> 129077623264SMatthew G. Knepley #endif 129170034214SMatthew G. Knepley 129270034214SMatthew G. Knepley #undef __FUNCT__ 129377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_ParMetis" 129477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 129570034214SMatthew G. Knepley { 129677623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 129770034214SMatthew G. Knepley MPI_Comm comm; 129870034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 129970034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 130070034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 130170034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 130270034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 130370034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 130470034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 130570034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 130670034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 130770034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 130870034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 130970034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 131070034214SMatthew G. Knepley /* Outputs */ 131170034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 131270034214SMatthew G. Knepley PetscInt *assignment, *points; 131377623264SMatthew G. Knepley PetscMPIInt rank, p, v, i; 131470034214SMatthew G. Knepley PetscErrorCode ierr; 131570034214SMatthew G. Knepley 131670034214SMatthew G. Knepley PetscFunctionBegin; 131777623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 131870034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 131970034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 132070034214SMatthew G. Knepley /* Calculate vertex distribution */ 132170034214SMatthew G. Knepley ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 132270034214SMatthew G. Knepley vtxdist[0] = 0; 132370034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 132470034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 132570034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 132670034214SMatthew G. Knepley } 132770034214SMatthew G. Knepley /* Calculate weights */ 132870034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 132970034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 133070034214SMatthew G. Knepley } 133170034214SMatthew G. Knepley ubvec[0] = 1.05; 133270034214SMatthew G. Knepley 133370034214SMatthew G. Knepley if (nparts == 1) { 13349fc93327SToby Isaac ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 133570034214SMatthew G. Knepley } else { 133670034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 133770034214SMatthew G. Knepley if (!rank) { 133870034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 133970034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 134070034214SMatthew G. Knepley PetscStackPop; 134170034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 134270034214SMatthew G. Knepley } 134370034214SMatthew G. Knepley } else { 134470034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 134570034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 134670034214SMatthew G. Knepley PetscStackPop; 134770034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 134870034214SMatthew G. Knepley } 134970034214SMatthew G. Knepley } 135070034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 135177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 135277623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 135377623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 135470034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 135577623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 135670034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 135770034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 135870034214SMatthew G. Knepley } 135970034214SMatthew G. Knepley } 136070034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 136170034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 136270034214SMatthew G. Knepley ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 13639b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 136470034214SMatthew G. Knepley #else 136577623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 136670034214SMatthew G. Knepley #endif 136770034214SMatthew G. Knepley } 136870034214SMatthew G. Knepley 136977623264SMatthew G. Knepley #undef __FUNCT__ 137077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_ParMetis" 137177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 137277623264SMatthew G. Knepley { 137377623264SMatthew G. Knepley PetscFunctionBegin; 137477623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 137577623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 137677623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 137777623264SMatthew G. Knepley PetscFunctionReturn(0); 137877623264SMatthew G. Knepley } 137977623264SMatthew G. Knepley 138077623264SMatthew G. Knepley /*MC 138177623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 138277623264SMatthew G. Knepley 138377623264SMatthew G. Knepley Level: intermediate 138477623264SMatthew G. Knepley 138577623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 138677623264SMatthew G. Knepley M*/ 138777623264SMatthew G. Knepley 138877623264SMatthew G. Knepley #undef __FUNCT__ 138977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_ParMetis" 139077623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 139177623264SMatthew G. Knepley { 139277623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 139377623264SMatthew G. Knepley PetscErrorCode ierr; 139477623264SMatthew G. Knepley 139577623264SMatthew G. Knepley PetscFunctionBegin; 139677623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 139777623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 139877623264SMatthew G. Knepley part->data = p; 139977623264SMatthew G. Knepley 140077623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 140177623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 140270034214SMatthew G. Knepley PetscFunctionReturn(0); 140370034214SMatthew G. Knepley } 140470034214SMatthew G. Knepley 140570034214SMatthew G. Knepley #undef __FUNCT__ 14065680f57bSMatthew G. Knepley #define __FUNCT__ "DMPlexGetPartitioner" 14075680f57bSMatthew G. Knepley /*@ 14085680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 14095680f57bSMatthew G. Knepley 14105680f57bSMatthew G. Knepley Not collective 14115680f57bSMatthew G. Knepley 14125680f57bSMatthew G. Knepley Input Parameter: 14135680f57bSMatthew G. Knepley . dm - The DM 14145680f57bSMatthew G. Knepley 14155680f57bSMatthew G. Knepley Output Parameter: 14165680f57bSMatthew G. Knepley . part - The PetscPartitioner 14175680f57bSMatthew G. Knepley 14185680f57bSMatthew G. Knepley Level: developer 14195680f57bSMatthew G. Knepley 142098599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 142198599a47SLawrence Mitchell 142298599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 14235680f57bSMatthew G. Knepley @*/ 14245680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 14255680f57bSMatthew G. Knepley { 14265680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 14275680f57bSMatthew G. Knepley 14285680f57bSMatthew G. Knepley PetscFunctionBegin; 14295680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14305680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 14315680f57bSMatthew G. Knepley *part = mesh->partitioner; 14325680f57bSMatthew G. Knepley PetscFunctionReturn(0); 14335680f57bSMatthew G. Knepley } 14345680f57bSMatthew G. Knepley 14355680f57bSMatthew G. Knepley #undef __FUNCT__ 143671bb2955SLawrence Mitchell #define __FUNCT__ "DMPlexSetPartitioner" 143771bb2955SLawrence Mitchell /*@ 143871bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 143971bb2955SLawrence Mitchell 144071bb2955SLawrence Mitchell logically collective on dm and part 144171bb2955SLawrence Mitchell 144271bb2955SLawrence Mitchell Input Parameters: 144371bb2955SLawrence Mitchell + dm - The DM 144471bb2955SLawrence Mitchell - part - The partitioner 144571bb2955SLawrence Mitchell 144671bb2955SLawrence Mitchell Level: developer 144771bb2955SLawrence Mitchell 144871bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 144971bb2955SLawrence Mitchell 145071bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 145171bb2955SLawrence Mitchell @*/ 145271bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 145371bb2955SLawrence Mitchell { 145471bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 145571bb2955SLawrence Mitchell PetscErrorCode ierr; 145671bb2955SLawrence Mitchell 145771bb2955SLawrence Mitchell PetscFunctionBegin; 145871bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 145971bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 146071bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 146171bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 146271bb2955SLawrence Mitchell mesh->partitioner = part; 146371bb2955SLawrence Mitchell PetscFunctionReturn(0); 146471bb2955SLawrence Mitchell } 146571bb2955SLawrence Mitchell 146671bb2955SLawrence Mitchell #undef __FUNCT__ 1467270bba0cSToby Isaac #define __FUNCT__ "DMPlexPartitionLabelClosure_Tree" 14686a5a2ffdSToby Isaac static PetscErrorCode DMPlexPartitionLabelClosure_Tree(DM dm, DMLabel label, PetscInt rank, PetscInt point, PetscBool up, PetscBool down) 1469270bba0cSToby Isaac { 1470270bba0cSToby Isaac PetscErrorCode ierr; 1471270bba0cSToby Isaac 1472270bba0cSToby Isaac PetscFunctionBegin; 14736a5a2ffdSToby Isaac if (up) { 14746a5a2ffdSToby Isaac PetscInt parent; 14756a5a2ffdSToby Isaac 1476270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 14776a5a2ffdSToby Isaac if (parent != point) { 14786a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 14796a5a2ffdSToby Isaac 1480270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1481270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 1482270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 1483270bba0cSToby Isaac 1484270bba0cSToby Isaac ierr = DMLabelSetValue(label,cpoint,rank);CHKERRQ(ierr); 14856a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1486270bba0cSToby Isaac } 1487270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 14886a5a2ffdSToby Isaac } 14896a5a2ffdSToby Isaac } 14906a5a2ffdSToby Isaac if (down) { 14916a5a2ffdSToby Isaac PetscInt numChildren; 14926a5a2ffdSToby Isaac const PetscInt *children; 14936a5a2ffdSToby Isaac 14946a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 14956a5a2ffdSToby Isaac if (numChildren) { 14966a5a2ffdSToby Isaac PetscInt i; 14976a5a2ffdSToby Isaac 14986a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 14996a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 15006a5a2ffdSToby Isaac 15016a5a2ffdSToby Isaac ierr = DMLabelSetValue(label,cpoint,rank);CHKERRQ(ierr); 15026a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 15036a5a2ffdSToby Isaac } 15046a5a2ffdSToby Isaac } 15056a5a2ffdSToby Isaac } 1506270bba0cSToby Isaac PetscFunctionReturn(0); 1507270bba0cSToby Isaac } 1508270bba0cSToby Isaac 1509270bba0cSToby Isaac #undef __FUNCT__ 15105abbe4feSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelClosure" 15115abbe4feSMichael Lange /*@ 15125abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 15135abbe4feSMichael Lange 15145abbe4feSMichael Lange Input Parameters: 15155abbe4feSMichael Lange + dm - The DM 15165abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 15175abbe4feSMichael Lange 15185abbe4feSMichael Lange Level: developer 15195abbe4feSMichael Lange 15205abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 15215abbe4feSMichael Lange @*/ 15225abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 15239ffc88e4SToby Isaac { 15245abbe4feSMichael Lange IS rankIS, pointIS; 15255abbe4feSMichael Lange const PetscInt *ranks, *points; 15265abbe4feSMichael Lange PetscInt numRanks, numPoints, r, p, c, closureSize; 15275abbe4feSMichael Lange PetscInt *closure = NULL; 15289ffc88e4SToby Isaac PetscErrorCode ierr; 15299ffc88e4SToby Isaac 15309ffc88e4SToby Isaac PetscFunctionBegin; 15315abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 15325abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 15335abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 15345abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 15355abbe4feSMichael Lange const PetscInt rank = ranks[r]; 15369ffc88e4SToby Isaac 15375abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 15385abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 15395abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 15405abbe4feSMichael Lange for (p = 0; p < numPoints; ++p) { 15415abbe4feSMichael Lange ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1542270bba0cSToby Isaac for (c = 0; c < closureSize*2; c += 2) { 1543270bba0cSToby Isaac ierr = DMLabelSetValue(label, closure[c], rank);CHKERRQ(ierr); 15446a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,closure[c],PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr); 1545270bba0cSToby Isaac } 15469ffc88e4SToby Isaac } 15475abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 15485abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 15499ffc88e4SToby Isaac } 15507de78196SMichael Lange if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);} 15515abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 15525abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 15539ffc88e4SToby Isaac PetscFunctionReturn(0); 15549ffc88e4SToby Isaac } 15559ffc88e4SToby Isaac 15569ffc88e4SToby Isaac #undef __FUNCT__ 155724d039d7SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelAdjacency" 155824d039d7SMichael Lange /*@ 155924d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 156024d039d7SMichael Lange 156124d039d7SMichael Lange Input Parameters: 156224d039d7SMichael Lange + dm - The DM 156324d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 156424d039d7SMichael Lange 156524d039d7SMichael Lange Level: developer 156624d039d7SMichael Lange 156724d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 156824d039d7SMichael Lange @*/ 156924d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 157070034214SMatthew G. Knepley { 157124d039d7SMichael Lange IS rankIS, pointIS; 157224d039d7SMichael Lange const PetscInt *ranks, *points; 157324d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 157424d039d7SMichael Lange PetscInt *adj = NULL; 157570034214SMatthew G. Knepley PetscErrorCode ierr; 157670034214SMatthew G. Knepley 157770034214SMatthew G. Knepley PetscFunctionBegin; 157824d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 157924d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 158024d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 158124d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 158224d039d7SMichael Lange const PetscInt rank = ranks[r]; 158370034214SMatthew G. Knepley 158424d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 158524d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 158624d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 158770034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 158824d039d7SMichael Lange adjSize = PETSC_DETERMINE; 158924d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 159024d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 159170034214SMatthew G. Knepley } 159224d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 159324d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 159470034214SMatthew G. Knepley } 159524d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 159624d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 159724d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 159824d039d7SMichael Lange PetscFunctionReturn(0); 159970034214SMatthew G. Knepley } 160070034214SMatthew G. Knepley 160124d039d7SMichael Lange #undef __FUNCT__ 1602be200f8dSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelPropagate" 1603be200f8dSMichael Lange /*@ 1604be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1605be200f8dSMichael Lange 1606be200f8dSMichael Lange Input Parameters: 1607be200f8dSMichael Lange + dm - The DM 1608be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 1609be200f8dSMichael Lange 1610be200f8dSMichael Lange Level: developer 1611be200f8dSMichael Lange 1612be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1613be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1614be200f8dSMichael Lange 1615be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 1616be200f8dSMichael Lange @*/ 1617be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1618be200f8dSMichael Lange { 1619be200f8dSMichael Lange MPI_Comm comm; 1620be200f8dSMichael Lange PetscMPIInt rank; 1621be200f8dSMichael Lange PetscSF sfPoint; 16225d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1623be200f8dSMichael Lange IS rankIS, pointIS; 1624be200f8dSMichael Lange const PetscInt *ranks; 1625be200f8dSMichael Lange PetscInt numRanks, r; 1626be200f8dSMichael Lange PetscErrorCode ierr; 1627be200f8dSMichael Lange 1628be200f8dSMichael Lange PetscFunctionBegin; 1629be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1630be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1631be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 16325d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 16335d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 16345d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 16355d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 16365d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 16375d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 16385d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 16395d04f6ebSMichael Lange if (remoteRank == rank) continue; 16405d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 16415d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 16425d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 16435d04f6ebSMichael Lange } 16445d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 16455d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 16465d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 1647be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 1648be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 1649be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 1650be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 1651be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 1652be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1653be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1654be200f8dSMichael Lange if (remoteRank == rank) continue; 1655be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 1656be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 1657be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1658be200f8dSMichael Lange } 1659be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 1660be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 1661be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 1662be200f8dSMichael Lange PetscFunctionReturn(0); 1663be200f8dSMichael Lange } 1664be200f8dSMichael Lange 1665be200f8dSMichael Lange #undef __FUNCT__ 16661fd9873aSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelInvert" 16671fd9873aSMichael Lange /*@ 16681fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 16691fd9873aSMichael Lange 16701fd9873aSMichael Lange Input Parameters: 16711fd9873aSMichael Lange + dm - The DM 16721fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 16731fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 16741fd9873aSMichael Lange 16751fd9873aSMichael Lange Output Parameter: 16761fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 16771fd9873aSMichael Lange 16781fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 16791fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 16801fd9873aSMichael Lange 16811fd9873aSMichael Lange Level: developer 16821fd9873aSMichael Lange 16831fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 16841fd9873aSMichael Lange @*/ 16851fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 16861fd9873aSMichael Lange { 16871fd9873aSMichael Lange MPI_Comm comm; 16881fd9873aSMichael Lange PetscMPIInt rank, numProcs; 16891fd9873aSMichael Lange PetscInt p, n, numNeighbors, size, l, nleaves; 16901fd9873aSMichael Lange PetscSF sfPoint; 16911fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 16921fd9873aSMichael Lange PetscSection rootSection, leafSection; 16931fd9873aSMichael Lange const PetscSFNode *remote; 16941fd9873aSMichael Lange const PetscInt *local, *neighbors; 16951fd9873aSMichael Lange IS valueIS; 16961fd9873aSMichael Lange PetscErrorCode ierr; 16971fd9873aSMichael Lange 16981fd9873aSMichael Lange PetscFunctionBegin; 16991fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 17001fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 17011fd9873aSMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 17021fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 17031fd9873aSMichael Lange 17041fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 17051fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 17061fd9873aSMichael Lange ierr = PetscSectionSetChart(rootSection, 0, numProcs);CHKERRQ(ierr); 17071fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 17081fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 17091fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 17101fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 17111fd9873aSMichael Lange PetscInt numPoints; 17121fd9873aSMichael Lange 17131fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 17141fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 17151fd9873aSMichael Lange } 17161fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 17171fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 17181fd9873aSMichael Lange ierr = PetscMalloc1(size, &rootPoints);CHKERRQ(ierr); 17191fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 17201fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 17211fd9873aSMichael Lange IS pointIS; 17221fd9873aSMichael Lange const PetscInt *points; 17231fd9873aSMichael Lange PetscInt off, numPoints, p; 17241fd9873aSMichael Lange 17251fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 17261fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 17271fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 17281fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 17291fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1730f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1731f8987ae8SMichael Lange else {l = -1;} 17321fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 17331fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 17341fd9873aSMichael Lange } 17351fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 17361fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 17371fd9873aSMichael Lange } 17381fd9873aSMichael Lange ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 17391fd9873aSMichael Lange ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 17401fd9873aSMichael Lange /* Communicate overlap */ 17411fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr); 17421fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 17431fd9873aSMichael Lange /* Filter remote contributions (ovLeafPoints) into the overlapSF */ 17441fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 17451fd9873aSMichael Lange for (p = 0; p < size; p++) { 17461fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 17471fd9873aSMichael Lange } 17481fd9873aSMichael Lange ierr = PetscFree(rootPoints);CHKERRQ(ierr); 17491fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 17501fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 17511fd9873aSMichael Lange ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 17521fd9873aSMichael Lange PetscFunctionReturn(0); 17531fd9873aSMichael Lange } 17541fd9873aSMichael Lange 17551fd9873aSMichael Lange #undef __FUNCT__ 1756aa3148a8SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelCreateSF" 1757aa3148a8SMichael Lange /*@ 1758aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1759aa3148a8SMichael Lange 1760aa3148a8SMichael Lange Input Parameters: 1761aa3148a8SMichael Lange + dm - The DM 1762aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 1763aa3148a8SMichael Lange 1764aa3148a8SMichael Lange Output Parameter: 1765aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 1766aa3148a8SMichael Lange 1767aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1768aa3148a8SMichael Lange 1769aa3148a8SMichael Lange Level: developer 1770aa3148a8SMichael Lange 1771aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 1772aa3148a8SMichael Lange @*/ 1773aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1774aa3148a8SMichael Lange { 177543f7d02bSMichael Lange PetscMPIInt rank, numProcs; 177643f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 1777aa3148a8SMichael Lange PetscSFNode *remotePoints; 177843f7d02bSMichael Lange IS remoteRootIS; 177943f7d02bSMichael Lange const PetscInt *remoteRoots; 1780aa3148a8SMichael Lange PetscErrorCode ierr; 1781aa3148a8SMichael Lange 1782aa3148a8SMichael Lange PetscFunctionBegin; 178343f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1784aa3148a8SMichael Lange ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 1785aa3148a8SMichael Lange 1786aa3148a8SMichael Lange for (numRemote = 0, n = 0; n < numProcs; ++n) { 1787aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1788aa3148a8SMichael Lange numRemote += numPoints; 1789aa3148a8SMichael Lange } 1790aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 179143f7d02bSMichael Lange /* Put owned points first */ 179243f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 179343f7d02bSMichael Lange if (numPoints > 0) { 179443f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 179543f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 179643f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 179743f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 179843f7d02bSMichael Lange remotePoints[idx].rank = rank; 179943f7d02bSMichael Lange idx++; 180043f7d02bSMichael Lange } 180143f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 180243f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 180343f7d02bSMichael Lange } 180443f7d02bSMichael Lange /* Now add remote points */ 180543f7d02bSMichael Lange for (n = 0; n < numProcs; ++n) { 1806aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 180743f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 1808aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 1809aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1810aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1811aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 1812aa3148a8SMichael Lange remotePoints[idx].rank = n; 1813aa3148a8SMichael Lange idx++; 1814aa3148a8SMichael Lange } 1815aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1816aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1817aa3148a8SMichael Lange } 1818aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1819aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1820aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 182170034214SMatthew G. Knepley PetscFunctionReturn(0); 182270034214SMatthew G. Knepley } 1823