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__ 30532c4e7dSMichael Lange #define __FUNCT__ "DMPlexCreatePartitionerGraph" 31532c4e7dSMichael Lange /*@C 32532c4e7dSMichael Lange DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 33532c4e7dSMichael Lange 34532c4e7dSMichael Lange Input Parameters: 35532c4e7dSMichael Lange + dm - The mesh DM dm 36532c4e7dSMichael Lange - height - Height of the strata from which to construct the graph 37532c4e7dSMichael Lange 38532c4e7dSMichael Lange Output Parameter: 39532c4e7dSMichael Lange + numVertices - Number of vertices in the graph 40532c4e7dSMichael Lange - offsets - Point offsets in the graph 41532c4e7dSMichael Lange - adjacency - Point connectivity in the graph 42532c4e7dSMichael Lange 43532c4e7dSMichael Lange The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and 44532c4e7dSMichael Lange DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function 45532c4e7dSMichael Lange representation on the mesh. 46532c4e7dSMichael Lange 47532c4e7dSMichael Lange Level: developer 48532c4e7dSMichael Lange 49532c4e7dSMichael Lange .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure() 50532c4e7dSMichael Lange @*/ 51532c4e7dSMichael Lange PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 52532c4e7dSMichael Lange { 53*43f7d02bSMichael Lange PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 54532c4e7dSMichael Lange PetscInt *adj = NULL, *vOffsets = NULL; 558cfe4c1fSMichael Lange IS cellNumbering; 568cfe4c1fSMichael Lange const PetscInt *cellNum; 57532c4e7dSMichael Lange PetscBool useCone, useClosure; 58532c4e7dSMichael Lange PetscSection section; 59532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 608cfe4c1fSMichael Lange PetscSF sfPoint; 61532c4e7dSMichael Lange PetscMPIInt rank; 62532c4e7dSMichael Lange PetscErrorCode ierr; 63532c4e7dSMichael Lange 64532c4e7dSMichael Lange PetscFunctionBegin; 65532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 66532c4e7dSMichael Lange ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 678cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 688cfe4c1fSMichael Lange ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 69532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 70532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 71532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 72532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 73532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 74532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 75532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 76532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 77532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr); 788cfe4c1fSMichael Lange if (nroots > 0) { 798cfe4c1fSMichael Lange ierr = DMPlexGetCellNumbering(dm, &cellNumbering);CHKERRQ(ierr); 808cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 818cfe4c1fSMichael Lange } 828cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 838cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 848cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 85532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 86532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 87532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 88532c4e7dSMichael Lange const PetscInt point = adj[a]; 89532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 90532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 91532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 92532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 93532c4e7dSMichael Lange *pBuf = point; 94532c4e7dSMichael Lange } 95532c4e7dSMichael Lange } 968cfe4c1fSMichael Lange (*numVertices)++; 97532c4e7dSMichael Lange } 98532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 99532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr); 100532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 101532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 102532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 103532c4e7dSMichael Lange ierr = PetscMalloc2(*numVertices+1, &vOffsets, size, adjacency);CHKERRQ(ierr); 104*43f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 105*43f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 106*43f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 107*43f7d02bSMichael Lange } 108532c4e7dSMichael Lange vOffsets[*numVertices] = size; 109532c4e7dSMichael Lange if (offsets) *offsets = vOffsets; 1108cfe4c1fSMichael Lange if (adjacency) { 1118cfe4c1fSMichael Lange ierr = PetscSegBufferExtractTo(adjBuffer, *adjacency);CHKERRQ(ierr); 1128cfe4c1fSMichael Lange if (nroots > 0) { 1138cfe4c1fSMichael Lange ISLocalToGlobalMapping ltogCells; 1148cfe4c1fSMichael Lange PetscInt n, size, *cells_arr; 1158cfe4c1fSMichael Lange /* In parallel, apply a global cell numbering to the graph */ 1168cfe4c1fSMichael Lange ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 1178cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingCreateIS(cellNumbering, <ogCells);CHKERRQ(ierr); 1188cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetSize(ltogCells, &size);CHKERRQ(ierr); 1198cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 1208cfe4c1fSMichael Lange /* Convert to positive global cell numbers */ 1218cfe4c1fSMichael Lange for (n=0; n<size; n++) {if (cells_arr[n] < 0) cells_arr[n] = -(cells_arr[n]+1);} 1228cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingRestoreIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 1238cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingApplyBlock(ltogCells, vOffsets[*numVertices], *adjacency, *adjacency);CHKERRQ(ierr); 1248cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingDestroy(<ogCells);CHKERRQ(ierr); 1258cfe4c1fSMichael Lange } 1268cfe4c1fSMichael Lange } 127532c4e7dSMichael Lange /* Clean up */ 128532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 129532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 130532c4e7dSMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 131532c4e7dSMichael Lange PetscFunctionReturn(0); 132532c4e7dSMichael Lange } 133532c4e7dSMichael Lange 134532c4e7dSMichael Lange #undef __FUNCT__ 13570034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 13670034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 13770034214SMatthew G. Knepley { 13870034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 13970034214SMatthew G. Knepley PetscInt numFaceCases = 0; 14070034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 14170034214SMatthew G. Knepley PetscInt *off, *adj; 14270034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 14370034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 14470034214SMatthew G. Knepley PetscErrorCode ierr; 14570034214SMatthew G. Knepley 14670034214SMatthew G. Knepley PetscFunctionBegin; 14770034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 148c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 14970034214SMatthew G. Knepley cellDim = dim - cellHeight; 15070034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 15170034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 15270034214SMatthew G. Knepley if (cEnd - cStart == 0) { 15370034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 15470034214SMatthew G. Knepley if (offsets) *offsets = NULL; 15570034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 15670034214SMatthew G. Knepley PetscFunctionReturn(0); 15770034214SMatthew G. Knepley } 15870034214SMatthew G. Knepley numCells = cEnd - cStart; 15970034214SMatthew G. Knepley faceDepth = depth - cellHeight; 16070034214SMatthew G. Knepley if (dim == depth) { 16170034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 16270034214SMatthew G. Knepley 16370034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 16470034214SMatthew G. Knepley /* Count neighboring cells */ 16570034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 16670034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 16770034214SMatthew G. Knepley const PetscInt *support; 16870034214SMatthew G. Knepley PetscInt supportSize; 16970034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 17070034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 17170034214SMatthew G. Knepley if (supportSize == 2) { 1729ffc88e4SToby Isaac PetscInt numChildren; 1739ffc88e4SToby Isaac 1749ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1759ffc88e4SToby Isaac if (!numChildren) { 17670034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 17770034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 17870034214SMatthew G. Knepley } 17970034214SMatthew G. Knepley } 1809ffc88e4SToby Isaac } 18170034214SMatthew G. Knepley /* Prefix sum */ 18270034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 18370034214SMatthew G. Knepley if (adjacency) { 18470034214SMatthew G. Knepley PetscInt *tmp; 18570034214SMatthew G. Knepley 18670034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 18770034214SMatthew G. Knepley ierr = PetscMalloc1((numCells+1), &tmp);CHKERRQ(ierr); 18870034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 18970034214SMatthew G. Knepley /* Get neighboring cells */ 19070034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 19170034214SMatthew G. Knepley const PetscInt *support; 19270034214SMatthew G. Knepley PetscInt supportSize; 19370034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 19470034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 19570034214SMatthew G. Knepley if (supportSize == 2) { 1969ffc88e4SToby Isaac PetscInt numChildren; 1979ffc88e4SToby Isaac 1989ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1999ffc88e4SToby Isaac if (!numChildren) { 20070034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 20170034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 20270034214SMatthew G. Knepley } 20370034214SMatthew G. Knepley } 2049ffc88e4SToby Isaac } 20570034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 20670034214SMatthew 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); 20770034214SMatthew G. Knepley #endif 20870034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 20970034214SMatthew G. Knepley } 21070034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 21170034214SMatthew G. Knepley if (offsets) *offsets = off; 21270034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 21370034214SMatthew G. Knepley PetscFunctionReturn(0); 21470034214SMatthew G. Knepley } 21570034214SMatthew G. Knepley /* Setup face recognition */ 21670034214SMatthew G. Knepley if (faceDepth == 1) { 21770034214SMatthew 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 */ 21870034214SMatthew G. Knepley 21970034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 22070034214SMatthew G. Knepley PetscInt corners; 22170034214SMatthew G. Knepley 22270034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 22370034214SMatthew G. Knepley if (!cornersSeen[corners]) { 22470034214SMatthew G. Knepley PetscInt nFV; 22570034214SMatthew G. Knepley 22670034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 22770034214SMatthew G. Knepley cornersSeen[corners] = 1; 22870034214SMatthew G. Knepley 22970034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 23070034214SMatthew G. Knepley 23170034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 23270034214SMatthew G. Knepley } 23370034214SMatthew G. Knepley } 23470034214SMatthew G. Knepley } 23570034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 23670034214SMatthew G. Knepley /* Count neighboring cells */ 23770034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 23870034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 23970034214SMatthew G. Knepley 2408b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 24170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 24270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 24370034214SMatthew G. Knepley PetscInt cellPair[2]; 24470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 24570034214SMatthew G. Knepley PetscInt meetSize = 0; 24670034214SMatthew G. Knepley const PetscInt *meet = NULL; 24770034214SMatthew G. Knepley 24870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 24970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 25070034214SMatthew G. Knepley if (!found) { 25170034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 25270034214SMatthew G. Knepley if (meetSize) { 25370034214SMatthew G. Knepley PetscInt f; 25470034214SMatthew G. Knepley 25570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 25670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 25770034214SMatthew G. Knepley found = PETSC_TRUE; 25870034214SMatthew G. Knepley break; 25970034214SMatthew G. Knepley } 26070034214SMatthew G. Knepley } 26170034214SMatthew G. Knepley } 26270034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 26370034214SMatthew G. Knepley } 26470034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 26570034214SMatthew G. Knepley } 26670034214SMatthew G. Knepley } 26770034214SMatthew G. Knepley /* Prefix sum */ 26870034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 26970034214SMatthew G. Knepley 27070034214SMatthew G. Knepley if (adjacency) { 27170034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 27270034214SMatthew G. Knepley /* Get neighboring cells */ 27370034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 27470034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 27570034214SMatthew G. Knepley PetscInt cellOffset = 0; 27670034214SMatthew G. Knepley 2778b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 27870034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 27970034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 28070034214SMatthew G. Knepley PetscInt cellPair[2]; 28170034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 28270034214SMatthew G. Knepley PetscInt meetSize = 0; 28370034214SMatthew G. Knepley const PetscInt *meet = NULL; 28470034214SMatthew G. Knepley 28570034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 28670034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 28770034214SMatthew G. Knepley if (!found) { 28870034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 28970034214SMatthew G. Knepley if (meetSize) { 29070034214SMatthew G. Knepley PetscInt f; 29170034214SMatthew G. Knepley 29270034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 29370034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 29470034214SMatthew G. Knepley found = PETSC_TRUE; 29570034214SMatthew G. Knepley break; 29670034214SMatthew G. Knepley } 29770034214SMatthew G. Knepley } 29870034214SMatthew G. Knepley } 29970034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 30070034214SMatthew G. Knepley } 30170034214SMatthew G. Knepley if (found) { 30270034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 30370034214SMatthew G. Knepley ++cellOffset; 30470034214SMatthew G. Knepley } 30570034214SMatthew G. Knepley } 30670034214SMatthew G. Knepley } 30770034214SMatthew G. Knepley } 30870034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 30970034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 31070034214SMatthew G. Knepley if (offsets) *offsets = off; 31170034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 31270034214SMatthew G. Knepley PetscFunctionReturn(0); 31370034214SMatthew G. Knepley } 31470034214SMatthew G. Knepley 31577623264SMatthew G. Knepley #undef __FUNCT__ 31677623264SMatthew G. Knepley #define __FUNCT__ "DMPlexEnlargePartition" 31777623264SMatthew G. Knepley /* Expand the partition by BFS on the adjacency graph */ 31877623264SMatthew G. Knepley PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection partSection, IS *partition) 31977623264SMatthew G. Knepley { 32077623264SMatthew G. Knepley PetscHashI h; 32177623264SMatthew G. Knepley const PetscInt *points; 32277623264SMatthew G. Knepley PetscInt **tmpPoints, *newPoints, totPoints = 0; 32377623264SMatthew G. Knepley PetscInt pStart, pEnd, part, q; 32477623264SMatthew G. Knepley PetscBool useCone; 32577623264SMatthew G. Knepley PetscErrorCode ierr; 32677623264SMatthew G. Knepley 32777623264SMatthew G. Knepley PetscFunctionBegin; 32877623264SMatthew G. Knepley PetscHashICreate(h); 32977623264SMatthew G. Knepley ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 33077623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, pStart, pEnd);CHKERRQ(ierr); 33177623264SMatthew G. Knepley ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 33277623264SMatthew G. Knepley ierr = PetscMalloc1((pEnd - pStart), &tmpPoints);CHKERRQ(ierr); 33377623264SMatthew G. Knepley ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 33477623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 33577623264SMatthew G. Knepley for (part = pStart; part < pEnd; ++part) { 33677623264SMatthew G. Knepley PetscInt *adj = NULL; 33777623264SMatthew G. Knepley PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 33877623264SMatthew G. Knepley 33977623264SMatthew G. Knepley PetscHashIClear(h); 34077623264SMatthew G. Knepley ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 34177623264SMatthew G. Knepley ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 34277623264SMatthew G. Knepley /* Add all existing points to h */ 34377623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 34477623264SMatthew G. Knepley const PetscInt point = points[off+p]; 34577623264SMatthew G. Knepley PetscHashIAdd(h, point, 1); 34677623264SMatthew G. Knepley } 34777623264SMatthew G. Knepley PetscHashISize(h, nP); 34877623264SMatthew 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); 34977623264SMatthew G. Knepley /* Add all points in next BFS level */ 35077623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 35177623264SMatthew G. Knepley const PetscInt point = points[off+p]; 35277623264SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 35377623264SMatthew G. Knepley 35477623264SMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, point, &adjSize, &adj);CHKERRQ(ierr); 35577623264SMatthew G. Knepley for (a = 0; a < adjSize; ++a) PetscHashIAdd(h, adj[a], 1); 35677623264SMatthew G. Knepley } 35777623264SMatthew G. Knepley PetscHashISize(h, numNewPoints); 35877623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, part, numNewPoints);CHKERRQ(ierr); 35977623264SMatthew G. Knepley ierr = PetscMalloc1(numNewPoints, &tmpPoints[part]);CHKERRQ(ierr); 36077623264SMatthew G. Knepley ierr = PetscHashIGetKeys(h, &n, tmpPoints[part]);CHKERRQ(ierr); 36177623264SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 36277623264SMatthew G. Knepley totPoints += numNewPoints; 36377623264SMatthew G. Knepley } 36477623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 36577623264SMatthew G. Knepley ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 36677623264SMatthew G. Knepley PetscHashIDestroy(h); 36777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 36877623264SMatthew G. Knepley ierr = PetscMalloc1(totPoints, &newPoints);CHKERRQ(ierr); 36977623264SMatthew G. Knepley for (part = pStart, q = 0; part < pEnd; ++part) { 37077623264SMatthew G. Knepley PetscInt numPoints, p; 37177623264SMatthew G. Knepley 37277623264SMatthew G. Knepley ierr = PetscSectionGetDof(partSection, part, &numPoints);CHKERRQ(ierr); 37377623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 37477623264SMatthew G. Knepley ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 37577623264SMatthew G. Knepley } 37677623264SMatthew G. Knepley ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 37777623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 37877623264SMatthew G. Knepley PetscFunctionReturn(0); 37977623264SMatthew G. Knepley } 38077623264SMatthew G. Knepley 38177623264SMatthew G. Knepley #undef __FUNCT__ 38277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerRegister" 38377623264SMatthew G. Knepley /*@C 38477623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 38577623264SMatthew G. Knepley 38677623264SMatthew G. Knepley Not Collective 38777623264SMatthew G. Knepley 38877623264SMatthew G. Knepley Input Parameters: 38977623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 39077623264SMatthew G. Knepley - create_func - The creation routine itself 39177623264SMatthew G. Knepley 39277623264SMatthew G. Knepley Notes: 39377623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 39477623264SMatthew G. Knepley 39577623264SMatthew G. Knepley Sample usage: 39677623264SMatthew G. Knepley .vb 39777623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 39877623264SMatthew G. Knepley .ve 39977623264SMatthew G. Knepley 40077623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 40177623264SMatthew G. Knepley .vb 40277623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 40377623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 40477623264SMatthew G. Knepley .ve 40577623264SMatthew G. Knepley or at runtime via the option 40677623264SMatthew G. Knepley .vb 40777623264SMatthew G. Knepley -petscpartitioner_type my_part 40877623264SMatthew G. Knepley .ve 40977623264SMatthew G. Knepley 41077623264SMatthew G. Knepley Level: advanced 41177623264SMatthew G. Knepley 41277623264SMatthew G. Knepley .keywords: PetscPartitioner, register 41377623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 41477623264SMatthew G. Knepley 41577623264SMatthew G. Knepley @*/ 41677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 41777623264SMatthew G. Knepley { 41877623264SMatthew G. Knepley PetscErrorCode ierr; 41977623264SMatthew G. Knepley 42077623264SMatthew G. Knepley PetscFunctionBegin; 42177623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 42277623264SMatthew G. Knepley PetscFunctionReturn(0); 42377623264SMatthew G. Knepley } 42477623264SMatthew G. Knepley 42577623264SMatthew G. Knepley #undef __FUNCT__ 42677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetType" 42777623264SMatthew G. Knepley /*@C 42877623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 42977623264SMatthew G. Knepley 43077623264SMatthew G. Knepley Collective on PetscPartitioner 43177623264SMatthew G. Knepley 43277623264SMatthew G. Knepley Input Parameters: 43377623264SMatthew G. Knepley + part - The PetscPartitioner object 43477623264SMatthew G. Knepley - name - The kind of partitioner 43577623264SMatthew G. Knepley 43677623264SMatthew G. Knepley Options Database Key: 43777623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 43877623264SMatthew G. Knepley 43977623264SMatthew G. Knepley Level: intermediate 44077623264SMatthew G. Knepley 44177623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 44277623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 44377623264SMatthew G. Knepley @*/ 44477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 44577623264SMatthew G. Knepley { 44677623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 44777623264SMatthew G. Knepley PetscBool match; 44877623264SMatthew G. Knepley PetscErrorCode ierr; 44977623264SMatthew G. Knepley 45077623264SMatthew G. Knepley PetscFunctionBegin; 45177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 45277623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 45377623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 45477623264SMatthew G. Knepley 45577623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 45677623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 45777623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 45877623264SMatthew G. Knepley 45977623264SMatthew G. Knepley if (part->ops->destroy) { 46077623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 46177623264SMatthew G. Knepley part->ops->destroy = NULL; 46277623264SMatthew G. Knepley } 46377623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 46477623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 46577623264SMatthew G. Knepley PetscFunctionReturn(0); 46677623264SMatthew G. Knepley } 46777623264SMatthew G. Knepley 46877623264SMatthew G. Knepley #undef __FUNCT__ 46977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerGetType" 47077623264SMatthew G. Knepley /*@C 47177623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 47277623264SMatthew G. Knepley 47377623264SMatthew G. Knepley Not Collective 47477623264SMatthew G. Knepley 47577623264SMatthew G. Knepley Input Parameter: 47677623264SMatthew G. Knepley . part - The PetscPartitioner 47777623264SMatthew G. Knepley 47877623264SMatthew G. Knepley Output Parameter: 47977623264SMatthew G. Knepley . name - The PetscPartitioner type name 48077623264SMatthew G. Knepley 48177623264SMatthew G. Knepley Level: intermediate 48277623264SMatthew G. Knepley 48377623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 48477623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 48577623264SMatthew G. Knepley @*/ 48677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 48777623264SMatthew G. Knepley { 48877623264SMatthew G. Knepley PetscErrorCode ierr; 48977623264SMatthew G. Knepley 49077623264SMatthew G. Knepley PetscFunctionBegin; 49177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 49277623264SMatthew G. Knepley PetscValidPointer(name, 2); 49377623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 49477623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 49577623264SMatthew G. Knepley PetscFunctionReturn(0); 49677623264SMatthew G. Knepley } 49777623264SMatthew G. Knepley 49877623264SMatthew G. Knepley #undef __FUNCT__ 49977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView" 50077623264SMatthew G. Knepley /*@C 50177623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 50277623264SMatthew G. Knepley 50377623264SMatthew G. Knepley Collective on PetscPartitioner 50477623264SMatthew G. Knepley 50577623264SMatthew G. Knepley Input Parameter: 50677623264SMatthew G. Knepley + part - the PetscPartitioner object to view 50777623264SMatthew G. Knepley - v - the viewer 50877623264SMatthew G. Knepley 50977623264SMatthew G. Knepley Level: developer 51077623264SMatthew G. Knepley 51177623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 51277623264SMatthew G. Knepley @*/ 51377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 51477623264SMatthew G. Knepley { 51577623264SMatthew G. Knepley PetscErrorCode ierr; 51677623264SMatthew G. Knepley 51777623264SMatthew G. Knepley PetscFunctionBegin; 51877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 51977623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 52077623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 52177623264SMatthew G. Knepley PetscFunctionReturn(0); 52277623264SMatthew G. Knepley } 52377623264SMatthew G. Knepley 52477623264SMatthew G. Knepley #undef __FUNCT__ 52577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerViewFromOptions" 52677623264SMatthew G. Knepley /* 52777623264SMatthew G. Knepley PetscPartitionerViewFromOptions - Processes command line options to determine if/how a PetscPartitioner is to be viewed. 52877623264SMatthew G. Knepley 52977623264SMatthew G. Knepley Collective on PetscPartitioner 53077623264SMatthew G. Knepley 53177623264SMatthew G. Knepley Input Parameters: 53277623264SMatthew G. Knepley + part - the PetscPartitioner 53377623264SMatthew G. Knepley . prefix - prefix to use for viewing, or NULL 53477623264SMatthew G. Knepley - optionname - option to activate viewing 53577623264SMatthew G. Knepley 53677623264SMatthew G. Knepley Level: intermediate 53777623264SMatthew G. Knepley 53877623264SMatthew G. Knepley .keywords: PetscPartitioner, view, options, database 53977623264SMatthew G. Knepley .seealso: VecViewFromOptions(), MatViewFromOptions() 54077623264SMatthew G. Knepley */ 54177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner part, const char prefix[], const char optionname[]) 54277623264SMatthew G. Knepley { 54377623264SMatthew G. Knepley PetscViewer viewer; 54477623264SMatthew G. Knepley PetscViewerFormat format; 54577623264SMatthew G. Knepley PetscBool flg; 54677623264SMatthew G. Knepley PetscErrorCode ierr; 54777623264SMatthew G. Knepley 54877623264SMatthew G. Knepley PetscFunctionBegin; 54977623264SMatthew G. Knepley if (prefix) {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 55077623264SMatthew G. Knepley else {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), ((PetscObject) part)->prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 55177623264SMatthew G. Knepley if (flg) { 55277623264SMatthew G. Knepley ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr); 55377623264SMatthew G. Knepley ierr = PetscPartitionerView(part, viewer);CHKERRQ(ierr); 55477623264SMatthew G. Knepley ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 55577623264SMatthew G. Knepley ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 55677623264SMatthew G. Knepley } 55777623264SMatthew G. Knepley PetscFunctionReturn(0); 55877623264SMatthew G. Knepley } 55977623264SMatthew G. Knepley #undef __FUNCT__ 56077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetTypeFromOptions_Internal" 56177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetTypeFromOptions_Internal(PetscPartitioner part) 56277623264SMatthew G. Knepley { 56377623264SMatthew G. Knepley const char *defaultType; 56477623264SMatthew G. Knepley char name[256]; 56577623264SMatthew G. Knepley PetscBool flg; 56677623264SMatthew G. Knepley PetscErrorCode ierr; 56777623264SMatthew G. Knepley 56877623264SMatthew G. Knepley PetscFunctionBegin; 56977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 57077623264SMatthew G. Knepley if (!((PetscObject) part)->type_name) defaultType = PETSCPARTITIONERCHACO; 57177623264SMatthew G. Knepley else defaultType = ((PetscObject) part)->type_name; 57277623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 57377623264SMatthew G. Knepley 57477623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 57577623264SMatthew G. Knepley ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, 256, &flg);CHKERRQ(ierr); 57677623264SMatthew G. Knepley if (flg) { 57777623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 57877623264SMatthew G. Knepley } else if (!((PetscObject) part)->type_name) { 57977623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 58077623264SMatthew G. Knepley } 58177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 58277623264SMatthew G. Knepley PetscFunctionReturn(0); 58377623264SMatthew G. Knepley } 58477623264SMatthew G. Knepley 58577623264SMatthew G. Knepley #undef __FUNCT__ 58677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions" 58777623264SMatthew G. Knepley /*@ 58877623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 58977623264SMatthew G. Knepley 59077623264SMatthew G. Knepley Collective on PetscPartitioner 59177623264SMatthew G. Knepley 59277623264SMatthew G. Knepley Input Parameter: 59377623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 59477623264SMatthew G. Knepley 59577623264SMatthew G. Knepley Level: developer 59677623264SMatthew G. Knepley 59777623264SMatthew G. Knepley .seealso: PetscPartitionerView() 59877623264SMatthew G. Knepley @*/ 59977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 60077623264SMatthew G. Knepley { 60177623264SMatthew G. Knepley PetscErrorCode ierr; 60277623264SMatthew G. Knepley 60377623264SMatthew G. Knepley PetscFunctionBegin; 60477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 60577623264SMatthew G. Knepley ierr = PetscPartitionerSetTypeFromOptions_Internal(part);CHKERRQ(ierr); 60677623264SMatthew G. Knepley 60777623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 60877623264SMatthew G. Knepley if (part->ops->setfromoptions) {ierr = (*part->ops->setfromoptions)(part);CHKERRQ(ierr);} 60977623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 61077623264SMatthew G. Knepley ierr = PetscObjectProcessOptionsHandlers((PetscObject) part);CHKERRQ(ierr); 61177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 61277623264SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 61377623264SMatthew G. Knepley PetscFunctionReturn(0); 61477623264SMatthew G. Knepley } 61577623264SMatthew G. Knepley 61677623264SMatthew G. Knepley #undef __FUNCT__ 61777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetUp" 61877623264SMatthew G. Knepley /*@C 61977623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 62077623264SMatthew G. Knepley 62177623264SMatthew G. Knepley Collective on PetscPartitioner 62277623264SMatthew G. Knepley 62377623264SMatthew G. Knepley Input Parameter: 62477623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 62577623264SMatthew G. Knepley 62677623264SMatthew G. Knepley Level: developer 62777623264SMatthew G. Knepley 62877623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 62977623264SMatthew G. Knepley @*/ 63077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 63177623264SMatthew G. Knepley { 63277623264SMatthew G. Knepley PetscErrorCode ierr; 63377623264SMatthew G. Knepley 63477623264SMatthew G. Knepley PetscFunctionBegin; 63577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 63677623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 63777623264SMatthew G. Knepley PetscFunctionReturn(0); 63877623264SMatthew G. Knepley } 63977623264SMatthew G. Knepley 64077623264SMatthew G. Knepley #undef __FUNCT__ 64177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy" 64277623264SMatthew G. Knepley /*@ 64377623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 64477623264SMatthew G. Knepley 64577623264SMatthew G. Knepley Collective on PetscPartitioner 64677623264SMatthew G. Knepley 64777623264SMatthew G. Knepley Input Parameter: 64877623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 64977623264SMatthew G. Knepley 65077623264SMatthew G. Knepley Level: developer 65177623264SMatthew G. Knepley 65277623264SMatthew G. Knepley .seealso: PetscPartitionerView() 65377623264SMatthew G. Knepley @*/ 65477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 65577623264SMatthew G. Knepley { 65677623264SMatthew G. Knepley PetscErrorCode ierr; 65777623264SMatthew G. Knepley 65877623264SMatthew G. Knepley PetscFunctionBegin; 65977623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 66077623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 66177623264SMatthew G. Knepley 66277623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 66377623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 66477623264SMatthew G. Knepley 66577623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 66677623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 66777623264SMatthew G. Knepley PetscFunctionReturn(0); 66877623264SMatthew G. Knepley } 66977623264SMatthew G. Knepley 67077623264SMatthew G. Knepley #undef __FUNCT__ 67177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate" 67277623264SMatthew G. Knepley /*@ 67377623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 67477623264SMatthew G. Knepley 67577623264SMatthew G. Knepley Collective on MPI_Comm 67677623264SMatthew G. Knepley 67777623264SMatthew G. Knepley Input Parameter: 67877623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 67977623264SMatthew G. Knepley 68077623264SMatthew G. Knepley Output Parameter: 68177623264SMatthew G. Knepley . part - The PetscPartitioner object 68277623264SMatthew G. Knepley 68377623264SMatthew G. Knepley Level: beginner 68477623264SMatthew G. Knepley 68577623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL 68677623264SMatthew G. Knepley @*/ 68777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 68877623264SMatthew G. Knepley { 68977623264SMatthew G. Knepley PetscPartitioner p; 69077623264SMatthew G. Knepley PetscErrorCode ierr; 69177623264SMatthew G. Knepley 69277623264SMatthew G. Knepley PetscFunctionBegin; 69377623264SMatthew G. Knepley PetscValidPointer(part, 2); 69477623264SMatthew G. Knepley *part = NULL; 69577623264SMatthew G. Knepley ierr = PetscFVInitializePackage();CHKERRQ(ierr); 69677623264SMatthew G. Knepley 69777623264SMatthew G. Knepley ierr = PetscHeaderCreate(p, _p_PetscPartitioner, struct _PetscPartitionerOps, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 69877623264SMatthew G. Knepley ierr = PetscMemzero(p->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 69977623264SMatthew G. Knepley 70077623264SMatthew G. Knepley *part = p; 70177623264SMatthew G. Knepley PetscFunctionReturn(0); 70277623264SMatthew G. Knepley } 70377623264SMatthew G. Knepley 70477623264SMatthew G. Knepley #undef __FUNCT__ 70577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition" 70677623264SMatthew G. Knepley /*@ 70777623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 70877623264SMatthew G. Knepley 70977623264SMatthew G. Knepley Collective on DM 71077623264SMatthew G. Knepley 71177623264SMatthew G. Knepley Input Parameters: 71277623264SMatthew G. Knepley + part - The PetscPartitioner 713f8987ae8SMichael Lange - dm - The mesh DM 71477623264SMatthew G. Knepley 71577623264SMatthew G. Knepley Output Parameters: 71677623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 717f8987ae8SMichael Lange - partition - The list of points by partition 71877623264SMatthew G. Knepley 71977623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 72077623264SMatthew G. Knepley 72177623264SMatthew G. Knepley Level: developer 72277623264SMatthew G. Knepley 72377623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 7244b15ede2SMatthew G. Knepley @*/ 725f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 72677623264SMatthew G. Knepley { 72777623264SMatthew G. Knepley PetscMPIInt size; 72877623264SMatthew G. Knepley PetscErrorCode ierr; 72977623264SMatthew G. Knepley 73077623264SMatthew G. Knepley PetscFunctionBegin; 73177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 73277623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 73377623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 73477623264SMatthew G. Knepley PetscValidPointer(partition, 5); 73577623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 73677623264SMatthew G. Knepley if (size == 1) { 73777623264SMatthew G. Knepley PetscInt *points; 73877623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 73977623264SMatthew G. Knepley 74077623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 74177623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 74277623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 74377623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 74477623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 74577623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 74677623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 74777623264SMatthew G. Knepley PetscFunctionReturn(0); 74877623264SMatthew G. Knepley } 74977623264SMatthew G. Knepley if (part->height == 0) { 75077623264SMatthew G. Knepley PetscInt numVertices; 75177623264SMatthew G. Knepley PetscInt *start = NULL; 75277623264SMatthew G. Knepley PetscInt *adjacency = NULL; 75377623264SMatthew G. Knepley 754532c4e7dSMichael Lange ierr = DMPlexCreatePartitionerGraph(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 75577623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 75677623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 75777623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 75877623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 75977623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 76077623264SMatthew G. Knepley PetscFunctionReturn(0); 76177623264SMatthew G. Knepley } 76277623264SMatthew G. Knepley 76377623264SMatthew G. Knepley #undef __FUNCT__ 76477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Shell" 76577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 76677623264SMatthew G. Knepley { 76777623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 76877623264SMatthew G. Knepley PetscErrorCode ierr; 76977623264SMatthew G. Knepley 77077623264SMatthew G. Knepley PetscFunctionBegin; 77177623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 77277623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 77377623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 77477623264SMatthew G. Knepley PetscFunctionReturn(0); 77577623264SMatthew G. Knepley } 77677623264SMatthew G. Knepley 77777623264SMatthew G. Knepley #undef __FUNCT__ 77877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell_Ascii" 77977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 78077623264SMatthew G. Knepley { 78177623264SMatthew G. Knepley PetscViewerFormat format; 78277623264SMatthew G. Knepley PetscErrorCode ierr; 78377623264SMatthew G. Knepley 78477623264SMatthew G. Knepley PetscFunctionBegin; 78577623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 78677623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Shell Graph Partitioner:\n");CHKERRQ(ierr); 78777623264SMatthew G. Knepley PetscFunctionReturn(0); 78877623264SMatthew G. Knepley } 78977623264SMatthew G. Knepley 79077623264SMatthew G. Knepley #undef __FUNCT__ 79177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell" 79277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 79377623264SMatthew G. Knepley { 79477623264SMatthew G. Knepley PetscBool iascii; 79577623264SMatthew G. Knepley PetscErrorCode ierr; 79677623264SMatthew G. Knepley 79777623264SMatthew G. Knepley PetscFunctionBegin; 79877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 79977623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 80077623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 80177623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 80277623264SMatthew G. Knepley PetscFunctionReturn(0); 80377623264SMatthew G. Knepley } 80477623264SMatthew G. Knepley 80577623264SMatthew G. Knepley #undef __FUNCT__ 80677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Shell" 80777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 80877623264SMatthew G. Knepley { 80977623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 81077623264SMatthew G. Knepley PetscInt np; 81177623264SMatthew G. Knepley PetscErrorCode ierr; 81277623264SMatthew G. Knepley 81377623264SMatthew G. Knepley PetscFunctionBegin; 81477623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 81577623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 81677623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 81777623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 8185680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 81977623264SMatthew G. Knepley *partition = p->partition; 82077623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 82177623264SMatthew G. Knepley PetscFunctionReturn(0); 82277623264SMatthew G. Knepley } 82377623264SMatthew G. Knepley 82477623264SMatthew G. Knepley #undef __FUNCT__ 82577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Shell" 82677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 82777623264SMatthew G. Knepley { 82877623264SMatthew G. Knepley PetscFunctionBegin; 82977623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 83077623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 83177623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 83277623264SMatthew G. Knepley PetscFunctionReturn(0); 83377623264SMatthew G. Knepley } 83477623264SMatthew G. Knepley 83577623264SMatthew G. Knepley /*MC 83677623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 83777623264SMatthew G. Knepley 83877623264SMatthew G. Knepley Level: intermediate 83977623264SMatthew G. Knepley 84077623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 84177623264SMatthew G. Knepley M*/ 84277623264SMatthew G. Knepley 84377623264SMatthew G. Knepley #undef __FUNCT__ 84477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Shell" 84577623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 84677623264SMatthew G. Knepley { 84777623264SMatthew G. Knepley PetscPartitioner_Shell *p; 84877623264SMatthew G. Knepley PetscErrorCode ierr; 84977623264SMatthew G. Knepley 85077623264SMatthew G. Knepley PetscFunctionBegin; 85177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 85277623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 85377623264SMatthew G. Knepley part->data = p; 85477623264SMatthew G. Knepley 85577623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 85677623264SMatthew G. Knepley PetscFunctionReturn(0); 85777623264SMatthew G. Knepley } 85877623264SMatthew G. Knepley 85977623264SMatthew G. Knepley #undef __FUNCT__ 8605680f57bSMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellSetPartition" 8615680f57bSMatthew G. Knepley /*@C 8625680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 8635680f57bSMatthew G. Knepley 8645680f57bSMatthew G. Knepley Collective on DM 8655680f57bSMatthew G. Knepley 8665680f57bSMatthew G. Knepley Input Parameters: 8675680f57bSMatthew G. Knepley + part - The PetscPartitioner 8685680f57bSMatthew G. Knepley . dm - The mesh DM 8695680f57bSMatthew G. Knepley - enlarge - Expand each partition with neighbors 8705680f57bSMatthew G. Knepley 8715680f57bSMatthew G. Knepley Level: developer 8725680f57bSMatthew G. Knepley 8735680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 8745680f57bSMatthew G. Knepley @*/ 8755680f57bSMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt numProcs, const PetscInt sizes[], const PetscInt points[]) 8765680f57bSMatthew G. Knepley { 8775680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 8785680f57bSMatthew G. Knepley PetscInt proc, numPoints; 8795680f57bSMatthew G. Knepley PetscErrorCode ierr; 8805680f57bSMatthew G. Knepley 8815680f57bSMatthew G. Knepley PetscFunctionBegin; 8825680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8835680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 8845680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(points, 4);} 8855680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 8865680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 8875680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 8885680f57bSMatthew G. Knepley ierr = PetscSectionSetChart(p->section, 0, numProcs);CHKERRQ(ierr); 8895680f57bSMatthew G. Knepley if (sizes) { 8905680f57bSMatthew G. Knepley for (proc = 0; proc < numProcs; ++proc) { 8915680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 8925680f57bSMatthew G. Knepley } 8935680f57bSMatthew G. Knepley } 8945680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 8955680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 8965680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 8975680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8985680f57bSMatthew G. Knepley } 8995680f57bSMatthew G. Knepley 9005680f57bSMatthew G. Knepley #undef __FUNCT__ 90177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Chaco" 90277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 90377623264SMatthew G. Knepley { 90477623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 90577623264SMatthew G. Knepley PetscErrorCode ierr; 90677623264SMatthew G. Knepley 90777623264SMatthew G. Knepley PetscFunctionBegin; 90877623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 90977623264SMatthew G. Knepley PetscFunctionReturn(0); 91077623264SMatthew G. Knepley } 91177623264SMatthew G. Knepley 91277623264SMatthew G. Knepley #undef __FUNCT__ 91377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco_Ascii" 91477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 91577623264SMatthew G. Knepley { 91677623264SMatthew G. Knepley PetscViewerFormat format; 91777623264SMatthew G. Knepley PetscErrorCode ierr; 91877623264SMatthew G. Knepley 91977623264SMatthew G. Knepley PetscFunctionBegin; 92077623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 92177623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Chaco Graph Partitioner:\n");CHKERRQ(ierr); 92277623264SMatthew G. Knepley PetscFunctionReturn(0); 92377623264SMatthew G. Knepley } 92477623264SMatthew G. Knepley 92577623264SMatthew G. Knepley #undef __FUNCT__ 92677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco" 92777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 92877623264SMatthew G. Knepley { 92977623264SMatthew G. Knepley PetscBool iascii; 93077623264SMatthew G. Knepley PetscErrorCode ierr; 93177623264SMatthew G. Knepley 93277623264SMatthew G. Knepley PetscFunctionBegin; 93377623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 93477623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 93577623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 93677623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 93777623264SMatthew G. Knepley PetscFunctionReturn(0); 93877623264SMatthew G. Knepley } 93977623264SMatthew G. Knepley 94070034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 94170034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 94270034214SMatthew G. Knepley #include <unistd.h> 94370034214SMatthew G. Knepley #endif 94470034214SMatthew G. Knepley /* Chaco does not have an include file */ 94570034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 94670034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 94770034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 94870034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 94970034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 95070034214SMatthew G. Knepley 95170034214SMatthew G. Knepley extern int FREE_GRAPH; 95277623264SMatthew G. Knepley #endif 95370034214SMatthew G. Knepley 95470034214SMatthew G. Knepley #undef __FUNCT__ 95577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Chaco" 95677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 95770034214SMatthew G. Knepley { 95877623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 95970034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 96070034214SMatthew G. Knepley MPI_Comm comm; 96170034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 96270034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 96370034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 96470034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 96570034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 96670034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 96770034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 96870034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 96970034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 97070034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 97170034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 97270034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 97370034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 97470034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 97570034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 97670034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 97770034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 97870034214SMatthew G. Knepley short int *assignment; /* Output partition */ 97970034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 98070034214SMatthew G. Knepley PetscInt *points; 98170034214SMatthew G. Knepley int i, v, p; 98270034214SMatthew G. Knepley PetscErrorCode ierr; 98370034214SMatthew G. Knepley 98470034214SMatthew G. Knepley PetscFunctionBegin; 98570034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 98670034214SMatthew G. Knepley if (!numVertices) { 98777623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 98877623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 98970034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 99070034214SMatthew G. Knepley PetscFunctionReturn(0); 99170034214SMatthew G. Knepley } 99270034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 99370034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 99470034214SMatthew G. Knepley 99570034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 99670034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 99770034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 99870034214SMatthew G. Knepley } 99977623264SMatthew G. Knepley mesh_dims[0] = nparts; 100070034214SMatthew G. Knepley mesh_dims[1] = 1; 100170034214SMatthew G. Knepley mesh_dims[2] = 1; 100270034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 100370034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 100470034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 100570034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 100670034214SMatthew G. Knepley { 100770034214SMatthew G. Knepley int piperet; 100870034214SMatthew G. Knepley piperet = pipe(fd_pipe); 100970034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 101070034214SMatthew G. Knepley fd_stdout = dup(1); 101170034214SMatthew G. Knepley close(1); 101270034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 101370034214SMatthew G. Knepley } 101470034214SMatthew G. Knepley #endif 101570034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 101670034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 101770034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 101870034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 101970034214SMatthew G. Knepley { 102070034214SMatthew G. Knepley char msgLog[10000]; 102170034214SMatthew G. Knepley int count; 102270034214SMatthew G. Knepley 102370034214SMatthew G. Knepley fflush(stdout); 102470034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 102570034214SMatthew G. Knepley if (count < 0) count = 0; 102670034214SMatthew G. Knepley msgLog[count] = 0; 102770034214SMatthew G. Knepley close(1); 102870034214SMatthew G. Knepley dup2(fd_stdout, 1); 102970034214SMatthew G. Knepley close(fd_stdout); 103070034214SMatthew G. Knepley close(fd_pipe[0]); 103170034214SMatthew G. Knepley close(fd_pipe[1]); 103270034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 103370034214SMatthew G. Knepley } 103470034214SMatthew G. Knepley #endif 103570034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 103677623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 103770034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 103877623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 103970034214SMatthew G. Knepley } 104077623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 104170034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 104277623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 104370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 104470034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 104570034214SMatthew G. Knepley } 104670034214SMatthew G. Knepley } 104770034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 104870034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 104970034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 105070034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 105170034214SMatthew G. Knepley } 105270034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 105370034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 105470034214SMatthew G. Knepley PetscFunctionReturn(0); 105577623264SMatthew G. Knepley #else 105677623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 105770034214SMatthew G. Knepley #endif 105877623264SMatthew G. Knepley } 105977623264SMatthew G. Knepley 106077623264SMatthew G. Knepley #undef __FUNCT__ 106177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Chaco" 106277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 106377623264SMatthew G. Knepley { 106477623264SMatthew G. Knepley PetscFunctionBegin; 106577623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 106677623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 106777623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 106877623264SMatthew G. Knepley PetscFunctionReturn(0); 106977623264SMatthew G. Knepley } 107077623264SMatthew G. Knepley 107177623264SMatthew G. Knepley /*MC 107277623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 107377623264SMatthew G. Knepley 107477623264SMatthew G. Knepley Level: intermediate 107577623264SMatthew G. Knepley 107677623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 107777623264SMatthew G. Knepley M*/ 107877623264SMatthew G. Knepley 107977623264SMatthew G. Knepley #undef __FUNCT__ 108077623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Chaco" 108177623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 108277623264SMatthew G. Knepley { 108377623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 108477623264SMatthew G. Knepley PetscErrorCode ierr; 108577623264SMatthew G. Knepley 108677623264SMatthew G. Knepley PetscFunctionBegin; 108777623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 108877623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 108977623264SMatthew G. Knepley part->data = p; 109077623264SMatthew G. Knepley 109177623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 109277623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 109377623264SMatthew G. Knepley PetscFunctionReturn(0); 109477623264SMatthew G. Knepley } 109577623264SMatthew G. Knepley 109677623264SMatthew G. Knepley #undef __FUNCT__ 109777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_ParMetis" 109877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 109977623264SMatthew G. Knepley { 110077623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 110177623264SMatthew G. Knepley PetscErrorCode ierr; 110277623264SMatthew G. Knepley 110377623264SMatthew G. Knepley PetscFunctionBegin; 110477623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 110577623264SMatthew G. Knepley PetscFunctionReturn(0); 110677623264SMatthew G. Knepley } 110777623264SMatthew G. Knepley 110877623264SMatthew G. Knepley #undef __FUNCT__ 110977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis_Ascii" 111077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 111177623264SMatthew G. Knepley { 111277623264SMatthew G. Knepley PetscViewerFormat format; 111377623264SMatthew G. Knepley PetscErrorCode ierr; 111477623264SMatthew G. Knepley 111577623264SMatthew G. Knepley PetscFunctionBegin; 111677623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 111777623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis Graph Partitioner:\n");CHKERRQ(ierr); 111877623264SMatthew G. Knepley PetscFunctionReturn(0); 111977623264SMatthew G. Knepley } 112077623264SMatthew G. Knepley 112177623264SMatthew G. Knepley #undef __FUNCT__ 112277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis" 112377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 112477623264SMatthew G. Knepley { 112577623264SMatthew G. Knepley PetscBool iascii; 112677623264SMatthew G. Knepley PetscErrorCode ierr; 112777623264SMatthew G. Knepley 112877623264SMatthew G. Knepley PetscFunctionBegin; 112977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 113077623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 113177623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 113277623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 113377623264SMatthew G. Knepley PetscFunctionReturn(0); 113477623264SMatthew G. Knepley } 113570034214SMatthew G. Knepley 113670034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 113770034214SMatthew G. Knepley #include <parmetis.h> 113877623264SMatthew G. Knepley #endif 113970034214SMatthew G. Knepley 114070034214SMatthew G. Knepley #undef __FUNCT__ 114177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_ParMetis" 114277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 114370034214SMatthew G. Knepley { 114477623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 114570034214SMatthew G. Knepley MPI_Comm comm; 114670034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 114770034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 114870034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 114970034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 115070034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 115170034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 115270034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 115370034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 115470034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 115570034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 115670034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 115770034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 115870034214SMatthew G. Knepley /* Outputs */ 115970034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 116070034214SMatthew G. Knepley PetscInt *assignment, *points; 116177623264SMatthew G. Knepley PetscMPIInt rank, p, v, i; 116270034214SMatthew G. Knepley PetscErrorCode ierr; 116370034214SMatthew G. Knepley 116470034214SMatthew G. Knepley PetscFunctionBegin; 116577623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 116670034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 116770034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 116870034214SMatthew G. Knepley /* Calculate vertex distribution */ 116970034214SMatthew G. Knepley ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 117070034214SMatthew G. Knepley vtxdist[0] = 0; 117170034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 117270034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 117370034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 117470034214SMatthew G. Knepley } 117570034214SMatthew G. Knepley /* Calculate weights */ 117670034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 117770034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 117870034214SMatthew G. Knepley } 117970034214SMatthew G. Knepley ubvec[0] = 1.05; 118070034214SMatthew G. Knepley 118170034214SMatthew G. Knepley if (nparts == 1) { 118270034214SMatthew G. Knepley ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 118370034214SMatthew G. Knepley } else { 118470034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 118570034214SMatthew G. Knepley if (!rank) { 118670034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 118770034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 118870034214SMatthew G. Knepley PetscStackPop; 118970034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 119070034214SMatthew G. Knepley } 119170034214SMatthew G. Knepley } else { 119270034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 119370034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 119470034214SMatthew G. Knepley PetscStackPop; 119570034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 119670034214SMatthew G. Knepley } 119770034214SMatthew G. Knepley } 119870034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 119977623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 120077623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 120177623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 120270034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 120377623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 120470034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 120570034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 120670034214SMatthew G. Knepley } 120770034214SMatthew G. Knepley } 120870034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 120970034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 121070034214SMatthew G. Knepley ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 121170034214SMatthew G. Knepley #else 121277623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 121370034214SMatthew G. Knepley #endif 121477623264SMatthew G. Knepley PetscFunctionReturn(0); 121570034214SMatthew G. Knepley } 121670034214SMatthew G. Knepley 121777623264SMatthew G. Knepley #undef __FUNCT__ 121877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_ParMetis" 121977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 122077623264SMatthew G. Knepley { 122177623264SMatthew G. Knepley PetscFunctionBegin; 122277623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 122377623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 122477623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 122577623264SMatthew G. Knepley PetscFunctionReturn(0); 122677623264SMatthew G. Knepley } 122777623264SMatthew G. Knepley 122877623264SMatthew G. Knepley /*MC 122977623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 123077623264SMatthew G. Knepley 123177623264SMatthew G. Knepley Level: intermediate 123277623264SMatthew G. Knepley 123377623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 123477623264SMatthew G. Knepley M*/ 123577623264SMatthew G. Knepley 123677623264SMatthew G. Knepley #undef __FUNCT__ 123777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_ParMetis" 123877623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 123977623264SMatthew G. Knepley { 124077623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 124177623264SMatthew G. Knepley PetscErrorCode ierr; 124277623264SMatthew G. Knepley 124377623264SMatthew G. Knepley PetscFunctionBegin; 124477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 124577623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 124677623264SMatthew G. Knepley part->data = p; 124777623264SMatthew G. Knepley 124877623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 124977623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 125070034214SMatthew G. Knepley PetscFunctionReturn(0); 125170034214SMatthew G. Knepley } 125270034214SMatthew G. Knepley 125370034214SMatthew G. Knepley #undef __FUNCT__ 12545680f57bSMatthew G. Knepley #define __FUNCT__ "DMPlexGetPartitioner" 12555680f57bSMatthew G. Knepley /*@ 12565680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 12575680f57bSMatthew G. Knepley 12585680f57bSMatthew G. Knepley Not collective 12595680f57bSMatthew G. Knepley 12605680f57bSMatthew G. Knepley Input Parameter: 12615680f57bSMatthew G. Knepley . dm - The DM 12625680f57bSMatthew G. Knepley 12635680f57bSMatthew G. Knepley Output Parameter: 12645680f57bSMatthew G. Knepley . part - The PetscPartitioner 12655680f57bSMatthew G. Knepley 12665680f57bSMatthew G. Knepley Level: developer 12675680f57bSMatthew G. Knepley 12685680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 12695680f57bSMatthew G. Knepley @*/ 12705680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 12715680f57bSMatthew G. Knepley { 12725680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 12735680f57bSMatthew G. Knepley 12745680f57bSMatthew G. Knepley PetscFunctionBegin; 12755680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12765680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 12775680f57bSMatthew G. Knepley *part = mesh->partitioner; 12785680f57bSMatthew G. Knepley PetscFunctionReturn(0); 12795680f57bSMatthew G. Knepley } 12805680f57bSMatthew G. Knepley 12815680f57bSMatthew G. Knepley #undef __FUNCT__ 12829ffc88e4SToby Isaac #define __FUNCT__ "DMPlexMarkTreeClosure" 12839ffc88e4SToby Isaac static PetscErrorCode DMPlexMarkTreeClosure(DM dm, PetscSegBuffer segpart, PetscBT bt, PetscInt point, PetscInt *partSize) 12849ffc88e4SToby Isaac { 12859ffc88e4SToby Isaac PetscInt parent, closureSize, *closure = NULL, i, pStart, pEnd; 12869ffc88e4SToby Isaac PetscErrorCode ierr; 12879ffc88e4SToby Isaac 12889ffc88e4SToby Isaac PetscFunctionBegin; 12899ffc88e4SToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 12909ffc88e4SToby Isaac if (parent == point) PetscFunctionReturn(0); 12919ffc88e4SToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 12929ffc88e4SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 12939ffc88e4SToby Isaac for (i = 0; i < closureSize; i++) { 12949ffc88e4SToby Isaac PetscInt cpoint = closure[2*i]; 12959ffc88e4SToby Isaac 12969ffc88e4SToby Isaac if (!PetscBTLookupSet(bt,cpoint-pStart)) { 12979ffc88e4SToby Isaac PetscInt *PETSC_RESTRICT pt; 12989ffc88e4SToby Isaac (*partSize)++; 12999ffc88e4SToby Isaac ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 13009ffc88e4SToby Isaac *pt = cpoint; 13019ffc88e4SToby Isaac } 13029ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,partSize);CHKERRQ(ierr); 13039ffc88e4SToby Isaac } 13049ffc88e4SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 13059ffc88e4SToby Isaac PetscFunctionReturn(0); 13069ffc88e4SToby Isaac } 13079ffc88e4SToby Isaac 13089ffc88e4SToby Isaac #undef __FUNCT__ 130970034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreatePartitionClosure" 131070034214SMatthew G. Knepley PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 131170034214SMatthew G. Knepley { 131270034214SMatthew G. Knepley /* const PetscInt height = 0; */ 131370034214SMatthew G. Knepley const PetscInt *partArray; 131470034214SMatthew G. Knepley PetscInt *allPoints, *packPoints; 131570034214SMatthew G. Knepley PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 131670034214SMatthew G. Knepley PetscErrorCode ierr; 131770034214SMatthew G. Knepley PetscBT bt; 131870034214SMatthew G. Knepley PetscSegBuffer segpack,segpart; 131970034214SMatthew G. Knepley 132070034214SMatthew G. Knepley PetscFunctionBegin; 132170034214SMatthew G. Knepley ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 132270034214SMatthew G. Knepley ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 132370034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 132470034214SMatthew G. Knepley ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 132570034214SMatthew G. Knepley ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 132670034214SMatthew G. Knepley ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 132770034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 132870034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 132970034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 133070034214SMatthew G. Knepley PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 133170034214SMatthew G. Knepley 133270034214SMatthew G. Knepley ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 133370034214SMatthew G. Knepley ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 133470034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 133570034214SMatthew G. Knepley PetscInt point = partArray[offset+p], closureSize, c; 133670034214SMatthew G. Knepley PetscInt *closure = NULL; 133770034214SMatthew G. Knepley 133870034214SMatthew G. Knepley /* TODO Include support for height > 0 case */ 133970034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 134070034214SMatthew G. Knepley for (c=0; c<closureSize; c++) { 134170034214SMatthew G. Knepley PetscInt cpoint = closure[c*2]; 134270034214SMatthew G. Knepley if (!PetscBTLookupSet(bt,cpoint-pStart)) { 134370034214SMatthew G. Knepley PetscInt *PETSC_RESTRICT pt; 134470034214SMatthew G. Knepley partSize++; 134570034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 134670034214SMatthew G. Knepley *pt = cpoint; 134770034214SMatthew G. Knepley } 13489ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,&partSize);CHKERRQ(ierr); 134970034214SMatthew G. Knepley } 135070034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 135170034214SMatthew G. Knepley } 135270034214SMatthew G. Knepley ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 135370034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 135470034214SMatthew G. Knepley ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 135570034214SMatthew G. Knepley ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 135670034214SMatthew G. Knepley for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 135770034214SMatthew G. Knepley } 135870034214SMatthew G. Knepley ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 135970034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 136070034214SMatthew G. Knepley 136170034214SMatthew G. Knepley ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 136270034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 136370034214SMatthew G. Knepley ierr = PetscMalloc1(newSize, &allPoints);CHKERRQ(ierr); 136470034214SMatthew G. Knepley 136570034214SMatthew G. Knepley ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 136670034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 136770034214SMatthew G. Knepley PetscInt numPoints, offset; 136870034214SMatthew G. Knepley 136970034214SMatthew G. Knepley ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 137070034214SMatthew G. Knepley ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 137170034214SMatthew G. Knepley ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 137270034214SMatthew G. Knepley packPoints += numPoints; 137370034214SMatthew G. Knepley } 137470034214SMatthew G. Knepley 137570034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 137670034214SMatthew G. Knepley ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 137770034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 137870034214SMatthew G. Knepley PetscFunctionReturn(0); 137970034214SMatthew G. Knepley } 1380aa3148a8SMichael Lange 1381aa3148a8SMichael Lange #undef __FUNCT__ 13825abbe4feSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelClosure" 13835abbe4feSMichael Lange /*@ 13845abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 13855abbe4feSMichael Lange 13865abbe4feSMichael Lange Input Parameters: 13875abbe4feSMichael Lange + dm - The DM 13885abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 13895abbe4feSMichael Lange 13905abbe4feSMichael Lange Level: developer 13915abbe4feSMichael Lange 13925abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 13935abbe4feSMichael Lange @*/ 13945abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 13955abbe4feSMichael Lange { 13965abbe4feSMichael Lange IS rankIS, pointIS; 13975abbe4feSMichael Lange const PetscInt *ranks, *points; 13985abbe4feSMichael Lange PetscInt numRanks, numPoints, r, p, c, closureSize; 13995abbe4feSMichael Lange PetscInt *closure = NULL; 14005abbe4feSMichael Lange PetscErrorCode ierr; 14015abbe4feSMichael Lange 14025abbe4feSMichael Lange PetscFunctionBegin; 14035abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 14045abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 14055abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 14065abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 14075abbe4feSMichael Lange const PetscInt rank = ranks[r]; 14085abbe4feSMichael Lange 14095abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 14105abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 14115abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 14125abbe4feSMichael Lange for (p = 0; p < numPoints; ++p) { 14135abbe4feSMichael Lange ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 14145abbe4feSMichael Lange for (c = 0; c < closureSize*2; c += 2) {ierr = DMLabelSetValue(label, closure[c], rank);CHKERRQ(ierr);} 14155abbe4feSMichael Lange } 14165abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 14175abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 14185abbe4feSMichael Lange } 14195abbe4feSMichael Lange if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);} 14205abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 14215abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 14225abbe4feSMichael Lange PetscFunctionReturn(0); 14235abbe4feSMichael Lange } 14245abbe4feSMichael Lange 14255abbe4feSMichael Lange #undef __FUNCT__ 142624d039d7SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelAdjacency" 142724d039d7SMichael Lange /*@ 142824d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 142924d039d7SMichael Lange 143024d039d7SMichael Lange Input Parameters: 143124d039d7SMichael Lange + dm - The DM 143224d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 143324d039d7SMichael Lange 143424d039d7SMichael Lange Level: developer 143524d039d7SMichael Lange 143624d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 143724d039d7SMichael Lange @*/ 143824d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 143924d039d7SMichael Lange { 144024d039d7SMichael Lange IS rankIS, pointIS; 144124d039d7SMichael Lange const PetscInt *ranks, *points; 144224d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 144324d039d7SMichael Lange PetscInt *adj = NULL; 144424d039d7SMichael Lange PetscErrorCode ierr; 144524d039d7SMichael Lange 144624d039d7SMichael Lange PetscFunctionBegin; 144724d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 144824d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 144924d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 145024d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 145124d039d7SMichael Lange const PetscInt rank = ranks[r]; 145224d039d7SMichael Lange 145324d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 145424d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 145524d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 145624d039d7SMichael Lange for (p = 0; p < numPoints; ++p) { 145724d039d7SMichael Lange adjSize = PETSC_DETERMINE; 145824d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 145924d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 146024d039d7SMichael Lange } 146124d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 146224d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 146324d039d7SMichael Lange } 146424d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 146524d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 146624d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 146724d039d7SMichael Lange PetscFunctionReturn(0); 146824d039d7SMichael Lange } 146924d039d7SMichael Lange 147024d039d7SMichael Lange #undef __FUNCT__ 14711fd9873aSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelInvert" 14721fd9873aSMichael Lange /*@ 14731fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 14741fd9873aSMichael Lange 14751fd9873aSMichael Lange Input Parameters: 14761fd9873aSMichael Lange + dm - The DM 14771fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 14781fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 14791fd9873aSMichael Lange 14801fd9873aSMichael Lange Output Parameter: 14811fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 14821fd9873aSMichael Lange 14831fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 14841fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 14851fd9873aSMichael Lange 14861fd9873aSMichael Lange Level: developer 14871fd9873aSMichael Lange 14881fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 14891fd9873aSMichael Lange @*/ 14901fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 14911fd9873aSMichael Lange { 14921fd9873aSMichael Lange MPI_Comm comm; 14931fd9873aSMichael Lange PetscMPIInt rank, numProcs; 14941fd9873aSMichael Lange PetscInt p, n, numNeighbors, size, l, nleaves; 14951fd9873aSMichael Lange PetscSF sfPoint; 14961fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 14971fd9873aSMichael Lange PetscSection rootSection, leafSection; 14981fd9873aSMichael Lange const PetscSFNode *remote; 14991fd9873aSMichael Lange const PetscInt *local, *neighbors; 15001fd9873aSMichael Lange IS valueIS; 15011fd9873aSMichael Lange PetscErrorCode ierr; 15021fd9873aSMichael Lange 15031fd9873aSMichael Lange PetscFunctionBegin; 15041fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 15051fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 15061fd9873aSMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 15071fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 15081fd9873aSMichael Lange 15091fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 15101fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 15111fd9873aSMichael Lange ierr = PetscSectionSetChart(rootSection, 0, numProcs);CHKERRQ(ierr); 15121fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 15131fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 15141fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 15151fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 15161fd9873aSMichael Lange PetscInt numPoints; 15171fd9873aSMichael Lange 15181fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 15191fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 15201fd9873aSMichael Lange } 15211fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 15221fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 15231fd9873aSMichael Lange ierr = PetscMalloc1(size, &rootPoints);CHKERRQ(ierr); 15241fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 15251fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 15261fd9873aSMichael Lange IS pointIS; 15271fd9873aSMichael Lange const PetscInt *points; 15281fd9873aSMichael Lange PetscInt off, numPoints, p; 15291fd9873aSMichael Lange 15301fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 15311fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 15321fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 15331fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 15341fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1535f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1536f8987ae8SMichael Lange else {l = -1;} 15371fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 15381fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 15391fd9873aSMichael Lange } 15401fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 15411fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 15421fd9873aSMichael Lange } 15431fd9873aSMichael Lange ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 15441fd9873aSMichael Lange ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 15451fd9873aSMichael Lange /* Communicate overlap */ 15461fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr); 15471fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 15481fd9873aSMichael Lange /* Filter remote contributions (ovLeafPoints) into the overlapSF */ 15491fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 15501fd9873aSMichael Lange for (p = 0; p < size; p++) { 15511fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 15521fd9873aSMichael Lange } 15531fd9873aSMichael Lange ierr = PetscFree(rootPoints);CHKERRQ(ierr); 15541fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 15551fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 15561fd9873aSMichael Lange ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 15571fd9873aSMichael Lange PetscFunctionReturn(0); 15581fd9873aSMichael Lange } 15591fd9873aSMichael Lange 15601fd9873aSMichael Lange #undef __FUNCT__ 1561aa3148a8SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelCreateSF" 1562aa3148a8SMichael Lange /*@ 1563aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1564aa3148a8SMichael Lange 1565aa3148a8SMichael Lange Input Parameters: 1566aa3148a8SMichael Lange + dm - The DM 1567aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 1568aa3148a8SMichael Lange 1569aa3148a8SMichael Lange Output Parameter: 1570aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 1571aa3148a8SMichael Lange 1572aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1573aa3148a8SMichael Lange 1574aa3148a8SMichael Lange Level: developer 1575aa3148a8SMichael Lange 1576aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 1577aa3148a8SMichael Lange @*/ 1578aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1579aa3148a8SMichael Lange { 1580*43f7d02bSMichael Lange PetscMPIInt rank, numProcs; 1581*43f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 1582aa3148a8SMichael Lange PetscSFNode *remotePoints; 1583*43f7d02bSMichael Lange IS remoteRootIS; 1584*43f7d02bSMichael Lange const PetscInt *remoteRoots; 1585aa3148a8SMichael Lange PetscErrorCode ierr; 1586aa3148a8SMichael Lange 1587aa3148a8SMichael Lange PetscFunctionBegin; 1588*43f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1589aa3148a8SMichael Lange ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 1590aa3148a8SMichael Lange 1591aa3148a8SMichael Lange for (numRemote = 0, n = 0; n < numProcs; ++n) { 1592aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1593aa3148a8SMichael Lange numRemote += numPoints; 1594aa3148a8SMichael Lange } 1595aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 1596*43f7d02bSMichael Lange /* Put owned points first */ 1597*43f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 1598*43f7d02bSMichael Lange if (numPoints > 0) { 1599*43f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 1600*43f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1601*43f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 1602*43f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 1603*43f7d02bSMichael Lange remotePoints[idx].rank = rank; 1604*43f7d02bSMichael Lange idx++; 1605*43f7d02bSMichael Lange } 1606*43f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1607*43f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1608*43f7d02bSMichael Lange } 1609*43f7d02bSMichael Lange /* Now add remote points */ 1610*43f7d02bSMichael Lange for (n = 0; n < numProcs; ++n) { 1611aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1612*43f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 1613aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 1614aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1615aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1616aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 1617aa3148a8SMichael Lange remotePoints[idx].rank = n; 1618aa3148a8SMichael Lange idx++; 1619aa3148a8SMichael Lange } 1620aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1621aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1622aa3148a8SMichael Lange } 1623aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1624aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1625aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 1626aa3148a8SMichael Lange PetscFunctionReturn(0); 1627aa3148a8SMichael Lange } 1628