170034214SMatthew G. Knepley #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__ 30*532c4e7dSMichael Lange #define __FUNCT__ "DMPlexCreatePartitionerGraph" 31*532c4e7dSMichael Lange /*@C 32*532c4e7dSMichael Lange DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 33*532c4e7dSMichael Lange 34*532c4e7dSMichael Lange Input Parameters: 35*532c4e7dSMichael Lange + dm - The mesh DM dm 36*532c4e7dSMichael Lange - height - Height of the strata from which to construct the graph 37*532c4e7dSMichael Lange 38*532c4e7dSMichael Lange Output Parameter: 39*532c4e7dSMichael Lange + numVertices - Number of vertices in the graph 40*532c4e7dSMichael Lange - offsets - Point offsets in the graph 41*532c4e7dSMichael Lange - adjacency - Point connectivity in the graph 42*532c4e7dSMichael Lange 43*532c4e7dSMichael Lange The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and 44*532c4e7dSMichael Lange DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function 45*532c4e7dSMichael Lange representation on the mesh. 46*532c4e7dSMichael Lange 47*532c4e7dSMichael Lange Level: developer 48*532c4e7dSMichael Lange 49*532c4e7dSMichael Lange .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure() 50*532c4e7dSMichael Lange @*/ 51*532c4e7dSMichael Lange PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 52*532c4e7dSMichael Lange { 53*532c4e7dSMichael Lange PetscInt p, pStart, pEnd, a, adjSize, size; 54*532c4e7dSMichael Lange PetscInt *adj = NULL, *vOffsets = NULL; 55*532c4e7dSMichael Lange PetscBool useCone, useClosure; 56*532c4e7dSMichael Lange PetscSection section; 57*532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 58*532c4e7dSMichael Lange PetscMPIInt rank; 59*532c4e7dSMichael Lange PetscErrorCode ierr; 60*532c4e7dSMichael Lange 61*532c4e7dSMichael Lange PetscFunctionBegin; 62*532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 63*532c4e7dSMichael Lange ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 64*532c4e7dSMichael Lange *numVertices = pEnd - pStart; 65*532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 66*532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 67*532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 68*532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 69*532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 70*532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 71*532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 72*532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 73*532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr); 74*532c4e7dSMichael Lange for (p = pStart; p < pEnd; p++) { 75*532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 76*532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 77*532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 78*532c4e7dSMichael Lange const PetscInt point = adj[a]; 79*532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 80*532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 81*532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 82*532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 83*532c4e7dSMichael Lange *pBuf = point; 84*532c4e7dSMichael Lange } 85*532c4e7dSMichael Lange } 86*532c4e7dSMichael Lange } 87*532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 88*532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr); 89*532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 90*532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 91*532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 92*532c4e7dSMichael Lange ierr = PetscMalloc2(*numVertices+1, &vOffsets, size, adjacency);CHKERRQ(ierr); 93*532c4e7dSMichael Lange for (p = pStart; p < pEnd; p++) {ierr = PetscSectionGetOffset(section, p, &(vOffsets[p]));CHKERRQ(ierr);} 94*532c4e7dSMichael Lange vOffsets[*numVertices] = size; 95*532c4e7dSMichael Lange if (offsets) *offsets = vOffsets; 96*532c4e7dSMichael Lange if (adjacency) {ierr = PetscSegBufferExtractTo(adjBuffer, *adjacency);CHKERRQ(ierr);} 97*532c4e7dSMichael Lange /* Clean up */ 98*532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 99*532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 100*532c4e7dSMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 101*532c4e7dSMichael Lange PetscFunctionReturn(0); 102*532c4e7dSMichael Lange } 103*532c4e7dSMichael Lange 104*532c4e7dSMichael Lange #undef __FUNCT__ 10570034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 10670034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 10770034214SMatthew G. Knepley { 10870034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 10970034214SMatthew G. Knepley PetscInt numFaceCases = 0; 11070034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 11170034214SMatthew G. Knepley PetscInt *off, *adj; 11270034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 11370034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 11470034214SMatthew G. Knepley PetscErrorCode ierr; 11570034214SMatthew G. Knepley 11670034214SMatthew G. Knepley PetscFunctionBegin; 11770034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 118c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 11970034214SMatthew G. Knepley cellDim = dim - cellHeight; 12070034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 12170034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 12270034214SMatthew G. Knepley if (cEnd - cStart == 0) { 12370034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 12470034214SMatthew G. Knepley if (offsets) *offsets = NULL; 12570034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 12670034214SMatthew G. Knepley PetscFunctionReturn(0); 12770034214SMatthew G. Knepley } 12870034214SMatthew G. Knepley numCells = cEnd - cStart; 12970034214SMatthew G. Knepley faceDepth = depth - cellHeight; 13070034214SMatthew G. Knepley if (dim == depth) { 13170034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 13270034214SMatthew G. Knepley 13370034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 13470034214SMatthew G. Knepley /* Count neighboring cells */ 13570034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 13670034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 13770034214SMatthew G. Knepley const PetscInt *support; 13870034214SMatthew G. Knepley PetscInt supportSize; 13970034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 14070034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 14170034214SMatthew G. Knepley if (supportSize == 2) { 1429ffc88e4SToby Isaac PetscInt numChildren; 1439ffc88e4SToby Isaac 1449ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1459ffc88e4SToby Isaac if (!numChildren) { 14670034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 14770034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 14870034214SMatthew G. Knepley } 14970034214SMatthew G. Knepley } 1509ffc88e4SToby Isaac } 15170034214SMatthew G. Knepley /* Prefix sum */ 15270034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 15370034214SMatthew G. Knepley if (adjacency) { 15470034214SMatthew G. Knepley PetscInt *tmp; 15570034214SMatthew G. Knepley 15670034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 15770034214SMatthew G. Knepley ierr = PetscMalloc1((numCells+1), &tmp);CHKERRQ(ierr); 15870034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 15970034214SMatthew G. Knepley /* Get neighboring cells */ 16070034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 16170034214SMatthew G. Knepley const PetscInt *support; 16270034214SMatthew G. Knepley PetscInt supportSize; 16370034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 16470034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 16570034214SMatthew G. Knepley if (supportSize == 2) { 1669ffc88e4SToby Isaac PetscInt numChildren; 1679ffc88e4SToby Isaac 1689ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1699ffc88e4SToby Isaac if (!numChildren) { 17070034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 17170034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 17270034214SMatthew G. Knepley } 17370034214SMatthew G. Knepley } 1749ffc88e4SToby Isaac } 17570034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 17670034214SMatthew 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); 17770034214SMatthew G. Knepley #endif 17870034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 17970034214SMatthew G. Knepley } 18070034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 18170034214SMatthew G. Knepley if (offsets) *offsets = off; 18270034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 18370034214SMatthew G. Knepley PetscFunctionReturn(0); 18470034214SMatthew G. Knepley } 18570034214SMatthew G. Knepley /* Setup face recognition */ 18670034214SMatthew G. Knepley if (faceDepth == 1) { 18770034214SMatthew 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 */ 18870034214SMatthew G. Knepley 18970034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 19070034214SMatthew G. Knepley PetscInt corners; 19170034214SMatthew G. Knepley 19270034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 19370034214SMatthew G. Knepley if (!cornersSeen[corners]) { 19470034214SMatthew G. Knepley PetscInt nFV; 19570034214SMatthew G. Knepley 19670034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 19770034214SMatthew G. Knepley cornersSeen[corners] = 1; 19870034214SMatthew G. Knepley 19970034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 20070034214SMatthew G. Knepley 20170034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 20270034214SMatthew G. Knepley } 20370034214SMatthew G. Knepley } 20470034214SMatthew G. Knepley } 20570034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 20670034214SMatthew G. Knepley /* Count neighboring cells */ 20770034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 20870034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 20970034214SMatthew G. Knepley 2108b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 21170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 21270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 21370034214SMatthew G. Knepley PetscInt cellPair[2]; 21470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 21570034214SMatthew G. Knepley PetscInt meetSize = 0; 21670034214SMatthew G. Knepley const PetscInt *meet = NULL; 21770034214SMatthew G. Knepley 21870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 21970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 22070034214SMatthew G. Knepley if (!found) { 22170034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 22270034214SMatthew G. Knepley if (meetSize) { 22370034214SMatthew G. Knepley PetscInt f; 22470034214SMatthew G. Knepley 22570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 22670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 22770034214SMatthew G. Knepley found = PETSC_TRUE; 22870034214SMatthew G. Knepley break; 22970034214SMatthew G. Knepley } 23070034214SMatthew G. Knepley } 23170034214SMatthew G. Knepley } 23270034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 23370034214SMatthew G. Knepley } 23470034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 23570034214SMatthew G. Knepley } 23670034214SMatthew G. Knepley } 23770034214SMatthew G. Knepley /* Prefix sum */ 23870034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 23970034214SMatthew G. Knepley 24070034214SMatthew G. Knepley if (adjacency) { 24170034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 24270034214SMatthew G. Knepley /* Get neighboring cells */ 24370034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 24470034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 24570034214SMatthew G. Knepley PetscInt cellOffset = 0; 24670034214SMatthew G. Knepley 2478b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 24870034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 24970034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 25070034214SMatthew G. Knepley PetscInt cellPair[2]; 25170034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 25270034214SMatthew G. Knepley PetscInt meetSize = 0; 25370034214SMatthew G. Knepley const PetscInt *meet = NULL; 25470034214SMatthew G. Knepley 25570034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 25670034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 25770034214SMatthew G. Knepley if (!found) { 25870034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 25970034214SMatthew G. Knepley if (meetSize) { 26070034214SMatthew G. Knepley PetscInt f; 26170034214SMatthew G. Knepley 26270034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 26370034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 26470034214SMatthew G. Knepley found = PETSC_TRUE; 26570034214SMatthew G. Knepley break; 26670034214SMatthew G. Knepley } 26770034214SMatthew G. Knepley } 26870034214SMatthew G. Knepley } 26970034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 27070034214SMatthew G. Knepley } 27170034214SMatthew G. Knepley if (found) { 27270034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 27370034214SMatthew G. Knepley ++cellOffset; 27470034214SMatthew G. Knepley } 27570034214SMatthew G. Knepley } 27670034214SMatthew G. Knepley } 27770034214SMatthew G. Knepley } 27870034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 27970034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 28070034214SMatthew G. Knepley if (offsets) *offsets = off; 28170034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 28270034214SMatthew G. Knepley PetscFunctionReturn(0); 28370034214SMatthew G. Knepley } 28470034214SMatthew G. Knepley 28577623264SMatthew G. Knepley #undef __FUNCT__ 28677623264SMatthew G. Knepley #define __FUNCT__ "DMPlexEnlargePartition" 28777623264SMatthew G. Knepley /* Expand the partition by BFS on the adjacency graph */ 28877623264SMatthew G. Knepley PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection partSection, IS *partition) 28977623264SMatthew G. Knepley { 29077623264SMatthew G. Knepley PetscHashI h; 29177623264SMatthew G. Knepley const PetscInt *points; 29277623264SMatthew G. Knepley PetscInt **tmpPoints, *newPoints, totPoints = 0; 29377623264SMatthew G. Knepley PetscInt pStart, pEnd, part, q; 29477623264SMatthew G. Knepley PetscBool useCone; 29577623264SMatthew G. Knepley PetscErrorCode ierr; 29677623264SMatthew G. Knepley 29777623264SMatthew G. Knepley PetscFunctionBegin; 29877623264SMatthew G. Knepley PetscHashICreate(h); 29977623264SMatthew G. Knepley ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 30077623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, pStart, pEnd);CHKERRQ(ierr); 30177623264SMatthew G. Knepley ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 30277623264SMatthew G. Knepley ierr = PetscMalloc1((pEnd - pStart), &tmpPoints);CHKERRQ(ierr); 30377623264SMatthew G. Knepley ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 30477623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 30577623264SMatthew G. Knepley for (part = pStart; part < pEnd; ++part) { 30677623264SMatthew G. Knepley PetscInt *adj = NULL; 30777623264SMatthew G. Knepley PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 30877623264SMatthew G. Knepley 30977623264SMatthew G. Knepley PetscHashIClear(h); 31077623264SMatthew G. Knepley ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 31177623264SMatthew G. Knepley ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 31277623264SMatthew G. Knepley /* Add all existing points to h */ 31377623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 31477623264SMatthew G. Knepley const PetscInt point = points[off+p]; 31577623264SMatthew G. Knepley PetscHashIAdd(h, point, 1); 31677623264SMatthew G. Knepley } 31777623264SMatthew G. Knepley PetscHashISize(h, nP); 31877623264SMatthew G. Knepley if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 31977623264SMatthew G. Knepley /* Add all points in next BFS level */ 32077623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 32177623264SMatthew G. Knepley const PetscInt point = points[off+p]; 32277623264SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 32377623264SMatthew G. Knepley 32477623264SMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, point, &adjSize, &adj);CHKERRQ(ierr); 32577623264SMatthew G. Knepley for (a = 0; a < adjSize; ++a) PetscHashIAdd(h, adj[a], 1); 32677623264SMatthew G. Knepley } 32777623264SMatthew G. Knepley PetscHashISize(h, numNewPoints); 32877623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, part, numNewPoints);CHKERRQ(ierr); 32977623264SMatthew G. Knepley ierr = PetscMalloc1(numNewPoints, &tmpPoints[part]);CHKERRQ(ierr); 33077623264SMatthew G. Knepley ierr = PetscHashIGetKeys(h, &n, tmpPoints[part]);CHKERRQ(ierr); 33177623264SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 33277623264SMatthew G. Knepley totPoints += numNewPoints; 33377623264SMatthew G. Knepley } 33477623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 33577623264SMatthew G. Knepley ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 33677623264SMatthew G. Knepley PetscHashIDestroy(h); 33777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 33877623264SMatthew G. Knepley ierr = PetscMalloc1(totPoints, &newPoints);CHKERRQ(ierr); 33977623264SMatthew G. Knepley for (part = pStart, q = 0; part < pEnd; ++part) { 34077623264SMatthew G. Knepley PetscInt numPoints, p; 34177623264SMatthew G. Knepley 34277623264SMatthew G. Knepley ierr = PetscSectionGetDof(partSection, part, &numPoints);CHKERRQ(ierr); 34377623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 34477623264SMatthew G. Knepley ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 34577623264SMatthew G. Knepley } 34677623264SMatthew G. Knepley ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 34777623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 34877623264SMatthew G. Knepley PetscFunctionReturn(0); 34977623264SMatthew G. Knepley } 35077623264SMatthew G. Knepley 35177623264SMatthew G. Knepley #undef __FUNCT__ 35277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerRegister" 35377623264SMatthew G. Knepley /*@C 35477623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 35577623264SMatthew G. Knepley 35677623264SMatthew G. Knepley Not Collective 35777623264SMatthew G. Knepley 35877623264SMatthew G. Knepley Input Parameters: 35977623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 36077623264SMatthew G. Knepley - create_func - The creation routine itself 36177623264SMatthew G. Knepley 36277623264SMatthew G. Knepley Notes: 36377623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 36477623264SMatthew G. Knepley 36577623264SMatthew G. Knepley Sample usage: 36677623264SMatthew G. Knepley .vb 36777623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 36877623264SMatthew G. Knepley .ve 36977623264SMatthew G. Knepley 37077623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 37177623264SMatthew G. Knepley .vb 37277623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 37377623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 37477623264SMatthew G. Knepley .ve 37577623264SMatthew G. Knepley or at runtime via the option 37677623264SMatthew G. Knepley .vb 37777623264SMatthew G. Knepley -petscpartitioner_type my_part 37877623264SMatthew G. Knepley .ve 37977623264SMatthew G. Knepley 38077623264SMatthew G. Knepley Level: advanced 38177623264SMatthew G. Knepley 38277623264SMatthew G. Knepley .keywords: PetscPartitioner, register 38377623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 38477623264SMatthew G. Knepley 38577623264SMatthew G. Knepley @*/ 38677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 38777623264SMatthew G. Knepley { 38877623264SMatthew G. Knepley PetscErrorCode ierr; 38977623264SMatthew G. Knepley 39077623264SMatthew G. Knepley PetscFunctionBegin; 39177623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 39277623264SMatthew G. Knepley PetscFunctionReturn(0); 39377623264SMatthew G. Knepley } 39477623264SMatthew G. Knepley 39577623264SMatthew G. Knepley #undef __FUNCT__ 39677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetType" 39777623264SMatthew G. Knepley /*@C 39877623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 39977623264SMatthew G. Knepley 40077623264SMatthew G. Knepley Collective on PetscPartitioner 40177623264SMatthew G. Knepley 40277623264SMatthew G. Knepley Input Parameters: 40377623264SMatthew G. Knepley + part - The PetscPartitioner object 40477623264SMatthew G. Knepley - name - The kind of partitioner 40577623264SMatthew G. Knepley 40677623264SMatthew G. Knepley Options Database Key: 40777623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 40877623264SMatthew G. Knepley 40977623264SMatthew G. Knepley Level: intermediate 41077623264SMatthew G. Knepley 41177623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 41277623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 41377623264SMatthew G. Knepley @*/ 41477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 41577623264SMatthew G. Knepley { 41677623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 41777623264SMatthew G. Knepley PetscBool match; 41877623264SMatthew G. Knepley PetscErrorCode ierr; 41977623264SMatthew G. Knepley 42077623264SMatthew G. Knepley PetscFunctionBegin; 42177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 42277623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 42377623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 42477623264SMatthew G. Knepley 42577623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 42677623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 42777623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 42877623264SMatthew G. Knepley 42977623264SMatthew G. Knepley if (part->ops->destroy) { 43077623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 43177623264SMatthew G. Knepley part->ops->destroy = NULL; 43277623264SMatthew G. Knepley } 43377623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 43477623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 43577623264SMatthew G. Knepley PetscFunctionReturn(0); 43677623264SMatthew G. Knepley } 43777623264SMatthew G. Knepley 43877623264SMatthew G. Knepley #undef __FUNCT__ 43977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerGetType" 44077623264SMatthew G. Knepley /*@C 44177623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 44277623264SMatthew G. Knepley 44377623264SMatthew G. Knepley Not Collective 44477623264SMatthew G. Knepley 44577623264SMatthew G. Knepley Input Parameter: 44677623264SMatthew G. Knepley . part - The PetscPartitioner 44777623264SMatthew G. Knepley 44877623264SMatthew G. Knepley Output Parameter: 44977623264SMatthew G. Knepley . name - The PetscPartitioner type name 45077623264SMatthew G. Knepley 45177623264SMatthew G. Knepley Level: intermediate 45277623264SMatthew G. Knepley 45377623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 45477623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 45577623264SMatthew G. Knepley @*/ 45677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 45777623264SMatthew G. Knepley { 45877623264SMatthew G. Knepley PetscErrorCode ierr; 45977623264SMatthew G. Knepley 46077623264SMatthew G. Knepley PetscFunctionBegin; 46177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 46277623264SMatthew G. Knepley PetscValidPointer(name, 2); 46377623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 46477623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 46577623264SMatthew G. Knepley PetscFunctionReturn(0); 46677623264SMatthew G. Knepley } 46777623264SMatthew G. Knepley 46877623264SMatthew G. Knepley #undef __FUNCT__ 46977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView" 47077623264SMatthew G. Knepley /*@C 47177623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 47277623264SMatthew G. Knepley 47377623264SMatthew G. Knepley Collective on PetscPartitioner 47477623264SMatthew G. Knepley 47577623264SMatthew G. Knepley Input Parameter: 47677623264SMatthew G. Knepley + part - the PetscPartitioner object to view 47777623264SMatthew G. Knepley - v - the viewer 47877623264SMatthew G. Knepley 47977623264SMatthew G. Knepley Level: developer 48077623264SMatthew G. Knepley 48177623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 48277623264SMatthew G. Knepley @*/ 48377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 48477623264SMatthew G. Knepley { 48577623264SMatthew G. Knepley PetscErrorCode ierr; 48677623264SMatthew G. Knepley 48777623264SMatthew G. Knepley PetscFunctionBegin; 48877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 48977623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 49077623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 49177623264SMatthew G. Knepley PetscFunctionReturn(0); 49277623264SMatthew G. Knepley } 49377623264SMatthew G. Knepley 49477623264SMatthew G. Knepley #undef __FUNCT__ 49577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerViewFromOptions" 49677623264SMatthew G. Knepley /* 49777623264SMatthew G. Knepley PetscPartitionerViewFromOptions - Processes command line options to determine if/how a PetscPartitioner is to be viewed. 49877623264SMatthew G. Knepley 49977623264SMatthew G. Knepley Collective on PetscPartitioner 50077623264SMatthew G. Knepley 50177623264SMatthew G. Knepley Input Parameters: 50277623264SMatthew G. Knepley + part - the PetscPartitioner 50377623264SMatthew G. Knepley . prefix - prefix to use for viewing, or NULL 50477623264SMatthew G. Knepley - optionname - option to activate viewing 50577623264SMatthew G. Knepley 50677623264SMatthew G. Knepley Level: intermediate 50777623264SMatthew G. Knepley 50877623264SMatthew G. Knepley .keywords: PetscPartitioner, view, options, database 50977623264SMatthew G. Knepley .seealso: VecViewFromOptions(), MatViewFromOptions() 51077623264SMatthew G. Knepley */ 51177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner part, const char prefix[], const char optionname[]) 51277623264SMatthew G. Knepley { 51377623264SMatthew G. Knepley PetscViewer viewer; 51477623264SMatthew G. Knepley PetscViewerFormat format; 51577623264SMatthew G. Knepley PetscBool flg; 51677623264SMatthew G. Knepley PetscErrorCode ierr; 51777623264SMatthew G. Knepley 51877623264SMatthew G. Knepley PetscFunctionBegin; 51977623264SMatthew G. Knepley if (prefix) {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 52077623264SMatthew G. Knepley else {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), ((PetscObject) part)->prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 52177623264SMatthew G. Knepley if (flg) { 52277623264SMatthew G. Knepley ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr); 52377623264SMatthew G. Knepley ierr = PetscPartitionerView(part, viewer);CHKERRQ(ierr); 52477623264SMatthew G. Knepley ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 52577623264SMatthew G. Knepley ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 52677623264SMatthew G. Knepley } 52777623264SMatthew G. Knepley PetscFunctionReturn(0); 52877623264SMatthew G. Knepley } 52977623264SMatthew G. Knepley #undef __FUNCT__ 53077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetTypeFromOptions_Internal" 53177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetTypeFromOptions_Internal(PetscPartitioner part) 53277623264SMatthew G. Knepley { 53377623264SMatthew G. Knepley const char *defaultType; 53477623264SMatthew G. Knepley char name[256]; 53577623264SMatthew G. Knepley PetscBool flg; 53677623264SMatthew G. Knepley PetscErrorCode ierr; 53777623264SMatthew G. Knepley 53877623264SMatthew G. Knepley PetscFunctionBegin; 53977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 54077623264SMatthew G. Knepley if (!((PetscObject) part)->type_name) defaultType = PETSCPARTITIONERCHACO; 54177623264SMatthew G. Knepley else defaultType = ((PetscObject) part)->type_name; 54277623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 54377623264SMatthew G. Knepley 54477623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 54577623264SMatthew G. Knepley ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, 256, &flg);CHKERRQ(ierr); 54677623264SMatthew G. Knepley if (flg) { 54777623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 54877623264SMatthew G. Knepley } else if (!((PetscObject) part)->type_name) { 54977623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 55077623264SMatthew G. Knepley } 55177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 55277623264SMatthew G. Knepley PetscFunctionReturn(0); 55377623264SMatthew G. Knepley } 55477623264SMatthew G. Knepley 55577623264SMatthew G. Knepley #undef __FUNCT__ 55677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions" 55777623264SMatthew G. Knepley /*@ 55877623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 55977623264SMatthew G. Knepley 56077623264SMatthew G. Knepley Collective on PetscPartitioner 56177623264SMatthew G. Knepley 56277623264SMatthew G. Knepley Input Parameter: 56377623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 56477623264SMatthew G. Knepley 56577623264SMatthew G. Knepley Level: developer 56677623264SMatthew G. Knepley 56777623264SMatthew G. Knepley .seealso: PetscPartitionerView() 56877623264SMatthew G. Knepley @*/ 56977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 57077623264SMatthew G. Knepley { 57177623264SMatthew G. Knepley PetscErrorCode ierr; 57277623264SMatthew G. Knepley 57377623264SMatthew G. Knepley PetscFunctionBegin; 57477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 57577623264SMatthew G. Knepley ierr = PetscPartitionerSetTypeFromOptions_Internal(part);CHKERRQ(ierr); 57677623264SMatthew G. Knepley 57777623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 57877623264SMatthew G. Knepley if (part->ops->setfromoptions) {ierr = (*part->ops->setfromoptions)(part);CHKERRQ(ierr);} 57977623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 58077623264SMatthew G. Knepley ierr = PetscObjectProcessOptionsHandlers((PetscObject) part);CHKERRQ(ierr); 58177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 58277623264SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 58377623264SMatthew G. Knepley PetscFunctionReturn(0); 58477623264SMatthew G. Knepley } 58577623264SMatthew G. Knepley 58677623264SMatthew G. Knepley #undef __FUNCT__ 58777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetUp" 58877623264SMatthew G. Knepley /*@C 58977623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 59077623264SMatthew G. Knepley 59177623264SMatthew G. Knepley Collective on PetscPartitioner 59277623264SMatthew G. Knepley 59377623264SMatthew G. Knepley Input Parameter: 59477623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 59577623264SMatthew G. Knepley 59677623264SMatthew G. Knepley Level: developer 59777623264SMatthew G. Knepley 59877623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 59977623264SMatthew G. Knepley @*/ 60077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 60177623264SMatthew G. Knepley { 60277623264SMatthew G. Knepley PetscErrorCode ierr; 60377623264SMatthew G. Knepley 60477623264SMatthew G. Knepley PetscFunctionBegin; 60577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 60677623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 60777623264SMatthew G. Knepley PetscFunctionReturn(0); 60877623264SMatthew G. Knepley } 60977623264SMatthew G. Knepley 61077623264SMatthew G. Knepley #undef __FUNCT__ 61177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy" 61277623264SMatthew G. Knepley /*@ 61377623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 61477623264SMatthew G. Knepley 61577623264SMatthew G. Knepley Collective on PetscPartitioner 61677623264SMatthew G. Knepley 61777623264SMatthew G. Knepley Input Parameter: 61877623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 61977623264SMatthew G. Knepley 62077623264SMatthew G. Knepley Level: developer 62177623264SMatthew G. Knepley 62277623264SMatthew G. Knepley .seealso: PetscPartitionerView() 62377623264SMatthew G. Knepley @*/ 62477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 62577623264SMatthew G. Knepley { 62677623264SMatthew G. Knepley PetscErrorCode ierr; 62777623264SMatthew G. Knepley 62877623264SMatthew G. Knepley PetscFunctionBegin; 62977623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 63077623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 63177623264SMatthew G. Knepley 63277623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 63377623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 63477623264SMatthew G. Knepley 63577623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 63677623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 63777623264SMatthew G. Knepley PetscFunctionReturn(0); 63877623264SMatthew G. Knepley } 63977623264SMatthew G. Knepley 64077623264SMatthew G. Knepley #undef __FUNCT__ 64177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate" 64277623264SMatthew G. Knepley /*@ 64377623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 64477623264SMatthew G. Knepley 64577623264SMatthew G. Knepley Collective on MPI_Comm 64677623264SMatthew G. Knepley 64777623264SMatthew G. Knepley Input Parameter: 64877623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 64977623264SMatthew G. Knepley 65077623264SMatthew G. Knepley Output Parameter: 65177623264SMatthew G. Knepley . part - The PetscPartitioner object 65277623264SMatthew G. Knepley 65377623264SMatthew G. Knepley Level: beginner 65477623264SMatthew G. Knepley 65577623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL 65677623264SMatthew G. Knepley @*/ 65777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 65877623264SMatthew G. Knepley { 65977623264SMatthew G. Knepley PetscPartitioner p; 66077623264SMatthew G. Knepley PetscErrorCode ierr; 66177623264SMatthew G. Knepley 66277623264SMatthew G. Knepley PetscFunctionBegin; 66377623264SMatthew G. Knepley PetscValidPointer(part, 2); 66477623264SMatthew G. Knepley *part = NULL; 66577623264SMatthew G. Knepley ierr = PetscFVInitializePackage();CHKERRQ(ierr); 66677623264SMatthew G. Knepley 66777623264SMatthew G. Knepley ierr = PetscHeaderCreate(p, _p_PetscPartitioner, struct _PetscPartitionerOps, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 66877623264SMatthew G. Knepley ierr = PetscMemzero(p->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 66977623264SMatthew G. Knepley 67077623264SMatthew G. Knepley *part = p; 67177623264SMatthew G. Knepley PetscFunctionReturn(0); 67277623264SMatthew G. Knepley } 67377623264SMatthew G. Knepley 67477623264SMatthew G. Knepley #undef __FUNCT__ 67577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition" 67677623264SMatthew G. Knepley /*@ 67777623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 67877623264SMatthew G. Knepley 67977623264SMatthew G. Knepley Collective on DM 68077623264SMatthew G. Knepley 68177623264SMatthew G. Knepley Input Parameters: 68277623264SMatthew G. Knepley + part - The PetscPartitioner 683f8987ae8SMichael Lange - dm - The mesh DM 68477623264SMatthew G. Knepley 68577623264SMatthew G. Knepley Output Parameters: 68677623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 687f8987ae8SMichael Lange - partition - The list of points by partition 68877623264SMatthew G. Knepley 68977623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 69077623264SMatthew G. Knepley 69177623264SMatthew G. Knepley Level: developer 69277623264SMatthew G. Knepley 69377623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 6944b15ede2SMatthew G. Knepley @*/ 695f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 69677623264SMatthew G. Knepley { 69777623264SMatthew G. Knepley PetscMPIInt size; 69877623264SMatthew G. Knepley PetscErrorCode ierr; 69977623264SMatthew G. Knepley 70077623264SMatthew G. Knepley PetscFunctionBegin; 70177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 70277623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 70377623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 70477623264SMatthew G. Knepley PetscValidPointer(partition, 5); 70577623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 70677623264SMatthew G. Knepley if (size == 1) { 70777623264SMatthew G. Knepley PetscInt *points; 70877623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 70977623264SMatthew G. Knepley 71077623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 71177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 71277623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 71377623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 71477623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 71577623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 71677623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 71777623264SMatthew G. Knepley PetscFunctionReturn(0); 71877623264SMatthew G. Knepley } 71977623264SMatthew G. Knepley if (part->height == 0) { 72077623264SMatthew G. Knepley PetscInt numVertices; 72177623264SMatthew G. Knepley PetscInt *start = NULL; 72277623264SMatthew G. Knepley PetscInt *adjacency = NULL; 72377623264SMatthew G. Knepley 724*532c4e7dSMichael Lange ierr = DMPlexCreatePartitionerGraph(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 72577623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 72677623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 72777623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 72877623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 72977623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 73077623264SMatthew G. Knepley PetscFunctionReturn(0); 73177623264SMatthew G. Knepley } 73277623264SMatthew G. Knepley 73377623264SMatthew G. Knepley #undef __FUNCT__ 73477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Shell" 73577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 73677623264SMatthew G. Knepley { 73777623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 73877623264SMatthew G. Knepley PetscErrorCode ierr; 73977623264SMatthew G. Knepley 74077623264SMatthew G. Knepley PetscFunctionBegin; 74177623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 74277623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 74377623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 74477623264SMatthew G. Knepley PetscFunctionReturn(0); 74577623264SMatthew G. Knepley } 74677623264SMatthew G. Knepley 74777623264SMatthew G. Knepley #undef __FUNCT__ 74877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell_Ascii" 74977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 75077623264SMatthew G. Knepley { 75177623264SMatthew G. Knepley PetscViewerFormat format; 75277623264SMatthew G. Knepley PetscErrorCode ierr; 75377623264SMatthew G. Knepley 75477623264SMatthew G. Knepley PetscFunctionBegin; 75577623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 75677623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Shell Graph Partitioner:\n");CHKERRQ(ierr); 75777623264SMatthew G. Knepley PetscFunctionReturn(0); 75877623264SMatthew G. Knepley } 75977623264SMatthew G. Knepley 76077623264SMatthew G. Knepley #undef __FUNCT__ 76177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell" 76277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 76377623264SMatthew G. Knepley { 76477623264SMatthew G. Knepley PetscBool iascii; 76577623264SMatthew G. Knepley PetscErrorCode ierr; 76677623264SMatthew G. Knepley 76777623264SMatthew G. Knepley PetscFunctionBegin; 76877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 76977623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 77077623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 77177623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 77277623264SMatthew G. Knepley PetscFunctionReturn(0); 77377623264SMatthew G. Knepley } 77477623264SMatthew G. Knepley 77577623264SMatthew G. Knepley #undef __FUNCT__ 77677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Shell" 77777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 77877623264SMatthew G. Knepley { 77977623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 78077623264SMatthew G. Knepley PetscInt np; 78177623264SMatthew G. Knepley PetscErrorCode ierr; 78277623264SMatthew G. Knepley 78377623264SMatthew G. Knepley PetscFunctionBegin; 78477623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 78577623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 78677623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 78777623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 7885680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 78977623264SMatthew G. Knepley *partition = p->partition; 79077623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 79177623264SMatthew G. Knepley PetscFunctionReturn(0); 79277623264SMatthew G. Knepley } 79377623264SMatthew G. Knepley 79477623264SMatthew G. Knepley #undef __FUNCT__ 79577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Shell" 79677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 79777623264SMatthew G. Knepley { 79877623264SMatthew G. Knepley PetscFunctionBegin; 79977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 80077623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 80177623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 80277623264SMatthew G. Knepley PetscFunctionReturn(0); 80377623264SMatthew G. Knepley } 80477623264SMatthew G. Knepley 80577623264SMatthew G. Knepley /*MC 80677623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 80777623264SMatthew G. Knepley 80877623264SMatthew G. Knepley Level: intermediate 80977623264SMatthew G. Knepley 81077623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 81177623264SMatthew G. Knepley M*/ 81277623264SMatthew G. Knepley 81377623264SMatthew G. Knepley #undef __FUNCT__ 81477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Shell" 81577623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 81677623264SMatthew G. Knepley { 81777623264SMatthew G. Knepley PetscPartitioner_Shell *p; 81877623264SMatthew G. Knepley PetscErrorCode ierr; 81977623264SMatthew G. Knepley 82077623264SMatthew G. Knepley PetscFunctionBegin; 82177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 82277623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 82377623264SMatthew G. Knepley part->data = p; 82477623264SMatthew G. Knepley 82577623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 82677623264SMatthew G. Knepley PetscFunctionReturn(0); 82777623264SMatthew G. Knepley } 82877623264SMatthew G. Knepley 82977623264SMatthew G. Knepley #undef __FUNCT__ 8305680f57bSMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellSetPartition" 8315680f57bSMatthew G. Knepley /*@C 8325680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 8335680f57bSMatthew G. Knepley 8345680f57bSMatthew G. Knepley Collective on DM 8355680f57bSMatthew G. Knepley 8365680f57bSMatthew G. Knepley Input Parameters: 8375680f57bSMatthew G. Knepley + part - The PetscPartitioner 8385680f57bSMatthew G. Knepley . dm - The mesh DM 8395680f57bSMatthew G. Knepley - enlarge - Expand each partition with neighbors 8405680f57bSMatthew G. Knepley 8415680f57bSMatthew G. Knepley Level: developer 8425680f57bSMatthew G. Knepley 8435680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 8445680f57bSMatthew G. Knepley @*/ 8455680f57bSMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt numProcs, const PetscInt sizes[], const PetscInt points[]) 8465680f57bSMatthew G. Knepley { 8475680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 8485680f57bSMatthew G. Knepley PetscInt proc, numPoints; 8495680f57bSMatthew G. Knepley PetscErrorCode ierr; 8505680f57bSMatthew G. Knepley 8515680f57bSMatthew G. Knepley PetscFunctionBegin; 8525680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8535680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 8545680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(points, 4);} 8555680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 8565680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 8575680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 8585680f57bSMatthew G. Knepley ierr = PetscSectionSetChart(p->section, 0, numProcs);CHKERRQ(ierr); 8595680f57bSMatthew G. Knepley if (sizes) { 8605680f57bSMatthew G. Knepley for (proc = 0; proc < numProcs; ++proc) { 8615680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 8625680f57bSMatthew G. Knepley } 8635680f57bSMatthew G. Knepley } 8645680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 8655680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 8665680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 8675680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8685680f57bSMatthew G. Knepley } 8695680f57bSMatthew G. Knepley 8705680f57bSMatthew G. Knepley #undef __FUNCT__ 87177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Chaco" 87277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 87377623264SMatthew G. Knepley { 87477623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 87577623264SMatthew G. Knepley PetscErrorCode ierr; 87677623264SMatthew G. Knepley 87777623264SMatthew G. Knepley PetscFunctionBegin; 87877623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 87977623264SMatthew G. Knepley PetscFunctionReturn(0); 88077623264SMatthew G. Knepley } 88177623264SMatthew G. Knepley 88277623264SMatthew G. Knepley #undef __FUNCT__ 88377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco_Ascii" 88477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 88577623264SMatthew G. Knepley { 88677623264SMatthew G. Knepley PetscViewerFormat format; 88777623264SMatthew G. Knepley PetscErrorCode ierr; 88877623264SMatthew G. Knepley 88977623264SMatthew G. Knepley PetscFunctionBegin; 89077623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 89177623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Chaco Graph Partitioner:\n");CHKERRQ(ierr); 89277623264SMatthew G. Knepley PetscFunctionReturn(0); 89377623264SMatthew G. Knepley } 89477623264SMatthew G. Knepley 89577623264SMatthew G. Knepley #undef __FUNCT__ 89677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco" 89777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 89877623264SMatthew G. Knepley { 89977623264SMatthew G. Knepley PetscBool iascii; 90077623264SMatthew G. Knepley PetscErrorCode ierr; 90177623264SMatthew G. Knepley 90277623264SMatthew G. Knepley PetscFunctionBegin; 90377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 90477623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 90577623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 90677623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 90777623264SMatthew G. Knepley PetscFunctionReturn(0); 90877623264SMatthew G. Knepley } 90977623264SMatthew G. Knepley 91070034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 91170034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 91270034214SMatthew G. Knepley #include <unistd.h> 91370034214SMatthew G. Knepley #endif 91470034214SMatthew G. Knepley /* Chaco does not have an include file */ 91570034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 91670034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 91770034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 91870034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 91970034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 92070034214SMatthew G. Knepley 92170034214SMatthew G. Knepley extern int FREE_GRAPH; 92277623264SMatthew G. Knepley #endif 92370034214SMatthew G. Knepley 92470034214SMatthew G. Knepley #undef __FUNCT__ 92577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Chaco" 92677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 92770034214SMatthew G. Knepley { 92877623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 92970034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 93070034214SMatthew G. Knepley MPI_Comm comm; 93170034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 93270034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 93370034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 93470034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 93570034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 93670034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 93770034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 93870034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 93970034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 94070034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 94170034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 94270034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 94370034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 94470034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 94570034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 94670034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 94770034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 94870034214SMatthew G. Knepley short int *assignment; /* Output partition */ 94970034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 95070034214SMatthew G. Knepley PetscInt *points; 95170034214SMatthew G. Knepley int i, v, p; 95270034214SMatthew G. Knepley PetscErrorCode ierr; 95370034214SMatthew G. Knepley 95470034214SMatthew G. Knepley PetscFunctionBegin; 95570034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 95670034214SMatthew G. Knepley if (!numVertices) { 95777623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 95877623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 95970034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 96070034214SMatthew G. Knepley PetscFunctionReturn(0); 96170034214SMatthew G. Knepley } 96270034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 96370034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 96470034214SMatthew G. Knepley 96570034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 96670034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 96770034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 96870034214SMatthew G. Knepley } 96977623264SMatthew G. Knepley mesh_dims[0] = nparts; 97070034214SMatthew G. Knepley mesh_dims[1] = 1; 97170034214SMatthew G. Knepley mesh_dims[2] = 1; 97270034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 97370034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 97470034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 97570034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 97670034214SMatthew G. Knepley { 97770034214SMatthew G. Knepley int piperet; 97870034214SMatthew G. Knepley piperet = pipe(fd_pipe); 97970034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 98070034214SMatthew G. Knepley fd_stdout = dup(1); 98170034214SMatthew G. Knepley close(1); 98270034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 98370034214SMatthew G. Knepley } 98470034214SMatthew G. Knepley #endif 98570034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 98670034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 98770034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 98870034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 98970034214SMatthew G. Knepley { 99070034214SMatthew G. Knepley char msgLog[10000]; 99170034214SMatthew G. Knepley int count; 99270034214SMatthew G. Knepley 99370034214SMatthew G. Knepley fflush(stdout); 99470034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 99570034214SMatthew G. Knepley if (count < 0) count = 0; 99670034214SMatthew G. Knepley msgLog[count] = 0; 99770034214SMatthew G. Knepley close(1); 99870034214SMatthew G. Knepley dup2(fd_stdout, 1); 99970034214SMatthew G. Knepley close(fd_stdout); 100070034214SMatthew G. Knepley close(fd_pipe[0]); 100170034214SMatthew G. Knepley close(fd_pipe[1]); 100270034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 100370034214SMatthew G. Knepley } 100470034214SMatthew G. Knepley #endif 100570034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 100677623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 100770034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 100877623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 100970034214SMatthew G. Knepley } 101077623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 101170034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 101277623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 101370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 101470034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 101570034214SMatthew G. Knepley } 101670034214SMatthew G. Knepley } 101770034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 101870034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 101970034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 102070034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 102170034214SMatthew G. Knepley } 102270034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 102370034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 102470034214SMatthew G. Knepley PetscFunctionReturn(0); 102577623264SMatthew G. Knepley #else 102677623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 102770034214SMatthew G. Knepley #endif 102877623264SMatthew G. Knepley } 102977623264SMatthew G. Knepley 103077623264SMatthew G. Knepley #undef __FUNCT__ 103177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Chaco" 103277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 103377623264SMatthew G. Knepley { 103477623264SMatthew G. Knepley PetscFunctionBegin; 103577623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 103677623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 103777623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 103877623264SMatthew G. Knepley PetscFunctionReturn(0); 103977623264SMatthew G. Knepley } 104077623264SMatthew G. Knepley 104177623264SMatthew G. Knepley /*MC 104277623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 104377623264SMatthew G. Knepley 104477623264SMatthew G. Knepley Level: intermediate 104577623264SMatthew G. Knepley 104677623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 104777623264SMatthew G. Knepley M*/ 104877623264SMatthew G. Knepley 104977623264SMatthew G. Knepley #undef __FUNCT__ 105077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Chaco" 105177623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 105277623264SMatthew G. Knepley { 105377623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 105477623264SMatthew G. Knepley PetscErrorCode ierr; 105577623264SMatthew G. Knepley 105677623264SMatthew G. Knepley PetscFunctionBegin; 105777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 105877623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 105977623264SMatthew G. Knepley part->data = p; 106077623264SMatthew G. Knepley 106177623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 106277623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 106377623264SMatthew G. Knepley PetscFunctionReturn(0); 106477623264SMatthew G. Knepley } 106577623264SMatthew G. Knepley 106677623264SMatthew G. Knepley #undef __FUNCT__ 106777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_ParMetis" 106877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 106977623264SMatthew G. Knepley { 107077623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 107177623264SMatthew G. Knepley PetscErrorCode ierr; 107277623264SMatthew G. Knepley 107377623264SMatthew G. Knepley PetscFunctionBegin; 107477623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 107577623264SMatthew G. Knepley PetscFunctionReturn(0); 107677623264SMatthew G. Knepley } 107777623264SMatthew G. Knepley 107877623264SMatthew G. Knepley #undef __FUNCT__ 107977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis_Ascii" 108077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 108177623264SMatthew G. Knepley { 108277623264SMatthew G. Knepley PetscViewerFormat format; 108377623264SMatthew G. Knepley PetscErrorCode ierr; 108477623264SMatthew G. Knepley 108577623264SMatthew G. Knepley PetscFunctionBegin; 108677623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 108777623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis Graph Partitioner:\n");CHKERRQ(ierr); 108877623264SMatthew G. Knepley PetscFunctionReturn(0); 108977623264SMatthew G. Knepley } 109077623264SMatthew G. Knepley 109177623264SMatthew G. Knepley #undef __FUNCT__ 109277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis" 109377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 109477623264SMatthew G. Knepley { 109577623264SMatthew G. Knepley PetscBool iascii; 109677623264SMatthew G. Knepley PetscErrorCode ierr; 109777623264SMatthew G. Knepley 109877623264SMatthew G. Knepley PetscFunctionBegin; 109977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 110077623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 110177623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 110277623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 110377623264SMatthew G. Knepley PetscFunctionReturn(0); 110477623264SMatthew G. Knepley } 110570034214SMatthew G. Knepley 110670034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 110770034214SMatthew G. Knepley #include <parmetis.h> 110877623264SMatthew G. Knepley #endif 110970034214SMatthew G. Knepley 111070034214SMatthew G. Knepley #undef __FUNCT__ 111177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_ParMetis" 111277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 111370034214SMatthew G. Knepley { 111477623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 111570034214SMatthew G. Knepley MPI_Comm comm; 111670034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 111770034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 111870034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 111970034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 112070034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 112170034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 112270034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 112370034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 112470034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 112570034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 112670034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 112770034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 112870034214SMatthew G. Knepley /* Outputs */ 112970034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 113070034214SMatthew G. Knepley PetscInt *assignment, *points; 113177623264SMatthew G. Knepley PetscMPIInt rank, p, v, i; 113270034214SMatthew G. Knepley PetscErrorCode ierr; 113370034214SMatthew G. Knepley 113470034214SMatthew G. Knepley PetscFunctionBegin; 113577623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 113670034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 113770034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 113870034214SMatthew G. Knepley /* Calculate vertex distribution */ 113970034214SMatthew G. Knepley ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 114070034214SMatthew G. Knepley vtxdist[0] = 0; 114170034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 114270034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 114370034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 114470034214SMatthew G. Knepley } 114570034214SMatthew G. Knepley /* Calculate weights */ 114670034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 114770034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 114870034214SMatthew G. Knepley } 114970034214SMatthew G. Knepley ubvec[0] = 1.05; 115070034214SMatthew G. Knepley 115170034214SMatthew G. Knepley if (nparts == 1) { 115270034214SMatthew G. Knepley ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 115370034214SMatthew G. Knepley } else { 115470034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 115570034214SMatthew G. Knepley if (!rank) { 115670034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 115770034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 115870034214SMatthew G. Knepley PetscStackPop; 115970034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 116070034214SMatthew G. Knepley } 116170034214SMatthew G. Knepley } else { 116270034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 116370034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 116470034214SMatthew G. Knepley PetscStackPop; 116570034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 116670034214SMatthew G. Knepley } 116770034214SMatthew G. Knepley } 116870034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 116977623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 117077623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 117177623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 117270034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 117377623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 117470034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 117570034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 117670034214SMatthew G. Knepley } 117770034214SMatthew G. Knepley } 117870034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 117970034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 118070034214SMatthew G. Knepley ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 118170034214SMatthew G. Knepley #else 118277623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 118370034214SMatthew G. Knepley #endif 118477623264SMatthew G. Knepley PetscFunctionReturn(0); 118570034214SMatthew G. Knepley } 118670034214SMatthew G. Knepley 118777623264SMatthew G. Knepley #undef __FUNCT__ 118877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_ParMetis" 118977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 119077623264SMatthew G. Knepley { 119177623264SMatthew G. Knepley PetscFunctionBegin; 119277623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 119377623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 119477623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 119577623264SMatthew G. Knepley PetscFunctionReturn(0); 119677623264SMatthew G. Knepley } 119777623264SMatthew G. Knepley 119877623264SMatthew G. Knepley /*MC 119977623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 120077623264SMatthew G. Knepley 120177623264SMatthew G. Knepley Level: intermediate 120277623264SMatthew G. Knepley 120377623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 120477623264SMatthew G. Knepley M*/ 120577623264SMatthew G. Knepley 120677623264SMatthew G. Knepley #undef __FUNCT__ 120777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_ParMetis" 120877623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 120977623264SMatthew G. Knepley { 121077623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 121177623264SMatthew G. Knepley PetscErrorCode ierr; 121277623264SMatthew G. Knepley 121377623264SMatthew G. Knepley PetscFunctionBegin; 121477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 121577623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 121677623264SMatthew G. Knepley part->data = p; 121777623264SMatthew G. Knepley 121877623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 121977623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 122070034214SMatthew G. Knepley PetscFunctionReturn(0); 122170034214SMatthew G. Knepley } 122270034214SMatthew G. Knepley 122370034214SMatthew G. Knepley #undef __FUNCT__ 12245680f57bSMatthew G. Knepley #define __FUNCT__ "DMPlexGetPartitioner" 12255680f57bSMatthew G. Knepley /*@ 12265680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 12275680f57bSMatthew G. Knepley 12285680f57bSMatthew G. Knepley Not collective 12295680f57bSMatthew G. Knepley 12305680f57bSMatthew G. Knepley Input Parameter: 12315680f57bSMatthew G. Knepley . dm - The DM 12325680f57bSMatthew G. Knepley 12335680f57bSMatthew G. Knepley Output Parameter: 12345680f57bSMatthew G. Knepley . part - The PetscPartitioner 12355680f57bSMatthew G. Knepley 12365680f57bSMatthew G. Knepley Level: developer 12375680f57bSMatthew G. Knepley 12385680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 12395680f57bSMatthew G. Knepley @*/ 12405680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 12415680f57bSMatthew G. Knepley { 12425680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 12435680f57bSMatthew G. Knepley 12445680f57bSMatthew G. Knepley PetscFunctionBegin; 12455680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12465680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 12475680f57bSMatthew G. Knepley *part = mesh->partitioner; 12485680f57bSMatthew G. Knepley PetscFunctionReturn(0); 12495680f57bSMatthew G. Knepley } 12505680f57bSMatthew G. Knepley 12515680f57bSMatthew G. Knepley #undef __FUNCT__ 12529ffc88e4SToby Isaac #define __FUNCT__ "DMPlexMarkTreeClosure" 12539ffc88e4SToby Isaac static PetscErrorCode DMPlexMarkTreeClosure(DM dm, PetscSegBuffer segpart, PetscBT bt, PetscInt point, PetscInt *partSize) 12549ffc88e4SToby Isaac { 12559ffc88e4SToby Isaac PetscInt parent, closureSize, *closure = NULL, i, pStart, pEnd; 12569ffc88e4SToby Isaac PetscErrorCode ierr; 12579ffc88e4SToby Isaac 12589ffc88e4SToby Isaac PetscFunctionBegin; 12599ffc88e4SToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 12609ffc88e4SToby Isaac if (parent == point) PetscFunctionReturn(0); 12619ffc88e4SToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12629ffc88e4SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 12639ffc88e4SToby Isaac for (i = 0; i < closureSize; i++) { 12649ffc88e4SToby Isaac PetscInt cpoint = closure[2*i]; 12659ffc88e4SToby Isaac 12669ffc88e4SToby Isaac if (!PetscBTLookupSet(bt,cpoint-pStart)) { 12679ffc88e4SToby Isaac PetscInt *PETSC_RESTRICT pt; 12689ffc88e4SToby Isaac (*partSize)++; 12699ffc88e4SToby Isaac ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 12709ffc88e4SToby Isaac *pt = cpoint; 12719ffc88e4SToby Isaac } 12729ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,partSize);CHKERRQ(ierr); 12739ffc88e4SToby Isaac } 12749ffc88e4SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 12759ffc88e4SToby Isaac PetscFunctionReturn(0); 12769ffc88e4SToby Isaac } 12779ffc88e4SToby Isaac 12789ffc88e4SToby Isaac #undef __FUNCT__ 127970034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreatePartitionClosure" 128070034214SMatthew G. Knepley PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 128170034214SMatthew G. Knepley { 128270034214SMatthew G. Knepley /* const PetscInt height = 0; */ 128370034214SMatthew G. Knepley const PetscInt *partArray; 128470034214SMatthew G. Knepley PetscInt *allPoints, *packPoints; 128570034214SMatthew G. Knepley PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 128670034214SMatthew G. Knepley PetscErrorCode ierr; 128770034214SMatthew G. Knepley PetscBT bt; 128870034214SMatthew G. Knepley PetscSegBuffer segpack,segpart; 128970034214SMatthew G. Knepley 129070034214SMatthew G. Knepley PetscFunctionBegin; 129170034214SMatthew G. Knepley ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 129270034214SMatthew G. Knepley ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 129370034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 129470034214SMatthew G. Knepley ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 129570034214SMatthew G. Knepley ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 129670034214SMatthew G. Knepley ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 129770034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 129870034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 129970034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 130070034214SMatthew G. Knepley PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 130170034214SMatthew G. Knepley 130270034214SMatthew G. Knepley ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 130370034214SMatthew G. Knepley ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 130470034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 130570034214SMatthew G. Knepley PetscInt point = partArray[offset+p], closureSize, c; 130670034214SMatthew G. Knepley PetscInt *closure = NULL; 130770034214SMatthew G. Knepley 130870034214SMatthew G. Knepley /* TODO Include support for height > 0 case */ 130970034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 131070034214SMatthew G. Knepley for (c=0; c<closureSize; c++) { 131170034214SMatthew G. Knepley PetscInt cpoint = closure[c*2]; 131270034214SMatthew G. Knepley if (!PetscBTLookupSet(bt,cpoint-pStart)) { 131370034214SMatthew G. Knepley PetscInt *PETSC_RESTRICT pt; 131470034214SMatthew G. Knepley partSize++; 131570034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 131670034214SMatthew G. Knepley *pt = cpoint; 131770034214SMatthew G. Knepley } 13189ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,&partSize);CHKERRQ(ierr); 131970034214SMatthew G. Knepley } 132070034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 132170034214SMatthew G. Knepley } 132270034214SMatthew G. Knepley ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 132370034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 132470034214SMatthew G. Knepley ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 132570034214SMatthew G. Knepley ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 132670034214SMatthew G. Knepley for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 132770034214SMatthew G. Knepley } 132870034214SMatthew G. Knepley ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 132970034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 133070034214SMatthew G. Knepley 133170034214SMatthew G. Knepley ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 133270034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 133370034214SMatthew G. Knepley ierr = PetscMalloc1(newSize, &allPoints);CHKERRQ(ierr); 133470034214SMatthew G. Knepley 133570034214SMatthew G. Knepley ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 133670034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 133770034214SMatthew G. Knepley PetscInt numPoints, offset; 133870034214SMatthew G. Knepley 133970034214SMatthew G. Knepley ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 134070034214SMatthew G. Knepley ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 134170034214SMatthew G. Knepley ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 134270034214SMatthew G. Knepley packPoints += numPoints; 134370034214SMatthew G. Knepley } 134470034214SMatthew G. Knepley 134570034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 134670034214SMatthew G. Knepley ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 134770034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 134870034214SMatthew G. Knepley PetscFunctionReturn(0); 134970034214SMatthew G. Knepley } 1350aa3148a8SMichael Lange 1351aa3148a8SMichael Lange #undef __FUNCT__ 13525abbe4feSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelClosure" 13535abbe4feSMichael Lange /*@ 13545abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 13555abbe4feSMichael Lange 13565abbe4feSMichael Lange Input Parameters: 13575abbe4feSMichael Lange + dm - The DM 13585abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 13595abbe4feSMichael Lange 13605abbe4feSMichael Lange Level: developer 13615abbe4feSMichael Lange 13625abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 13635abbe4feSMichael Lange @*/ 13645abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 13655abbe4feSMichael Lange { 13665abbe4feSMichael Lange IS rankIS, pointIS; 13675abbe4feSMichael Lange const PetscInt *ranks, *points; 13685abbe4feSMichael Lange PetscInt numRanks, numPoints, r, p, c, closureSize; 13695abbe4feSMichael Lange PetscInt *closure = NULL; 13705abbe4feSMichael Lange PetscErrorCode ierr; 13715abbe4feSMichael Lange 13725abbe4feSMichael Lange PetscFunctionBegin; 13735abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 13745abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 13755abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 13765abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 13775abbe4feSMichael Lange const PetscInt rank = ranks[r]; 13785abbe4feSMichael Lange 13795abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 13805abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 13815abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 13825abbe4feSMichael Lange for (p = 0; p < numPoints; ++p) { 13835abbe4feSMichael Lange ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 13845abbe4feSMichael Lange for (c = 0; c < closureSize*2; c += 2) {ierr = DMLabelSetValue(label, closure[c], rank);CHKERRQ(ierr);} 13855abbe4feSMichael Lange } 13865abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 13875abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 13885abbe4feSMichael Lange } 13895abbe4feSMichael Lange if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);} 13905abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 13915abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 13925abbe4feSMichael Lange PetscFunctionReturn(0); 13935abbe4feSMichael Lange } 13945abbe4feSMichael Lange 13955abbe4feSMichael Lange #undef __FUNCT__ 139624d039d7SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelAdjacency" 139724d039d7SMichael Lange /*@ 139824d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 139924d039d7SMichael Lange 140024d039d7SMichael Lange Input Parameters: 140124d039d7SMichael Lange + dm - The DM 140224d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 140324d039d7SMichael Lange 140424d039d7SMichael Lange Level: developer 140524d039d7SMichael Lange 140624d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 140724d039d7SMichael Lange @*/ 140824d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 140924d039d7SMichael Lange { 141024d039d7SMichael Lange IS rankIS, pointIS; 141124d039d7SMichael Lange const PetscInt *ranks, *points; 141224d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 141324d039d7SMichael Lange PetscInt *adj = NULL; 141424d039d7SMichael Lange PetscErrorCode ierr; 141524d039d7SMichael Lange 141624d039d7SMichael Lange PetscFunctionBegin; 141724d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 141824d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 141924d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 142024d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 142124d039d7SMichael Lange const PetscInt rank = ranks[r]; 142224d039d7SMichael Lange 142324d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 142424d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 142524d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 142624d039d7SMichael Lange for (p = 0; p < numPoints; ++p) { 142724d039d7SMichael Lange adjSize = PETSC_DETERMINE; 142824d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 142924d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 143024d039d7SMichael Lange } 143124d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 143224d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 143324d039d7SMichael Lange } 143424d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 143524d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 143624d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 143724d039d7SMichael Lange PetscFunctionReturn(0); 143824d039d7SMichael Lange } 143924d039d7SMichael Lange 144024d039d7SMichael Lange #undef __FUNCT__ 14411fd9873aSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelInvert" 14421fd9873aSMichael Lange /*@ 14431fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 14441fd9873aSMichael Lange 14451fd9873aSMichael Lange Input Parameters: 14461fd9873aSMichael Lange + dm - The DM 14471fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 14481fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 14491fd9873aSMichael Lange 14501fd9873aSMichael Lange Output Parameter: 14511fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 14521fd9873aSMichael Lange 14531fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 14541fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 14551fd9873aSMichael Lange 14561fd9873aSMichael Lange Level: developer 14571fd9873aSMichael Lange 14581fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 14591fd9873aSMichael Lange @*/ 14601fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 14611fd9873aSMichael Lange { 14621fd9873aSMichael Lange MPI_Comm comm; 14631fd9873aSMichael Lange PetscMPIInt rank, numProcs; 14641fd9873aSMichael Lange PetscInt p, n, numNeighbors, size, l, nleaves; 14651fd9873aSMichael Lange PetscSF sfPoint; 14661fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 14671fd9873aSMichael Lange PetscSection rootSection, leafSection; 14681fd9873aSMichael Lange const PetscSFNode *remote; 14691fd9873aSMichael Lange const PetscInt *local, *neighbors; 14701fd9873aSMichael Lange IS valueIS; 14711fd9873aSMichael Lange PetscErrorCode ierr; 14721fd9873aSMichael Lange 14731fd9873aSMichael Lange PetscFunctionBegin; 14741fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 14751fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 14761fd9873aSMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 14771fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 14781fd9873aSMichael Lange 14791fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 14801fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 14811fd9873aSMichael Lange ierr = PetscSectionSetChart(rootSection, 0, numProcs);CHKERRQ(ierr); 14821fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 14831fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 14841fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 14851fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 14861fd9873aSMichael Lange PetscInt numPoints; 14871fd9873aSMichael Lange 14881fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 14891fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 14901fd9873aSMichael Lange } 14911fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 14921fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 14931fd9873aSMichael Lange ierr = PetscMalloc1(size, &rootPoints);CHKERRQ(ierr); 14941fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 14951fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 14961fd9873aSMichael Lange IS pointIS; 14971fd9873aSMichael Lange const PetscInt *points; 14981fd9873aSMichael Lange PetscInt off, numPoints, p; 14991fd9873aSMichael Lange 15001fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 15011fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 15021fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 15031fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 15041fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1505f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1506f8987ae8SMichael Lange else {l = -1;} 15071fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 15081fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 15091fd9873aSMichael Lange } 15101fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 15111fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 15121fd9873aSMichael Lange } 15131fd9873aSMichael Lange ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 15141fd9873aSMichael Lange ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 15151fd9873aSMichael Lange /* Communicate overlap */ 15161fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr); 15171fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 15181fd9873aSMichael Lange /* Filter remote contributions (ovLeafPoints) into the overlapSF */ 15191fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 15201fd9873aSMichael Lange for (p = 0; p < size; p++) { 15211fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 15221fd9873aSMichael Lange } 15231fd9873aSMichael Lange ierr = PetscFree(rootPoints);CHKERRQ(ierr); 15241fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 15251fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 15261fd9873aSMichael Lange ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 15271fd9873aSMichael Lange PetscFunctionReturn(0); 15281fd9873aSMichael Lange } 15291fd9873aSMichael Lange 15301fd9873aSMichael Lange #undef __FUNCT__ 1531aa3148a8SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelCreateSF" 1532aa3148a8SMichael Lange /*@ 1533aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1534aa3148a8SMichael Lange 1535aa3148a8SMichael Lange Input Parameters: 1536aa3148a8SMichael Lange + dm - The DM 1537aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 1538aa3148a8SMichael Lange 1539aa3148a8SMichael Lange Output Parameter: 1540aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 1541aa3148a8SMichael Lange 1542aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1543aa3148a8SMichael Lange 1544aa3148a8SMichael Lange Level: developer 1545aa3148a8SMichael Lange 1546aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 1547aa3148a8SMichael Lange @*/ 1548aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1549aa3148a8SMichael Lange { 1550aa3148a8SMichael Lange PetscMPIInt numProcs; 1551aa3148a8SMichael Lange PetscInt n, idx, numRemote, p, numPoints, pStart, pEnd; 1552aa3148a8SMichael Lange PetscSFNode *remotePoints; 1553aa3148a8SMichael Lange PetscErrorCode ierr; 1554aa3148a8SMichael Lange 1555aa3148a8SMichael Lange PetscFunctionBegin; 1556aa3148a8SMichael Lange ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 1557aa3148a8SMichael Lange 1558aa3148a8SMichael Lange for (numRemote = 0, n = 0; n < numProcs; ++n) { 1559aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1560aa3148a8SMichael Lange numRemote += numPoints; 1561aa3148a8SMichael Lange } 1562aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 1563aa3148a8SMichael Lange for (idx = 0, n = 0; n < numProcs; ++n) { 1564aa3148a8SMichael Lange IS remoteRootIS; 1565aa3148a8SMichael Lange const PetscInt *remoteRoots; 1566aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1567aa3148a8SMichael Lange if (numPoints <= 0) continue; 1568aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 1569aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1570aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1571aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 1572aa3148a8SMichael Lange remotePoints[idx].rank = n; 1573aa3148a8SMichael Lange idx++; 1574aa3148a8SMichael Lange } 1575aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1576aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1577aa3148a8SMichael Lange } 1578aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1579aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1580aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 1581aa3148a8SMichael Lange PetscFunctionReturn(0); 1582aa3148a8SMichael Lange } 1583