1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 270034214SMatthew G. Knepley 377623264SMatthew G. Knepley PetscClassId PETSCPARTITIONER_CLASSID = 0; 477623264SMatthew G. Knepley 577623264SMatthew G. Knepley PetscFunctionList PetscPartitionerList = NULL; 677623264SMatthew G. Knepley PetscBool PetscPartitionerRegisterAllCalled = PETSC_FALSE; 777623264SMatthew G. Knepley 877623264SMatthew G. Knepley PetscBool ChacoPartitionercite = PETSC_FALSE; 977623264SMatthew G. Knepley const char ChacoPartitionerCitation[] = "@inproceedings{Chaco95,\n" 1077623264SMatthew G. Knepley " author = {Bruce Hendrickson and Robert Leland},\n" 1177623264SMatthew G. Knepley " title = {A multilevel algorithm for partitioning graphs},\n" 1277623264SMatthew G. Knepley " booktitle = {Supercomputing '95: Proceedings of the 1995 ACM/IEEE Conference on Supercomputing (CDROM)}," 1377623264SMatthew G. Knepley " isbn = {0-89791-816-9},\n" 1477623264SMatthew G. Knepley " pages = {28},\n" 1577623264SMatthew G. Knepley " doi = {http://doi.acm.org/10.1145/224170.224228},\n" 1677623264SMatthew G. Knepley " publisher = {ACM Press},\n" 1777623264SMatthew G. Knepley " address = {New York},\n" 1877623264SMatthew G. Knepley " year = {1995}\n}\n"; 1977623264SMatthew G. Knepley 2077623264SMatthew G. Knepley PetscBool ParMetisPartitionercite = PETSC_FALSE; 2177623264SMatthew G. Knepley const char ParMetisPartitionerCitation[] = "@article{KarypisKumar98,\n" 2277623264SMatthew G. Knepley " author = {George Karypis and Vipin Kumar},\n" 2377623264SMatthew G. Knepley " title = {A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering},\n" 2477623264SMatthew G. Knepley " journal = {Journal of Parallel and Distributed Computing},\n" 2577623264SMatthew G. Knepley " volume = {48},\n" 2677623264SMatthew G. Knepley " pages = {71--85},\n" 2777623264SMatthew G. Knepley " year = {1998}\n}\n"; 2877623264SMatthew G. Knepley 2970034214SMatthew G. Knepley #undef __FUNCT__ 30532c4e7dSMichael Lange #define __FUNCT__ "DMPlexCreatePartitionerGraph" 31532c4e7dSMichael Lange /*@C 32532c4e7dSMichael Lange DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner 33532c4e7dSMichael Lange 34532c4e7dSMichael Lange Input Parameters: 35532c4e7dSMichael Lange + dm - The mesh DM dm 36532c4e7dSMichael Lange - height - Height of the strata from which to construct the graph 37532c4e7dSMichael Lange 38532c4e7dSMichael Lange Output Parameter: 39532c4e7dSMichael Lange + numVertices - Number of vertices in the graph 403fa7752dSToby Isaac . offsets - Point offsets in the graph 413fa7752dSToby Isaac . adjacency - Point connectivity in the graph 423fa7752dSToby Isaac - globalNumbering - A map from the local cell numbering to the global numbering used in "adjacency". Negative indicates that the cell is a duplicate from another process. 43532c4e7dSMichael Lange 44532c4e7dSMichael Lange The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and 45532c4e7dSMichael Lange DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function 46532c4e7dSMichael Lange representation on the mesh. 47532c4e7dSMichael Lange 48532c4e7dSMichael Lange Level: developer 49532c4e7dSMichael Lange 50532c4e7dSMichael Lange .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure() 51532c4e7dSMichael Lange @*/ 523fa7752dSToby Isaac PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering) 53532c4e7dSMichael Lange { 5443f7d02bSMichael Lange PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 55389e55d8SMichael Lange PetscInt *adj = NULL, *vOffsets = NULL, *graph = NULL; 568cfe4c1fSMichael Lange IS cellNumbering; 578cfe4c1fSMichael Lange const PetscInt *cellNum; 58532c4e7dSMichael Lange PetscBool useCone, useClosure; 59532c4e7dSMichael Lange PetscSection section; 60532c4e7dSMichael Lange PetscSegBuffer adjBuffer; 618cfe4c1fSMichael Lange PetscSF sfPoint; 62532c4e7dSMichael Lange PetscMPIInt rank; 63532c4e7dSMichael Lange PetscErrorCode ierr; 64532c4e7dSMichael Lange 65532c4e7dSMichael Lange PetscFunctionBegin; 66532c4e7dSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 67532c4e7dSMichael Lange ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr); 688cfe4c1fSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 698cfe4c1fSMichael Lange ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 70532c4e7dSMichael Lange /* Build adjacency graph via a section/segbuffer */ 71532c4e7dSMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ion);CHKERRQ(ierr); 72532c4e7dSMichael Lange ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 73532c4e7dSMichael Lange ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr); 74532c4e7dSMichael Lange /* Always use FVM adjacency to create partitioner graph */ 75532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 76532c4e7dSMichael Lange ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr); 77532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 78532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, PETSC_FALSE);CHKERRQ(ierr); 79f0927f4eSMatthew G. Knepley ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &cellNumbering);CHKERRQ(ierr); 803fa7752dSToby Isaac if (globalNumbering) { 813fa7752dSToby Isaac ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr); 823fa7752dSToby Isaac *globalNumbering = cellNumbering; 833fa7752dSToby Isaac } 848cfe4c1fSMichael Lange ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 858cfe4c1fSMichael Lange for (*numVertices = 0, p = pStart; p < pEnd; p++) { 868cfe4c1fSMichael Lange /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 878cfe4c1fSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 88532c4e7dSMichael Lange adjSize = PETSC_DETERMINE; 89532c4e7dSMichael Lange ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 90532c4e7dSMichael Lange for (a = 0; a < adjSize; ++a) { 91532c4e7dSMichael Lange const PetscInt point = adj[a]; 92532c4e7dSMichael Lange if (point != p && pStart <= point && point < pEnd) { 93532c4e7dSMichael Lange PetscInt *PETSC_RESTRICT pBuf; 94532c4e7dSMichael Lange ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr); 95532c4e7dSMichael Lange ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr); 96532c4e7dSMichael Lange *pBuf = point; 97532c4e7dSMichael Lange } 98532c4e7dSMichael Lange } 998cfe4c1fSMichael Lange (*numVertices)++; 100532c4e7dSMichael Lange } 101532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 102532c4e7dSMichael Lange ierr = DMPlexSetAdjacencyUseClosure(dm, useClosure);CHKERRQ(ierr); 103532c4e7dSMichael Lange /* Derive CSR graph from section/segbuffer */ 104532c4e7dSMichael Lange ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 105532c4e7dSMichael Lange ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 106389e55d8SMichael Lange ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr); 10743f7d02bSMichael Lange for (idx = 0, p = pStart; p < pEnd; p++) { 10843f7d02bSMichael Lange if (nroots > 0) {if (cellNum[p] < 0) continue;} 10943f7d02bSMichael Lange ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr); 11043f7d02bSMichael Lange } 111532c4e7dSMichael Lange vOffsets[*numVertices] = size; 112532c4e7dSMichael Lange if (offsets) *offsets = vOffsets; 113389e55d8SMichael Lange ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr); 114bf4602e4SToby Isaac { 1158cfe4c1fSMichael Lange ISLocalToGlobalMapping ltogCells; 1168cfe4c1fSMichael Lange PetscInt n, size, *cells_arr; 1178cfe4c1fSMichael Lange /* In parallel, apply a global cell numbering to the graph */ 1188cfe4c1fSMichael Lange ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr); 1198cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingCreateIS(cellNumbering, <ogCells);CHKERRQ(ierr); 1208cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetSize(ltogCells, &size);CHKERRQ(ierr); 1218cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingGetIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 1228cfe4c1fSMichael Lange /* Convert to positive global cell numbers */ 1238cfe4c1fSMichael Lange for (n=0; n<size; n++) {if (cells_arr[n] < 0) cells_arr[n] = -(cells_arr[n]+1);} 1248cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingRestoreIndices(ltogCells, (const PetscInt**)&cells_arr);CHKERRQ(ierr); 125389e55d8SMichael Lange ierr = ISLocalToGlobalMappingApplyBlock(ltogCells, vOffsets[*numVertices], graph, graph);CHKERRQ(ierr); 1268cfe4c1fSMichael Lange ierr = ISLocalToGlobalMappingDestroy(<ogCells);CHKERRQ(ierr); 127f0927f4eSMatthew G. Knepley ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr); 1288cfe4c1fSMichael Lange } 129389e55d8SMichael Lange if (adjacency) *adjacency = graph; 130532c4e7dSMichael Lange /* Clean up */ 131532c4e7dSMichael Lange ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr); 132532c4e7dSMichael Lange ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 133532c4e7dSMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 134532c4e7dSMichael Lange PetscFunctionReturn(0); 135532c4e7dSMichael Lange } 136532c4e7dSMichael Lange 137532c4e7dSMichael Lange #undef __FUNCT__ 13870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 13970034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 14070034214SMatthew G. Knepley { 14170034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 14270034214SMatthew G. Knepley PetscInt numFaceCases = 0; 14370034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 14470034214SMatthew G. Knepley PetscInt *off, *adj; 14570034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 14670034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 14770034214SMatthew G. Knepley PetscErrorCode ierr; 14870034214SMatthew G. Knepley 14970034214SMatthew G. Knepley PetscFunctionBegin; 15070034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 151c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 15270034214SMatthew G. Knepley cellDim = dim - cellHeight; 15370034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 15470034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 15570034214SMatthew G. Knepley if (cEnd - cStart == 0) { 15670034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 15770034214SMatthew G. Knepley if (offsets) *offsets = NULL; 15870034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 15970034214SMatthew G. Knepley PetscFunctionReturn(0); 16070034214SMatthew G. Knepley } 16170034214SMatthew G. Knepley numCells = cEnd - cStart; 16270034214SMatthew G. Knepley faceDepth = depth - cellHeight; 16370034214SMatthew G. Knepley if (dim == depth) { 16470034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 16570034214SMatthew G. Knepley 16670034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 16770034214SMatthew G. Knepley /* Count neighboring cells */ 16870034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 16970034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 17070034214SMatthew G. Knepley const PetscInt *support; 17170034214SMatthew G. Knepley PetscInt supportSize; 17270034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 17370034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 17470034214SMatthew G. Knepley if (supportSize == 2) { 1759ffc88e4SToby Isaac PetscInt numChildren; 1769ffc88e4SToby Isaac 1779ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 1789ffc88e4SToby Isaac if (!numChildren) { 17970034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 18070034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 18170034214SMatthew G. Knepley } 18270034214SMatthew G. Knepley } 1839ffc88e4SToby Isaac } 18470034214SMatthew G. Knepley /* Prefix sum */ 18570034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 18670034214SMatthew G. Knepley if (adjacency) { 18770034214SMatthew G. Knepley PetscInt *tmp; 18870034214SMatthew G. Knepley 18970034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 190854ce69bSBarry Smith ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr); 19170034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 19270034214SMatthew G. Knepley /* Get neighboring cells */ 19370034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 19470034214SMatthew G. Knepley const PetscInt *support; 19570034214SMatthew G. Knepley PetscInt supportSize; 19670034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 19770034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 19870034214SMatthew G. Knepley if (supportSize == 2) { 1999ffc88e4SToby Isaac PetscInt numChildren; 2009ffc88e4SToby Isaac 2019ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 2029ffc88e4SToby Isaac if (!numChildren) { 20370034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 20470034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 20570034214SMatthew G. Knepley } 20670034214SMatthew G. Knepley } 2079ffc88e4SToby Isaac } 20870034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 20970034214SMatthew 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); 21070034214SMatthew G. Knepley #endif 21170034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 21270034214SMatthew G. Knepley } 21370034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 21470034214SMatthew G. Knepley if (offsets) *offsets = off; 21570034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 21670034214SMatthew G. Knepley PetscFunctionReturn(0); 21770034214SMatthew G. Knepley } 21870034214SMatthew G. Knepley /* Setup face recognition */ 21970034214SMatthew G. Knepley if (faceDepth == 1) { 22070034214SMatthew 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 */ 22170034214SMatthew G. Knepley 22270034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 22370034214SMatthew G. Knepley PetscInt corners; 22470034214SMatthew G. Knepley 22570034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 22670034214SMatthew G. Knepley if (!cornersSeen[corners]) { 22770034214SMatthew G. Knepley PetscInt nFV; 22870034214SMatthew G. Knepley 22970034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 23070034214SMatthew G. Knepley cornersSeen[corners] = 1; 23170034214SMatthew G. Knepley 23270034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 23370034214SMatthew G. Knepley 23470034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 23570034214SMatthew G. Knepley } 23670034214SMatthew G. Knepley } 23770034214SMatthew G. Knepley } 23870034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 23970034214SMatthew G. Knepley /* Count neighboring cells */ 24070034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 24170034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 24270034214SMatthew G. Knepley 2438b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 24470034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 24570034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 24670034214SMatthew G. Knepley PetscInt cellPair[2]; 24770034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 24870034214SMatthew G. Knepley PetscInt meetSize = 0; 24970034214SMatthew G. Knepley const PetscInt *meet = NULL; 25070034214SMatthew G. Knepley 25170034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 25270034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 25370034214SMatthew G. Knepley if (!found) { 25470034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 25570034214SMatthew G. Knepley if (meetSize) { 25670034214SMatthew G. Knepley PetscInt f; 25770034214SMatthew G. Knepley 25870034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 25970034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 26070034214SMatthew G. Knepley found = PETSC_TRUE; 26170034214SMatthew G. Knepley break; 26270034214SMatthew G. Knepley } 26370034214SMatthew G. Knepley } 26470034214SMatthew G. Knepley } 26570034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 26670034214SMatthew G. Knepley } 26770034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 26870034214SMatthew G. Knepley } 26970034214SMatthew G. Knepley } 27070034214SMatthew G. Knepley /* Prefix sum */ 27170034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 27270034214SMatthew G. Knepley 27370034214SMatthew G. Knepley if (adjacency) { 27470034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 27570034214SMatthew G. Knepley /* Get neighboring cells */ 27670034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 27770034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 27870034214SMatthew G. Knepley PetscInt cellOffset = 0; 27970034214SMatthew G. Knepley 2808b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 28170034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 28270034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 28370034214SMatthew G. Knepley PetscInt cellPair[2]; 28470034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 28570034214SMatthew G. Knepley PetscInt meetSize = 0; 28670034214SMatthew G. Knepley const PetscInt *meet = NULL; 28770034214SMatthew G. Knepley 28870034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 28970034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 29070034214SMatthew G. Knepley if (!found) { 29170034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 29270034214SMatthew G. Knepley if (meetSize) { 29370034214SMatthew G. Knepley PetscInt f; 29470034214SMatthew G. Knepley 29570034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 29670034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 29770034214SMatthew G. Knepley found = PETSC_TRUE; 29870034214SMatthew G. Knepley break; 29970034214SMatthew G. Knepley } 30070034214SMatthew G. Knepley } 30170034214SMatthew G. Knepley } 30270034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 30370034214SMatthew G. Knepley } 30470034214SMatthew G. Knepley if (found) { 30570034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 30670034214SMatthew G. Knepley ++cellOffset; 30770034214SMatthew G. Knepley } 30870034214SMatthew G. Knepley } 30970034214SMatthew G. Knepley } 31070034214SMatthew G. Knepley } 31170034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 31270034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 31370034214SMatthew G. Knepley if (offsets) *offsets = off; 31470034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 31570034214SMatthew G. Knepley PetscFunctionReturn(0); 31670034214SMatthew G. Knepley } 31770034214SMatthew G. Knepley 31877623264SMatthew G. Knepley #undef __FUNCT__ 31977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerRegister" 32077623264SMatthew G. Knepley /*@C 32177623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 32277623264SMatthew G. Knepley 32377623264SMatthew G. Knepley Not Collective 32477623264SMatthew G. Knepley 32577623264SMatthew G. Knepley Input Parameters: 32677623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 32777623264SMatthew G. Knepley - create_func - The creation routine itself 32877623264SMatthew G. Knepley 32977623264SMatthew G. Knepley Notes: 33077623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 33177623264SMatthew G. Knepley 33277623264SMatthew G. Knepley Sample usage: 33377623264SMatthew G. Knepley .vb 33477623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 33577623264SMatthew G. Knepley .ve 33677623264SMatthew G. Knepley 33777623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 33877623264SMatthew G. Knepley .vb 33977623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 34077623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 34177623264SMatthew G. Knepley .ve 34277623264SMatthew G. Knepley or at runtime via the option 34377623264SMatthew G. Knepley .vb 34477623264SMatthew G. Knepley -petscpartitioner_type my_part 34577623264SMatthew G. Knepley .ve 34677623264SMatthew G. Knepley 34777623264SMatthew G. Knepley Level: advanced 34877623264SMatthew G. Knepley 34977623264SMatthew G. Knepley .keywords: PetscPartitioner, register 35077623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 35177623264SMatthew G. Knepley 35277623264SMatthew G. Knepley @*/ 35377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 35477623264SMatthew G. Knepley { 35577623264SMatthew G. Knepley PetscErrorCode ierr; 35677623264SMatthew G. Knepley 35777623264SMatthew G. Knepley PetscFunctionBegin; 35877623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 35977623264SMatthew G. Knepley PetscFunctionReturn(0); 36077623264SMatthew G. Knepley } 36177623264SMatthew G. Knepley 36277623264SMatthew G. Knepley #undef __FUNCT__ 36377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetType" 36477623264SMatthew G. Knepley /*@C 36577623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 36677623264SMatthew G. Knepley 36777623264SMatthew G. Knepley Collective on PetscPartitioner 36877623264SMatthew G. Knepley 36977623264SMatthew G. Knepley Input Parameters: 37077623264SMatthew G. Knepley + part - The PetscPartitioner object 37177623264SMatthew G. Knepley - name - The kind of partitioner 37277623264SMatthew G. Knepley 37377623264SMatthew G. Knepley Options Database Key: 37477623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 37577623264SMatthew G. Knepley 37677623264SMatthew G. Knepley Level: intermediate 37777623264SMatthew G. Knepley 37877623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 37977623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 38077623264SMatthew G. Knepley @*/ 38177623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 38277623264SMatthew G. Knepley { 38377623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 38477623264SMatthew G. Knepley PetscBool match; 38577623264SMatthew G. Knepley PetscErrorCode ierr; 38677623264SMatthew G. Knepley 38777623264SMatthew G. Knepley PetscFunctionBegin; 38877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 38977623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 39077623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 39177623264SMatthew G. Knepley 3920f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 39377623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 39477623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 39577623264SMatthew G. Knepley 39677623264SMatthew G. Knepley if (part->ops->destroy) { 39777623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 39877623264SMatthew G. Knepley part->ops->destroy = NULL; 39977623264SMatthew G. Knepley } 40077623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 40177623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 40277623264SMatthew G. Knepley PetscFunctionReturn(0); 40377623264SMatthew G. Knepley } 40477623264SMatthew G. Knepley 40577623264SMatthew G. Knepley #undef __FUNCT__ 40677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerGetType" 40777623264SMatthew G. Knepley /*@C 40877623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 40977623264SMatthew G. Knepley 41077623264SMatthew G. Knepley Not Collective 41177623264SMatthew G. Knepley 41277623264SMatthew G. Knepley Input Parameter: 41377623264SMatthew G. Knepley . part - The PetscPartitioner 41477623264SMatthew G. Knepley 41577623264SMatthew G. Knepley Output Parameter: 41677623264SMatthew G. Knepley . name - The PetscPartitioner type name 41777623264SMatthew G. Knepley 41877623264SMatthew G. Knepley Level: intermediate 41977623264SMatthew G. Knepley 42077623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 42177623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 42277623264SMatthew G. Knepley @*/ 42377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 42477623264SMatthew G. Knepley { 42577623264SMatthew G. Knepley PetscErrorCode ierr; 42677623264SMatthew G. Knepley 42777623264SMatthew G. Knepley PetscFunctionBegin; 42877623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 42977623264SMatthew G. Knepley PetscValidPointer(name, 2); 4300f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 43177623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 43277623264SMatthew G. Knepley PetscFunctionReturn(0); 43377623264SMatthew G. Knepley } 43477623264SMatthew G. Knepley 43577623264SMatthew G. Knepley #undef __FUNCT__ 43677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView" 43777623264SMatthew G. Knepley /*@C 43877623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 43977623264SMatthew G. Knepley 44077623264SMatthew G. Knepley Collective on PetscPartitioner 44177623264SMatthew G. Knepley 44277623264SMatthew G. Knepley Input Parameter: 44377623264SMatthew G. Knepley + part - the PetscPartitioner object to view 44477623264SMatthew G. Knepley - v - the viewer 44577623264SMatthew G. Knepley 44677623264SMatthew G. Knepley Level: developer 44777623264SMatthew G. Knepley 44877623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 44977623264SMatthew G. Knepley @*/ 45077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 45177623264SMatthew G. Knepley { 45277623264SMatthew G. Knepley PetscErrorCode ierr; 45377623264SMatthew G. Knepley 45477623264SMatthew G. Knepley PetscFunctionBegin; 45577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 45677623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 45777623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 45877623264SMatthew G. Knepley PetscFunctionReturn(0); 45977623264SMatthew G. Knepley } 46077623264SMatthew G. Knepley 46177623264SMatthew G. Knepley #undef __FUNCT__ 46277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetTypeFromOptions_Internal" 46377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetTypeFromOptions_Internal(PetscPartitioner part) 46477623264SMatthew G. Knepley { 46577623264SMatthew G. Knepley const char *defaultType; 46677623264SMatthew G. Knepley char name[256]; 46777623264SMatthew G. Knepley PetscBool flg; 46877623264SMatthew G. Knepley PetscErrorCode ierr; 46977623264SMatthew G. Knepley 47077623264SMatthew G. Knepley PetscFunctionBegin; 47177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 4727cf71cfdSLisandro Dalcin if (!((PetscObject) part)->type_name) 4737cf71cfdSLisandro Dalcin #if defined(PETSC_HAVE_CHACO) 4747cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERCHACO; 4757cf71cfdSLisandro Dalcin #elif defined(PETSC_HAVE_PARMETIS) 4767cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERPARMETIS; 4777cf71cfdSLisandro Dalcin #else 4787cf71cfdSLisandro Dalcin defaultType = PETSCPARTITIONERSIMPLE; 4797cf71cfdSLisandro Dalcin #endif 4807cf71cfdSLisandro Dalcin else 4817cf71cfdSLisandro Dalcin defaultType = ((PetscObject) part)->type_name; 4820f51fdf8SToby Isaac ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr); 48377623264SMatthew G. Knepley 48477623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 48577623264SMatthew G. Knepley ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, 256, &flg);CHKERRQ(ierr); 48677623264SMatthew G. Knepley if (flg) { 48777623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 48877623264SMatthew G. Knepley } else if (!((PetscObject) part)->type_name) { 48977623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 49077623264SMatthew G. Knepley } 49177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 49277623264SMatthew G. Knepley PetscFunctionReturn(0); 49377623264SMatthew G. Knepley } 49477623264SMatthew G. Knepley 49577623264SMatthew G. Knepley #undef __FUNCT__ 49677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions" 49777623264SMatthew G. Knepley /*@ 49877623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 49977623264SMatthew G. Knepley 50077623264SMatthew G. Knepley Collective on PetscPartitioner 50177623264SMatthew G. Knepley 50277623264SMatthew G. Knepley Input Parameter: 50377623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 50477623264SMatthew G. Knepley 50577623264SMatthew G. Knepley Level: developer 50677623264SMatthew G. Knepley 50777623264SMatthew G. Knepley .seealso: PetscPartitionerView() 50877623264SMatthew G. Knepley @*/ 50977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 51077623264SMatthew G. Knepley { 51177623264SMatthew G. Knepley PetscErrorCode ierr; 51277623264SMatthew G. Knepley 51377623264SMatthew G. Knepley PetscFunctionBegin; 51477623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 51577623264SMatthew G. Knepley ierr = PetscPartitionerSetTypeFromOptions_Internal(part);CHKERRQ(ierr); 51677623264SMatthew G. Knepley 51777623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 518077101c0SMatthew G. Knepley if (part->ops->setfromoptions) {ierr = (*part->ops->setfromoptions)(PetscOptionsObject,part);CHKERRQ(ierr);} 51977623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 5200633abcbSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);CHKERRQ(ierr); 52177623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 52277623264SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 52377623264SMatthew G. Knepley PetscFunctionReturn(0); 52477623264SMatthew G. Knepley } 52577623264SMatthew G. Knepley 52677623264SMatthew G. Knepley #undef __FUNCT__ 52777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetUp" 52877623264SMatthew G. Knepley /*@C 52977623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 53077623264SMatthew G. Knepley 53177623264SMatthew G. Knepley Collective on PetscPartitioner 53277623264SMatthew G. Knepley 53377623264SMatthew G. Knepley Input Parameter: 53477623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 53577623264SMatthew G. Knepley 53677623264SMatthew G. Knepley Level: developer 53777623264SMatthew G. Knepley 53877623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 53977623264SMatthew G. Knepley @*/ 54077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 54177623264SMatthew G. Knepley { 54277623264SMatthew G. Knepley PetscErrorCode ierr; 54377623264SMatthew G. Knepley 54477623264SMatthew G. Knepley PetscFunctionBegin; 54577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 54677623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 54777623264SMatthew G. Knepley PetscFunctionReturn(0); 54877623264SMatthew G. Knepley } 54977623264SMatthew G. Knepley 55077623264SMatthew G. Knepley #undef __FUNCT__ 55177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy" 55277623264SMatthew G. Knepley /*@ 55377623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 55477623264SMatthew G. Knepley 55577623264SMatthew G. Knepley Collective on PetscPartitioner 55677623264SMatthew G. Knepley 55777623264SMatthew G. Knepley Input Parameter: 55877623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 55977623264SMatthew G. Knepley 56077623264SMatthew G. Knepley Level: developer 56177623264SMatthew G. Knepley 56277623264SMatthew G. Knepley .seealso: PetscPartitionerView() 56377623264SMatthew G. Knepley @*/ 56477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 56577623264SMatthew G. Knepley { 56677623264SMatthew G. Knepley PetscErrorCode ierr; 56777623264SMatthew G. Knepley 56877623264SMatthew G. Knepley PetscFunctionBegin; 56977623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 57077623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 57177623264SMatthew G. Knepley 57277623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 57377623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 57477623264SMatthew G. Knepley 57577623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 57677623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 57777623264SMatthew G. Knepley PetscFunctionReturn(0); 57877623264SMatthew G. Knepley } 57977623264SMatthew G. Knepley 58077623264SMatthew G. Knepley #undef __FUNCT__ 58177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate" 58277623264SMatthew G. Knepley /*@ 58377623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 58477623264SMatthew G. Knepley 58577623264SMatthew G. Knepley Collective on MPI_Comm 58677623264SMatthew G. Knepley 58777623264SMatthew G. Knepley Input Parameter: 58877623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 58977623264SMatthew G. Knepley 59077623264SMatthew G. Knepley Output Parameter: 59177623264SMatthew G. Knepley . part - The PetscPartitioner object 59277623264SMatthew G. Knepley 59377623264SMatthew G. Knepley Level: beginner 59477623264SMatthew G. Knepley 595dae52e14SToby Isaac .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL, PETSCPARTITIONERSIMPLE, PETSCPARTITIONERGATHER 59677623264SMatthew G. Knepley @*/ 59777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 59877623264SMatthew G. Knepley { 59977623264SMatthew G. Knepley PetscPartitioner p; 60077623264SMatthew G. Knepley PetscErrorCode ierr; 60177623264SMatthew G. Knepley 60277623264SMatthew G. Knepley PetscFunctionBegin; 60377623264SMatthew G. Knepley PetscValidPointer(part, 2); 60477623264SMatthew G. Knepley *part = NULL; 60583cde681SMatthew G. Knepley ierr = DMInitializePackage();CHKERRQ(ierr); 60677623264SMatthew G. Knepley 60773107ff1SLisandro Dalcin ierr = PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 60877623264SMatthew G. Knepley 60977623264SMatthew G. Knepley *part = p; 61077623264SMatthew G. Knepley PetscFunctionReturn(0); 61177623264SMatthew G. Knepley } 61277623264SMatthew G. Knepley 61377623264SMatthew G. Knepley #undef __FUNCT__ 61477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition" 61577623264SMatthew G. Knepley /*@ 61677623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 61777623264SMatthew G. Knepley 61877623264SMatthew G. Knepley Collective on DM 61977623264SMatthew G. Knepley 62077623264SMatthew G. Knepley Input Parameters: 62177623264SMatthew G. Knepley + part - The PetscPartitioner 622f8987ae8SMichael Lange - dm - The mesh DM 62377623264SMatthew G. Knepley 62477623264SMatthew G. Knepley Output Parameters: 62577623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 626f8987ae8SMichael Lange - partition - The list of points by partition 62777623264SMatthew G. Knepley 62877623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 62977623264SMatthew G. Knepley 63077623264SMatthew G. Knepley Level: developer 63177623264SMatthew G. Knepley 63277623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 6334b15ede2SMatthew G. Knepley @*/ 634f8987ae8SMichael Lange PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscSection partSection, IS *partition) 63577623264SMatthew G. Knepley { 63677623264SMatthew G. Knepley PetscMPIInt size; 63777623264SMatthew G. Knepley PetscErrorCode ierr; 63877623264SMatthew G. Knepley 63977623264SMatthew G. Knepley PetscFunctionBegin; 64077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 64177623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 64277623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 64377623264SMatthew G. Knepley PetscValidPointer(partition, 5); 64477623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 64577623264SMatthew G. Knepley if (size == 1) { 64677623264SMatthew G. Knepley PetscInt *points; 64777623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 64877623264SMatthew G. Knepley 64977623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 65077623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 65177623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 65277623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 65377623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 65477623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 65577623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 65677623264SMatthew G. Knepley PetscFunctionReturn(0); 65777623264SMatthew G. Knepley } 65877623264SMatthew G. Knepley if (part->height == 0) { 65977623264SMatthew G. Knepley PetscInt numVertices; 66077623264SMatthew G. Knepley PetscInt *start = NULL; 66177623264SMatthew G. Knepley PetscInt *adjacency = NULL; 6623fa7752dSToby Isaac IS globalNumbering; 66377623264SMatthew G. Knepley 6643fa7752dSToby Isaac ierr = DMPlexCreatePartitionerGraph(dm, 0, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr); 66577623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 66677623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 66777623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 66877623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 6693fa7752dSToby Isaac if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */ 6703fa7752dSToby Isaac const PetscInt *globalNum; 6713fa7752dSToby Isaac const PetscInt *partIdx; 6723fa7752dSToby Isaac PetscInt *map, cStart, cEnd; 6733fa7752dSToby Isaac PetscInt *adjusted, i, localSize, offset; 6743fa7752dSToby Isaac IS newPartition; 6753fa7752dSToby Isaac 6763fa7752dSToby Isaac ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr); 6773fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr); 6783fa7752dSToby Isaac ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 6793fa7752dSToby Isaac ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr); 6803fa7752dSToby Isaac ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr); 6813fa7752dSToby Isaac ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 6823fa7752dSToby Isaac for (i = cStart, offset = 0; i < cEnd; i++) { 6833fa7752dSToby Isaac if (globalNum[i - cStart] >= 0) map[offset++] = i; 6843fa7752dSToby Isaac } 6853fa7752dSToby Isaac for (i = 0; i < localSize; i++) { 6863fa7752dSToby Isaac adjusted[i] = map[partIdx[i]]; 6873fa7752dSToby Isaac } 6883fa7752dSToby Isaac ierr = PetscFree(map);CHKERRQ(ierr); 6893fa7752dSToby Isaac ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr); 6903fa7752dSToby Isaac ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr); 6913fa7752dSToby Isaac ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr); 6923fa7752dSToby Isaac ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr); 6933fa7752dSToby Isaac ierr = ISDestroy(partition);CHKERRQ(ierr); 6943fa7752dSToby Isaac *partition = newPartition; 6953fa7752dSToby Isaac } 69677623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 69777623264SMatthew G. Knepley PetscFunctionReturn(0); 6983fa7752dSToby Isaac 69977623264SMatthew G. Knepley } 70077623264SMatthew G. Knepley 70177623264SMatthew G. Knepley #undef __FUNCT__ 70277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Shell" 70377623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 70477623264SMatthew G. Knepley { 70577623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 70677623264SMatthew G. Knepley PetscErrorCode ierr; 70777623264SMatthew G. Knepley 70877623264SMatthew G. Knepley PetscFunctionBegin; 70977623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 71077623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 71177623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 71277623264SMatthew G. Knepley PetscFunctionReturn(0); 71377623264SMatthew G. Knepley } 71477623264SMatthew G. Knepley 71577623264SMatthew G. Knepley #undef __FUNCT__ 71677623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell_Ascii" 71777623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 71877623264SMatthew G. Knepley { 719077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 72077623264SMatthew G. Knepley PetscViewerFormat format; 72177623264SMatthew G. Knepley PetscErrorCode ierr; 72277623264SMatthew G. Knepley 72377623264SMatthew G. Knepley PetscFunctionBegin; 72477623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 72577623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Shell Graph Partitioner:\n");CHKERRQ(ierr); 726077101c0SMatthew G. Knepley if (p->random) { 727077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 728077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 729077101c0SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 730077101c0SMatthew G. Knepley } 73177623264SMatthew G. Knepley PetscFunctionReturn(0); 73277623264SMatthew G. Knepley } 73377623264SMatthew G. Knepley 73477623264SMatthew G. Knepley #undef __FUNCT__ 73577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell" 73677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 73777623264SMatthew G. Knepley { 73877623264SMatthew G. Knepley PetscBool iascii; 73977623264SMatthew G. Knepley PetscErrorCode ierr; 74077623264SMatthew G. Knepley 74177623264SMatthew G. Knepley PetscFunctionBegin; 74277623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 74377623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 74477623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 74577623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 74677623264SMatthew G. Knepley PetscFunctionReturn(0); 74777623264SMatthew G. Knepley } 74877623264SMatthew G. Knepley 74977623264SMatthew G. Knepley #undef __FUNCT__ 750077101c0SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions_Shell" 751077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 752077101c0SMatthew G. Knepley { 753077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 754077101c0SMatthew G. Knepley PetscErrorCode ierr; 755077101c0SMatthew G. Knepley 756077101c0SMatthew G. Knepley PetscFunctionBegin; 757077101c0SMatthew G. Knepley ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitionerShell Options");CHKERRQ(ierr); 758077101c0SMatthew G. Knepley ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &p->random, NULL);CHKERRQ(ierr); 759077101c0SMatthew G. Knepley ierr = PetscOptionsTail();CHKERRQ(ierr); 760077101c0SMatthew G. Knepley PetscFunctionReturn(0); 761077101c0SMatthew G. Knepley } 762077101c0SMatthew G. Knepley 763077101c0SMatthew G. Knepley #undef __FUNCT__ 76477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Shell" 76577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 76677623264SMatthew G. Knepley { 76777623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 76877623264SMatthew G. Knepley PetscInt np; 76977623264SMatthew G. Knepley PetscErrorCode ierr; 77077623264SMatthew G. Knepley 77177623264SMatthew G. Knepley PetscFunctionBegin; 772077101c0SMatthew G. Knepley if (p->random) { 773077101c0SMatthew G. Knepley PetscRandom r; 774077101c0SMatthew G. Knepley PetscInt *sizes, *points, v; 775077101c0SMatthew G. Knepley 776077101c0SMatthew G. Knepley ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 777*351ac257SMatthew G. Knepley ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (nparts+1));CHKERRQ(ierr); 778077101c0SMatthew G. Knepley ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 779077101c0SMatthew G. Knepley ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 780077101c0SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 781077101c0SMatthew G. Knepley PetscReal val; 782077101c0SMatthew G. Knepley PetscInt part; 783077101c0SMatthew G. Knepley 784077101c0SMatthew G. Knepley ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 785077101c0SMatthew G. Knepley part = PetscFloorReal(val); 786077101c0SMatthew G. Knepley points[v] = part; 787077101c0SMatthew G. Knepley ++sizes[part]; 788077101c0SMatthew G. Knepley } 789077101c0SMatthew G. Knepley ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 790077101c0SMatthew G. Knepley ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 791077101c0SMatthew G. Knepley ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 792077101c0SMatthew G. Knepley } 79377623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 79477623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 79577623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 79677623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 7975680f57bSMatthew G. Knepley ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 79877623264SMatthew G. Knepley *partition = p->partition; 79977623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 80077623264SMatthew G. Knepley PetscFunctionReturn(0); 80177623264SMatthew G. Knepley } 80277623264SMatthew G. Knepley 80377623264SMatthew G. Knepley #undef __FUNCT__ 80477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Shell" 80577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 80677623264SMatthew G. Knepley { 80777623264SMatthew G. Knepley PetscFunctionBegin; 80877623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 809077101c0SMatthew G. Knepley part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 81077623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 81177623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 81277623264SMatthew G. Knepley PetscFunctionReturn(0); 81377623264SMatthew G. Knepley } 81477623264SMatthew G. Knepley 81577623264SMatthew G. Knepley /*MC 81677623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 81777623264SMatthew G. Knepley 81877623264SMatthew G. Knepley Level: intermediate 81977623264SMatthew G. Knepley 82077623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 82177623264SMatthew G. Knepley M*/ 82277623264SMatthew G. Knepley 82377623264SMatthew G. Knepley #undef __FUNCT__ 82477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Shell" 82577623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 82677623264SMatthew G. Knepley { 82777623264SMatthew G. Knepley PetscPartitioner_Shell *p; 82877623264SMatthew G. Knepley PetscErrorCode ierr; 82977623264SMatthew G. Knepley 83077623264SMatthew G. Knepley PetscFunctionBegin; 83177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 83277623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 83377623264SMatthew G. Knepley part->data = p; 83477623264SMatthew G. Knepley 83577623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 836077101c0SMatthew G. Knepley p->random = PETSC_FALSE; 83777623264SMatthew G. Knepley PetscFunctionReturn(0); 83877623264SMatthew G. Knepley } 83977623264SMatthew G. Knepley 84077623264SMatthew G. Knepley #undef __FUNCT__ 8415680f57bSMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellSetPartition" 8425680f57bSMatthew G. Knepley /*@C 8435680f57bSMatthew G. Knepley PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 8445680f57bSMatthew G. Knepley 845077101c0SMatthew G. Knepley Collective on Part 8465680f57bSMatthew G. Knepley 8475680f57bSMatthew G. Knepley Input Parameters: 8485680f57bSMatthew G. Knepley + part - The PetscPartitioner 849b7e49471SLawrence Mitchell . numProcs - The number of partitions 850b7e49471SLawrence Mitchell . sizes - array of size numProcs (or NULL) providing the number of points in each partition 851b7e49471SLawrence Mitchell - points - array of size sum(sizes) (may be NULL iff sizes is NULL) providing the partition each point belongs to 8525680f57bSMatthew G. Knepley 8535680f57bSMatthew G. Knepley Level: developer 8545680f57bSMatthew G. Knepley 855b7e49471SLawrence Mitchell Notes: 856b7e49471SLawrence Mitchell 857b7e49471SLawrence Mitchell It is safe to free the sizes and points arrays after use in this routine. 858b7e49471SLawrence Mitchell 8595680f57bSMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerCreate() 8605680f57bSMatthew G. Knepley @*/ 8615680f57bSMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt numProcs, const PetscInt sizes[], const PetscInt points[]) 8625680f57bSMatthew G. Knepley { 8635680f57bSMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 8645680f57bSMatthew G. Knepley PetscInt proc, numPoints; 8655680f57bSMatthew G. Knepley PetscErrorCode ierr; 8665680f57bSMatthew G. Knepley 8675680f57bSMatthew G. Knepley PetscFunctionBegin; 8685680f57bSMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 8695680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(sizes, 3);} 8705680f57bSMatthew G. Knepley if (sizes) {PetscValidPointer(points, 4);} 8715680f57bSMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 8725680f57bSMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 8735680f57bSMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 8745680f57bSMatthew G. Knepley ierr = PetscSectionSetChart(p->section, 0, numProcs);CHKERRQ(ierr); 8755680f57bSMatthew G. Knepley if (sizes) { 8765680f57bSMatthew G. Knepley for (proc = 0; proc < numProcs; ++proc) { 8775680f57bSMatthew G. Knepley ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 8785680f57bSMatthew G. Knepley } 8795680f57bSMatthew G. Knepley } 8805680f57bSMatthew G. Knepley ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 8815680f57bSMatthew G. Knepley ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 8825680f57bSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 8835680f57bSMatthew G. Knepley PetscFunctionReturn(0); 8845680f57bSMatthew G. Knepley } 8855680f57bSMatthew G. Knepley 8865680f57bSMatthew G. Knepley #undef __FUNCT__ 887077101c0SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellSetRandom" 888077101c0SMatthew G. Knepley /*@ 889077101c0SMatthew G. Knepley PetscPartitionerShellSetRandom - Set the flag to use a random partition 890077101c0SMatthew G. Knepley 891077101c0SMatthew G. Knepley Collective on Part 892077101c0SMatthew G. Knepley 893077101c0SMatthew G. Knepley Input Parameters: 894077101c0SMatthew G. Knepley + part - The PetscPartitioner 895077101c0SMatthew G. Knepley - random - The flag to use a random partition 896077101c0SMatthew G. Knepley 897077101c0SMatthew G. Knepley Level: intermediate 898077101c0SMatthew G. Knepley 899077101c0SMatthew G. Knepley .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 900077101c0SMatthew G. Knepley @*/ 901077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 902077101c0SMatthew G. Knepley { 903077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 904077101c0SMatthew G. Knepley 905077101c0SMatthew G. Knepley PetscFunctionBegin; 906077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 907077101c0SMatthew G. Knepley p->random = random; 908077101c0SMatthew G. Knepley PetscFunctionReturn(0); 909077101c0SMatthew G. Knepley } 910077101c0SMatthew G. Knepley 911077101c0SMatthew G. Knepley #undef __FUNCT__ 912077101c0SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerShellGetRandom" 913077101c0SMatthew G. Knepley /*@ 914077101c0SMatthew G. Knepley PetscPartitionerShellGetRandom - get the flag to use a random partition 915077101c0SMatthew G. Knepley 916077101c0SMatthew G. Knepley Collective on Part 917077101c0SMatthew G. Knepley 918077101c0SMatthew G. Knepley Input Parameter: 919077101c0SMatthew G. Knepley . part - The PetscPartitioner 920077101c0SMatthew G. Knepley 921077101c0SMatthew G. Knepley Output Parameter 922077101c0SMatthew G. Knepley . random - The flag to use a random partition 923077101c0SMatthew G. Knepley 924077101c0SMatthew G. Knepley Level: intermediate 925077101c0SMatthew G. Knepley 926077101c0SMatthew G. Knepley .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 927077101c0SMatthew G. Knepley @*/ 928077101c0SMatthew G. Knepley PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 929077101c0SMatthew G. Knepley { 930077101c0SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 931077101c0SMatthew G. Knepley 932077101c0SMatthew G. Knepley PetscFunctionBegin; 933077101c0SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 934077101c0SMatthew G. Knepley PetscValidPointer(random, 2); 935077101c0SMatthew G. Knepley *random = p->random; 936077101c0SMatthew G. Knepley PetscFunctionReturn(0); 937077101c0SMatthew G. Knepley } 938077101c0SMatthew G. Knepley 939077101c0SMatthew G. Knepley #undef __FUNCT__ 940555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Simple" 941555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Simple(PetscPartitioner part) 942555a9cf8SMatthew G. Knepley { 943555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p = (PetscPartitioner_Simple *) part->data; 944555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 945555a9cf8SMatthew G. Knepley 946555a9cf8SMatthew G. Knepley PetscFunctionBegin; 947555a9cf8SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 948555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 949555a9cf8SMatthew G. Knepley } 950555a9cf8SMatthew G. Knepley 951555a9cf8SMatthew G. Knepley #undef __FUNCT__ 952555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Simple_Ascii" 953555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Simple_Ascii(PetscPartitioner part, PetscViewer viewer) 954555a9cf8SMatthew G. Knepley { 955555a9cf8SMatthew G. Knepley PetscViewerFormat format; 956555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 957555a9cf8SMatthew G. Knepley 958555a9cf8SMatthew G. Knepley PetscFunctionBegin; 959555a9cf8SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 960555a9cf8SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Simple Graph Partitioner:\n");CHKERRQ(ierr); 961555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 962555a9cf8SMatthew G. Knepley } 963555a9cf8SMatthew G. Knepley 964555a9cf8SMatthew G. Knepley #undef __FUNCT__ 965555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Simple" 966555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Simple(PetscPartitioner part, PetscViewer viewer) 967555a9cf8SMatthew G. Knepley { 968555a9cf8SMatthew G. Knepley PetscBool iascii; 969555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 970555a9cf8SMatthew G. Knepley 971555a9cf8SMatthew G. Knepley PetscFunctionBegin; 972555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 973555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 974555a9cf8SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 975555a9cf8SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Simple_Ascii(part, viewer);CHKERRQ(ierr);} 976555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 977555a9cf8SMatthew G. Knepley } 978555a9cf8SMatthew G. Knepley 979555a9cf8SMatthew G. Knepley #undef __FUNCT__ 980555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Simple" 981555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Simple(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 982555a9cf8SMatthew G. Knepley { 983cead94edSToby Isaac MPI_Comm comm; 984555a9cf8SMatthew G. Knepley PetscInt np; 985cead94edSToby Isaac PetscMPIInt size; 986555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 987555a9cf8SMatthew G. Knepley 988555a9cf8SMatthew G. Knepley PetscFunctionBegin; 989cead94edSToby Isaac comm = PetscObjectComm((PetscObject)dm); 990cead94edSToby Isaac ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 991555a9cf8SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 992555a9cf8SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 993cead94edSToby Isaac if (size == 1) { 994cead94edSToby Isaac for (np = 0; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, numVertices/nparts + ((numVertices % nparts) > np));CHKERRQ(ierr);} 995cead94edSToby Isaac } 996cead94edSToby Isaac else { 997cead94edSToby Isaac PetscMPIInt rank; 998cead94edSToby Isaac PetscInt nvGlobal, *offsets, myFirst, myLast; 999cead94edSToby Isaac 1000a679a563SToby Isaac ierr = PetscMalloc1(size+1,&offsets);CHKERRQ(ierr); 1001cead94edSToby Isaac offsets[0] = 0; 1002cead94edSToby Isaac ierr = MPI_Allgather(&numVertices,1,MPIU_INT,&offsets[1],1,MPIU_INT,comm);CHKERRQ(ierr); 1003cead94edSToby Isaac for (np = 2; np <= size; np++) { 1004cead94edSToby Isaac offsets[np] += offsets[np-1]; 1005cead94edSToby Isaac } 1006cead94edSToby Isaac nvGlobal = offsets[size]; 1007cead94edSToby Isaac ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1008cead94edSToby Isaac myFirst = offsets[rank]; 1009cead94edSToby Isaac myLast = offsets[rank + 1] - 1; 1010cead94edSToby Isaac ierr = PetscFree(offsets);CHKERRQ(ierr); 1011cead94edSToby Isaac if (numVertices) { 1012cead94edSToby Isaac PetscInt firstPart = 0, firstLargePart = 0; 1013cead94edSToby Isaac PetscInt lastPart = 0, lastLargePart = 0; 1014cead94edSToby Isaac PetscInt rem = nvGlobal % nparts; 1015cead94edSToby Isaac PetscInt pSmall = nvGlobal/nparts; 1016cead94edSToby Isaac PetscInt pBig = nvGlobal/nparts + 1; 1017cead94edSToby Isaac 1018cead94edSToby Isaac 1019cead94edSToby Isaac if (rem) { 1020cead94edSToby Isaac firstLargePart = myFirst / pBig; 1021cead94edSToby Isaac lastLargePart = myLast / pBig; 1022cead94edSToby Isaac 1023cead94edSToby Isaac if (firstLargePart < rem) { 1024cead94edSToby Isaac firstPart = firstLargePart; 1025cead94edSToby Isaac } 1026cead94edSToby Isaac else { 1027cead94edSToby Isaac firstPart = rem + (myFirst - (rem * pBig)) / pSmall; 1028cead94edSToby Isaac } 1029cead94edSToby Isaac if (lastLargePart < rem) { 1030cead94edSToby Isaac lastPart = lastLargePart; 1031cead94edSToby Isaac } 1032cead94edSToby Isaac else { 1033cead94edSToby Isaac lastPart = rem + (myLast - (rem * pBig)) / pSmall; 1034cead94edSToby Isaac } 1035cead94edSToby Isaac } 1036cead94edSToby Isaac else { 1037cead94edSToby Isaac firstPart = myFirst / (nvGlobal/nparts); 1038cead94edSToby Isaac lastPart = myLast / (nvGlobal/nparts); 1039cead94edSToby Isaac } 1040cead94edSToby Isaac 1041cead94edSToby Isaac for (np = firstPart; np <= lastPart; np++) { 1042cead94edSToby Isaac PetscInt PartStart = np * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np); 1043cead94edSToby Isaac PetscInt PartEnd = (np+1) * (nvGlobal/nparts) + PetscMin(nvGlobal % nparts,np+1); 1044cead94edSToby Isaac 1045cead94edSToby Isaac PartStart = PetscMax(PartStart,myFirst); 1046cead94edSToby Isaac PartEnd = PetscMin(PartEnd,myLast+1); 1047cead94edSToby Isaac ierr = PetscSectionSetDof(partSection,np,PartEnd-PartStart);CHKERRQ(ierr); 1048cead94edSToby Isaac } 1049cead94edSToby Isaac } 1050cead94edSToby Isaac } 1051cead94edSToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1052555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1053555a9cf8SMatthew G. Knepley } 1054555a9cf8SMatthew G. Knepley 1055555a9cf8SMatthew G. Knepley #undef __FUNCT__ 1056555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Simple" 1057555a9cf8SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Simple(PetscPartitioner part) 1058555a9cf8SMatthew G. Knepley { 1059555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1060555a9cf8SMatthew G. Knepley part->ops->view = PetscPartitionerView_Simple; 1061555a9cf8SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Simple; 1062555a9cf8SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Simple; 1063555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1064555a9cf8SMatthew G. Knepley } 1065555a9cf8SMatthew G. Knepley 1066555a9cf8SMatthew G. Knepley /*MC 1067555a9cf8SMatthew G. Knepley PETSCPARTITIONERSIMPLE = "simple" - A PetscPartitioner object 1068555a9cf8SMatthew G. Knepley 1069555a9cf8SMatthew G. Knepley Level: intermediate 1070555a9cf8SMatthew G. Knepley 1071555a9cf8SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1072555a9cf8SMatthew G. Knepley M*/ 1073555a9cf8SMatthew G. Knepley 1074555a9cf8SMatthew G. Knepley #undef __FUNCT__ 1075555a9cf8SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Simple" 1076555a9cf8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Simple(PetscPartitioner part) 1077555a9cf8SMatthew G. Knepley { 1078555a9cf8SMatthew G. Knepley PetscPartitioner_Simple *p; 1079555a9cf8SMatthew G. Knepley PetscErrorCode ierr; 1080555a9cf8SMatthew G. Knepley 1081555a9cf8SMatthew G. Knepley PetscFunctionBegin; 1082555a9cf8SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1083555a9cf8SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1084555a9cf8SMatthew G. Knepley part->data = p; 1085555a9cf8SMatthew G. Knepley 1086555a9cf8SMatthew G. Knepley ierr = PetscPartitionerInitialize_Simple(part);CHKERRQ(ierr); 1087555a9cf8SMatthew G. Knepley PetscFunctionReturn(0); 1088555a9cf8SMatthew G. Knepley } 1089555a9cf8SMatthew G. Knepley 1090555a9cf8SMatthew G. Knepley #undef __FUNCT__ 1091dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerDestroy_Gather" 1092dae52e14SToby Isaac PetscErrorCode PetscPartitionerDestroy_Gather(PetscPartitioner part) 1093dae52e14SToby Isaac { 1094dae52e14SToby Isaac PetscPartitioner_Gather *p = (PetscPartitioner_Gather *) part->data; 1095dae52e14SToby Isaac PetscErrorCode ierr; 1096dae52e14SToby Isaac 1097dae52e14SToby Isaac PetscFunctionBegin; 1098dae52e14SToby Isaac ierr = PetscFree(p);CHKERRQ(ierr); 1099dae52e14SToby Isaac PetscFunctionReturn(0); 1100dae52e14SToby Isaac } 1101dae52e14SToby Isaac 1102dae52e14SToby Isaac #undef __FUNCT__ 1103dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerView_Gather_Ascii" 1104dae52e14SToby Isaac PetscErrorCode PetscPartitionerView_Gather_Ascii(PetscPartitioner part, PetscViewer viewer) 1105dae52e14SToby Isaac { 1106dae52e14SToby Isaac PetscViewerFormat format; 1107dae52e14SToby Isaac PetscErrorCode ierr; 1108dae52e14SToby Isaac 1109dae52e14SToby Isaac PetscFunctionBegin; 1110dae52e14SToby Isaac ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 1111dae52e14SToby Isaac ierr = PetscViewerASCIIPrintf(viewer, "Gather Graph Partitioner:\n");CHKERRQ(ierr); 1112dae52e14SToby Isaac PetscFunctionReturn(0); 1113dae52e14SToby Isaac } 1114dae52e14SToby Isaac 1115dae52e14SToby Isaac #undef __FUNCT__ 1116dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerView_Gather" 1117dae52e14SToby Isaac PetscErrorCode PetscPartitionerView_Gather(PetscPartitioner part, PetscViewer viewer) 1118dae52e14SToby Isaac { 1119dae52e14SToby Isaac PetscBool iascii; 1120dae52e14SToby Isaac PetscErrorCode ierr; 1121dae52e14SToby Isaac 1122dae52e14SToby Isaac PetscFunctionBegin; 1123dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1124dae52e14SToby Isaac PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1125dae52e14SToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1126dae52e14SToby Isaac if (iascii) {ierr = PetscPartitionerView_Gather_Ascii(part, viewer);CHKERRQ(ierr);} 1127dae52e14SToby Isaac PetscFunctionReturn(0); 1128dae52e14SToby Isaac } 1129dae52e14SToby Isaac 1130dae52e14SToby Isaac #undef __FUNCT__ 1131dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerPartition_Gather" 1132dae52e14SToby Isaac PetscErrorCode PetscPartitionerPartition_Gather(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 1133dae52e14SToby Isaac { 1134dae52e14SToby Isaac PetscInt np; 1135dae52e14SToby Isaac PetscErrorCode ierr; 1136dae52e14SToby Isaac 1137dae52e14SToby Isaac PetscFunctionBegin; 1138dae52e14SToby Isaac ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1139dae52e14SToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF, numVertices, 0, 1, partition);CHKERRQ(ierr); 1140dae52e14SToby Isaac ierr = PetscSectionSetDof(partSection,0,numVertices);CHKERRQ(ierr); 1141dae52e14SToby Isaac for (np = 1; np < nparts; ++np) {ierr = PetscSectionSetDof(partSection, np, 0);CHKERRQ(ierr);} 1142dae52e14SToby Isaac ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 1143dae52e14SToby Isaac PetscFunctionReturn(0); 1144dae52e14SToby Isaac } 1145dae52e14SToby Isaac 1146dae52e14SToby Isaac #undef __FUNCT__ 1147dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerInitialize_Gather" 1148dae52e14SToby Isaac PetscErrorCode PetscPartitionerInitialize_Gather(PetscPartitioner part) 1149dae52e14SToby Isaac { 1150dae52e14SToby Isaac PetscFunctionBegin; 1151dae52e14SToby Isaac part->ops->view = PetscPartitionerView_Gather; 1152dae52e14SToby Isaac part->ops->destroy = PetscPartitionerDestroy_Gather; 1153dae52e14SToby Isaac part->ops->partition = PetscPartitionerPartition_Gather; 1154dae52e14SToby Isaac PetscFunctionReturn(0); 1155dae52e14SToby Isaac } 1156dae52e14SToby Isaac 1157dae52e14SToby Isaac /*MC 1158dae52e14SToby Isaac PETSCPARTITIONERGATHER = "gather" - A PetscPartitioner object 1159dae52e14SToby Isaac 1160dae52e14SToby Isaac Level: intermediate 1161dae52e14SToby Isaac 1162dae52e14SToby Isaac .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1163dae52e14SToby Isaac M*/ 1164dae52e14SToby Isaac 1165dae52e14SToby Isaac #undef __FUNCT__ 1166dae52e14SToby Isaac #define __FUNCT__ "PetscPartitionerCreate_Gather" 1167dae52e14SToby Isaac PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Gather(PetscPartitioner part) 1168dae52e14SToby Isaac { 1169dae52e14SToby Isaac PetscPartitioner_Gather *p; 1170dae52e14SToby Isaac PetscErrorCode ierr; 1171dae52e14SToby Isaac 1172dae52e14SToby Isaac PetscFunctionBegin; 1173dae52e14SToby Isaac PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1174dae52e14SToby Isaac ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1175dae52e14SToby Isaac part->data = p; 1176dae52e14SToby Isaac 1177dae52e14SToby Isaac ierr = PetscPartitionerInitialize_Gather(part);CHKERRQ(ierr); 1178dae52e14SToby Isaac PetscFunctionReturn(0); 1179dae52e14SToby Isaac } 1180dae52e14SToby Isaac 1181dae52e14SToby Isaac 1182dae52e14SToby Isaac #undef __FUNCT__ 118377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Chaco" 118477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 118577623264SMatthew G. Knepley { 118677623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 118777623264SMatthew G. Knepley PetscErrorCode ierr; 118877623264SMatthew G. Knepley 118977623264SMatthew G. Knepley PetscFunctionBegin; 119077623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 119177623264SMatthew G. Knepley PetscFunctionReturn(0); 119277623264SMatthew G. Knepley } 119377623264SMatthew G. Knepley 119477623264SMatthew G. Knepley #undef __FUNCT__ 119577623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco_Ascii" 119677623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 119777623264SMatthew G. Knepley { 119877623264SMatthew G. Knepley PetscViewerFormat format; 119977623264SMatthew G. Knepley PetscErrorCode ierr; 120077623264SMatthew G. Knepley 120177623264SMatthew G. Knepley PetscFunctionBegin; 120277623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 120377623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Chaco Graph Partitioner:\n");CHKERRQ(ierr); 120477623264SMatthew G. Knepley PetscFunctionReturn(0); 120577623264SMatthew G. Knepley } 120677623264SMatthew G. Knepley 120777623264SMatthew G. Knepley #undef __FUNCT__ 120877623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco" 120977623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 121077623264SMatthew G. Knepley { 121177623264SMatthew G. Knepley PetscBool iascii; 121277623264SMatthew G. Knepley PetscErrorCode ierr; 121377623264SMatthew G. Knepley 121477623264SMatthew G. Knepley PetscFunctionBegin; 121577623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 121677623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 121777623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 121877623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 121977623264SMatthew G. Knepley PetscFunctionReturn(0); 122077623264SMatthew G. Knepley } 122177623264SMatthew G. Knepley 122270034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 122370034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 122470034214SMatthew G. Knepley #include <unistd.h> 122570034214SMatthew G. Knepley #endif 122670034214SMatthew G. Knepley /* Chaco does not have an include file */ 122770034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 122870034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 122970034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 123070034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 123170034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 123270034214SMatthew G. Knepley 123370034214SMatthew G. Knepley extern int FREE_GRAPH; 123477623264SMatthew G. Knepley #endif 123570034214SMatthew G. Knepley 123670034214SMatthew G. Knepley #undef __FUNCT__ 123777623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Chaco" 123877623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 123970034214SMatthew G. Knepley { 124077623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 124170034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 124270034214SMatthew G. Knepley MPI_Comm comm; 124370034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 124470034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 124570034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 124670034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 124770034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 124870034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 124970034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 125070034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 125170034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 125270034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 125370034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 125470034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 125570034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 125670034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 125770034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 125870034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 125970034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 126070034214SMatthew G. Knepley short int *assignment; /* Output partition */ 126170034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 126270034214SMatthew G. Knepley PetscInt *points; 126370034214SMatthew G. Knepley int i, v, p; 126470034214SMatthew G. Knepley PetscErrorCode ierr; 126570034214SMatthew G. Knepley 126670034214SMatthew G. Knepley PetscFunctionBegin; 126770034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 126870034214SMatthew G. Knepley if (!numVertices) { 126977623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 127077623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 127170034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 127270034214SMatthew G. Knepley PetscFunctionReturn(0); 127370034214SMatthew G. Knepley } 127470034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 127570034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 127670034214SMatthew G. Knepley 127770034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 127870034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 127970034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 128070034214SMatthew G. Knepley } 128177623264SMatthew G. Knepley mesh_dims[0] = nparts; 128270034214SMatthew G. Knepley mesh_dims[1] = 1; 128370034214SMatthew G. Knepley mesh_dims[2] = 1; 128470034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 128570034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 128670034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 128770034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 128870034214SMatthew G. Knepley { 128970034214SMatthew G. Knepley int piperet; 129070034214SMatthew G. Knepley piperet = pipe(fd_pipe); 129170034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 129270034214SMatthew G. Knepley fd_stdout = dup(1); 129370034214SMatthew G. Knepley close(1); 129470034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 129570034214SMatthew G. Knepley } 129670034214SMatthew G. Knepley #endif 129770034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 129870034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 129970034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 130070034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 130170034214SMatthew G. Knepley { 130270034214SMatthew G. Knepley char msgLog[10000]; 130370034214SMatthew G. Knepley int count; 130470034214SMatthew G. Knepley 130570034214SMatthew G. Knepley fflush(stdout); 130670034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 130770034214SMatthew G. Knepley if (count < 0) count = 0; 130870034214SMatthew G. Knepley msgLog[count] = 0; 130970034214SMatthew G. Knepley close(1); 131070034214SMatthew G. Knepley dup2(fd_stdout, 1); 131170034214SMatthew G. Knepley close(fd_stdout); 131270034214SMatthew G. Knepley close(fd_pipe[0]); 131370034214SMatthew G. Knepley close(fd_pipe[1]); 131470034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 131570034214SMatthew G. Knepley } 131670034214SMatthew G. Knepley #endif 131770034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 131877623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 131970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 132077623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 132170034214SMatthew G. Knepley } 132277623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 132370034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 132477623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 132570034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 132670034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 132770034214SMatthew G. Knepley } 132870034214SMatthew G. Knepley } 132970034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 133070034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 133170034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 133270034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 133370034214SMatthew G. Knepley } 133470034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 133570034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 133670034214SMatthew G. Knepley PetscFunctionReturn(0); 133777623264SMatthew G. Knepley #else 133877623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 133970034214SMatthew G. Knepley #endif 134077623264SMatthew G. Knepley } 134177623264SMatthew G. Knepley 134277623264SMatthew G. Knepley #undef __FUNCT__ 134377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Chaco" 134477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 134577623264SMatthew G. Knepley { 134677623264SMatthew G. Knepley PetscFunctionBegin; 134777623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 134877623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 134977623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 135077623264SMatthew G. Knepley PetscFunctionReturn(0); 135177623264SMatthew G. Knepley } 135277623264SMatthew G. Knepley 135377623264SMatthew G. Knepley /*MC 135477623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 135577623264SMatthew G. Knepley 135677623264SMatthew G. Knepley Level: intermediate 135777623264SMatthew G. Knepley 135877623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 135977623264SMatthew G. Knepley M*/ 136077623264SMatthew G. Knepley 136177623264SMatthew G. Knepley #undef __FUNCT__ 136277623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Chaco" 136377623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 136477623264SMatthew G. Knepley { 136577623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 136677623264SMatthew G. Knepley PetscErrorCode ierr; 136777623264SMatthew G. Knepley 136877623264SMatthew G. Knepley PetscFunctionBegin; 136977623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 137077623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 137177623264SMatthew G. Knepley part->data = p; 137277623264SMatthew G. Knepley 137377623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 137477623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 137577623264SMatthew G. Knepley PetscFunctionReturn(0); 137677623264SMatthew G. Knepley } 137777623264SMatthew G. Knepley 137877623264SMatthew G. Knepley #undef __FUNCT__ 137977623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_ParMetis" 138077623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 138177623264SMatthew G. Knepley { 138277623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 138377623264SMatthew G. Knepley PetscErrorCode ierr; 138477623264SMatthew G. Knepley 138577623264SMatthew G. Knepley PetscFunctionBegin; 138677623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 138777623264SMatthew G. Knepley PetscFunctionReturn(0); 138877623264SMatthew G. Knepley } 138977623264SMatthew G. Knepley 139077623264SMatthew G. Knepley #undef __FUNCT__ 139177623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis_Ascii" 139277623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 139377623264SMatthew G. Knepley { 139477623264SMatthew G. Knepley PetscViewerFormat format; 139577623264SMatthew G. Knepley PetscErrorCode ierr; 139677623264SMatthew G. Knepley 139777623264SMatthew G. Knepley PetscFunctionBegin; 139877623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 139977623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis Graph Partitioner:\n");CHKERRQ(ierr); 140077623264SMatthew G. Knepley PetscFunctionReturn(0); 140177623264SMatthew G. Knepley } 140277623264SMatthew G. Knepley 140377623264SMatthew G. Knepley #undef __FUNCT__ 140477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis" 140577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 140677623264SMatthew G. Knepley { 140777623264SMatthew G. Knepley PetscBool iascii; 140877623264SMatthew G. Knepley PetscErrorCode ierr; 140977623264SMatthew G. Knepley 141077623264SMatthew G. Knepley PetscFunctionBegin; 141177623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 141277623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 141377623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 141477623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 141577623264SMatthew G. Knepley PetscFunctionReturn(0); 141677623264SMatthew G. Knepley } 141770034214SMatthew G. Knepley 141870034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 141970034214SMatthew G. Knepley #include <parmetis.h> 142077623264SMatthew G. Knepley #endif 142170034214SMatthew G. Knepley 142270034214SMatthew G. Knepley #undef __FUNCT__ 142377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_ParMetis" 142477623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 142570034214SMatthew G. Knepley { 142677623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 142770034214SMatthew G. Knepley MPI_Comm comm; 1428deea36a5SMatthew G. Knepley PetscSection section; 142970034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 143070034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 143170034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 143270034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 143370034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 143470034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 143570034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 143670034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 143770034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 143870034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 143970034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 144070034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 144170034214SMatthew G. Knepley /* Outputs */ 144270034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 144370034214SMatthew G. Knepley PetscInt *assignment, *points; 144477623264SMatthew G. Knepley PetscMPIInt rank, p, v, i; 144570034214SMatthew G. Knepley PetscErrorCode ierr; 144670034214SMatthew G. Knepley 144770034214SMatthew G. Knepley PetscFunctionBegin; 144877623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 144970034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 145070034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 145170034214SMatthew G. Knepley /* Calculate vertex distribution */ 1452cd0de0f2SShri ierr = PetscMalloc5(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment,nvtxs,&vwgt);CHKERRQ(ierr); 145370034214SMatthew G. Knepley vtxdist[0] = 0; 145470034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 145570034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 145670034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 145770034214SMatthew G. Knepley } 145870034214SMatthew G. Knepley /* Calculate weights */ 145970034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 146070034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 146170034214SMatthew G. Knepley } 146270034214SMatthew G. Knepley ubvec[0] = 1.05; 1463deea36a5SMatthew G. Knepley /* Weight cells by dofs on cell by default */ 1464deea36a5SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1465deea36a5SMatthew G. Knepley if (section) { 1466deea36a5SMatthew G. Knepley PetscInt cStart, cEnd, dof; 146770034214SMatthew G. Knepley 1468deea36a5SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1469deea36a5SMatthew G. Knepley for (v = cStart; v < cEnd; ++v) { 1470deea36a5SMatthew G. Knepley ierr = PetscSectionGetDof(section, v, &dof);CHKERRQ(ierr); 1471deea36a5SMatthew G. Knepley vwgt[v-cStart] = PetscMax(dof, 1); 1472deea36a5SMatthew G. Knepley } 1473deea36a5SMatthew G. Knepley } else { 1474deea36a5SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) vwgt[v] = 1; 1475cd0de0f2SShri } 1476cd0de0f2SShri 147770034214SMatthew G. Knepley if (nparts == 1) { 14789fc93327SToby Isaac ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));CHKERRQ(ierr); 147970034214SMatthew G. Knepley } else { 148070034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 148170034214SMatthew G. Knepley if (!rank) { 148270034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 148370034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 148470034214SMatthew G. Knepley PetscStackPop; 148570034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 148670034214SMatthew G. Knepley } 148770034214SMatthew G. Knepley } else { 148870034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 148970034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 149070034214SMatthew G. Knepley PetscStackPop; 149170034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 149270034214SMatthew G. Knepley } 149370034214SMatthew G. Knepley } 149470034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 149577623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 149677623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 149777623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 149870034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 149977623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 150070034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 150170034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 150270034214SMatthew G. Knepley } 150370034214SMatthew G. Knepley } 150470034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 150570034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 1506cd0de0f2SShri ierr = PetscFree5(vtxdist,tpwgts,ubvec,assignment,vwgt);CHKERRQ(ierr); 15079b80ac48SMatthew G. Knepley PetscFunctionReturn(0); 150870034214SMatthew G. Knepley #else 150977623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 151070034214SMatthew G. Knepley #endif 151170034214SMatthew G. Knepley } 151270034214SMatthew G. Knepley 151377623264SMatthew G. Knepley #undef __FUNCT__ 151477623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_ParMetis" 151577623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 151677623264SMatthew G. Knepley { 151777623264SMatthew G. Knepley PetscFunctionBegin; 151877623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 151977623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 152077623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 152177623264SMatthew G. Knepley PetscFunctionReturn(0); 152277623264SMatthew G. Knepley } 152377623264SMatthew G. Knepley 152477623264SMatthew G. Knepley /*MC 152577623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 152677623264SMatthew G. Knepley 152777623264SMatthew G. Knepley Level: intermediate 152877623264SMatthew G. Knepley 152977623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 153077623264SMatthew G. Knepley M*/ 153177623264SMatthew G. Knepley 153277623264SMatthew G. Knepley #undef __FUNCT__ 153377623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_ParMetis" 153477623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 153577623264SMatthew G. Knepley { 153677623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 153777623264SMatthew G. Knepley PetscErrorCode ierr; 153877623264SMatthew G. Knepley 153977623264SMatthew G. Knepley PetscFunctionBegin; 154077623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 154177623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 154277623264SMatthew G. Knepley part->data = p; 154377623264SMatthew G. Knepley 154477623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 154577623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 154670034214SMatthew G. Knepley PetscFunctionReturn(0); 154770034214SMatthew G. Knepley } 154870034214SMatthew G. Knepley 154970034214SMatthew G. Knepley #undef __FUNCT__ 15505680f57bSMatthew G. Knepley #define __FUNCT__ "DMPlexGetPartitioner" 15515680f57bSMatthew G. Knepley /*@ 15525680f57bSMatthew G. Knepley DMPlexGetPartitioner - Get the mesh partitioner 15535680f57bSMatthew G. Knepley 15545680f57bSMatthew G. Knepley Not collective 15555680f57bSMatthew G. Knepley 15565680f57bSMatthew G. Knepley Input Parameter: 15575680f57bSMatthew G. Knepley . dm - The DM 15585680f57bSMatthew G. Knepley 15595680f57bSMatthew G. Knepley Output Parameter: 15605680f57bSMatthew G. Knepley . part - The PetscPartitioner 15615680f57bSMatthew G. Knepley 15625680f57bSMatthew G. Knepley Level: developer 15635680f57bSMatthew G. Knepley 156498599a47SLawrence Mitchell Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner. 156598599a47SLawrence Mitchell 156698599a47SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerCreate() 15675680f57bSMatthew G. Knepley @*/ 15685680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part) 15695680f57bSMatthew G. Knepley { 15705680f57bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 15715680f57bSMatthew G. Knepley 15725680f57bSMatthew G. Knepley PetscFunctionBegin; 15735680f57bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15745680f57bSMatthew G. Knepley PetscValidPointer(part, 2); 15755680f57bSMatthew G. Knepley *part = mesh->partitioner; 15765680f57bSMatthew G. Knepley PetscFunctionReturn(0); 15775680f57bSMatthew G. Knepley } 15785680f57bSMatthew G. Knepley 15795680f57bSMatthew G. Knepley #undef __FUNCT__ 158071bb2955SLawrence Mitchell #define __FUNCT__ "DMPlexSetPartitioner" 158171bb2955SLawrence Mitchell /*@ 158271bb2955SLawrence Mitchell DMPlexSetPartitioner - Set the mesh partitioner 158371bb2955SLawrence Mitchell 158471bb2955SLawrence Mitchell logically collective on dm and part 158571bb2955SLawrence Mitchell 158671bb2955SLawrence Mitchell Input Parameters: 158771bb2955SLawrence Mitchell + dm - The DM 158871bb2955SLawrence Mitchell - part - The partitioner 158971bb2955SLawrence Mitchell 159071bb2955SLawrence Mitchell Level: developer 159171bb2955SLawrence Mitchell 159271bb2955SLawrence Mitchell Note: Any existing PetscPartitioner will be destroyed. 159371bb2955SLawrence Mitchell 159471bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate() 159571bb2955SLawrence Mitchell @*/ 159671bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part) 159771bb2955SLawrence Mitchell { 159871bb2955SLawrence Mitchell DM_Plex *mesh = (DM_Plex *) dm->data; 159971bb2955SLawrence Mitchell PetscErrorCode ierr; 160071bb2955SLawrence Mitchell 160171bb2955SLawrence Mitchell PetscFunctionBegin; 160271bb2955SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 160371bb2955SLawrence Mitchell PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2); 160471bb2955SLawrence Mitchell ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr); 160571bb2955SLawrence Mitchell ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 160671bb2955SLawrence Mitchell mesh->partitioner = part; 160771bb2955SLawrence Mitchell PetscFunctionReturn(0); 160871bb2955SLawrence Mitchell } 160971bb2955SLawrence Mitchell 161071bb2955SLawrence Mitchell #undef __FUNCT__ 1611270bba0cSToby Isaac #define __FUNCT__ "DMPlexPartitionLabelClosure_Tree" 16126a5a2ffdSToby Isaac static PetscErrorCode DMPlexPartitionLabelClosure_Tree(DM dm, DMLabel label, PetscInt rank, PetscInt point, PetscBool up, PetscBool down) 1613270bba0cSToby Isaac { 1614270bba0cSToby Isaac PetscErrorCode ierr; 1615270bba0cSToby Isaac 1616270bba0cSToby Isaac PetscFunctionBegin; 16176a5a2ffdSToby Isaac if (up) { 16186a5a2ffdSToby Isaac PetscInt parent; 16196a5a2ffdSToby Isaac 1620270bba0cSToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 16216a5a2ffdSToby Isaac if (parent != point) { 16226a5a2ffdSToby Isaac PetscInt closureSize, *closure = NULL, i; 16236a5a2ffdSToby Isaac 1624270bba0cSToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1625270bba0cSToby Isaac for (i = 0; i < closureSize; i++) { 1626270bba0cSToby Isaac PetscInt cpoint = closure[2*i]; 1627270bba0cSToby Isaac 1628270bba0cSToby Isaac ierr = DMLabelSetValue(label,cpoint,rank);CHKERRQ(ierr); 16296a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1630270bba0cSToby Isaac } 1631270bba0cSToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 16326a5a2ffdSToby Isaac } 16336a5a2ffdSToby Isaac } 16346a5a2ffdSToby Isaac if (down) { 16356a5a2ffdSToby Isaac PetscInt numChildren; 16366a5a2ffdSToby Isaac const PetscInt *children; 16376a5a2ffdSToby Isaac 16386a5a2ffdSToby Isaac ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr); 16396a5a2ffdSToby Isaac if (numChildren) { 16406a5a2ffdSToby Isaac PetscInt i; 16416a5a2ffdSToby Isaac 16426a5a2ffdSToby Isaac for (i = 0; i < numChildren; i++) { 16436a5a2ffdSToby Isaac PetscInt cpoint = children[i]; 16446a5a2ffdSToby Isaac 16456a5a2ffdSToby Isaac ierr = DMLabelSetValue(label,cpoint,rank);CHKERRQ(ierr); 16466a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr); 16476a5a2ffdSToby Isaac } 16486a5a2ffdSToby Isaac } 16496a5a2ffdSToby Isaac } 1650270bba0cSToby Isaac PetscFunctionReturn(0); 1651270bba0cSToby Isaac } 1652270bba0cSToby Isaac 1653270bba0cSToby Isaac #undef __FUNCT__ 16545abbe4feSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelClosure" 16555abbe4feSMichael Lange /*@ 16565abbe4feSMichael Lange DMPlexPartitionLabelClosure - Add the closure of all points to the partition label 16575abbe4feSMichael Lange 16585abbe4feSMichael Lange Input Parameters: 16595abbe4feSMichael Lange + dm - The DM 16605abbe4feSMichael Lange - label - DMLabel assinging ranks to remote roots 16615abbe4feSMichael Lange 16625abbe4feSMichael Lange Level: developer 16635abbe4feSMichael Lange 16645abbe4feSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 16655abbe4feSMichael Lange @*/ 16665abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label) 16679ffc88e4SToby Isaac { 16685abbe4feSMichael Lange IS rankIS, pointIS; 16695abbe4feSMichael Lange const PetscInt *ranks, *points; 16705abbe4feSMichael Lange PetscInt numRanks, numPoints, r, p, c, closureSize; 16715abbe4feSMichael Lange PetscInt *closure = NULL; 16729ffc88e4SToby Isaac PetscErrorCode ierr; 16739ffc88e4SToby Isaac 16749ffc88e4SToby Isaac PetscFunctionBegin; 16755abbe4feSMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 16765abbe4feSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 16775abbe4feSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 16785abbe4feSMichael Lange for (r = 0; r < numRanks; ++r) { 16795abbe4feSMichael Lange const PetscInt rank = ranks[r]; 16809ffc88e4SToby Isaac 16815abbe4feSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 16825abbe4feSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 16835abbe4feSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 16845abbe4feSMichael Lange for (p = 0; p < numPoints; ++p) { 16855abbe4feSMichael Lange ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1686270bba0cSToby Isaac for (c = 0; c < closureSize*2; c += 2) { 1687270bba0cSToby Isaac ierr = DMLabelSetValue(label, closure[c], rank);CHKERRQ(ierr); 16886a5a2ffdSToby Isaac ierr = DMPlexPartitionLabelClosure_Tree(dm,label,rank,closure[c],PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr); 1689270bba0cSToby Isaac } 16909ffc88e4SToby Isaac } 16915abbe4feSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 16925abbe4feSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 16939ffc88e4SToby Isaac } 16947de78196SMichael Lange if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);} 16955abbe4feSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 16965abbe4feSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 16979ffc88e4SToby Isaac PetscFunctionReturn(0); 16989ffc88e4SToby Isaac } 16999ffc88e4SToby Isaac 17009ffc88e4SToby Isaac #undef __FUNCT__ 170124d039d7SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelAdjacency" 170224d039d7SMichael Lange /*@ 170324d039d7SMichael Lange DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label 170424d039d7SMichael Lange 170524d039d7SMichael Lange Input Parameters: 170624d039d7SMichael Lange + dm - The DM 170724d039d7SMichael Lange - label - DMLabel assinging ranks to remote roots 170824d039d7SMichael Lange 170924d039d7SMichael Lange Level: developer 171024d039d7SMichael Lange 171124d039d7SMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 171224d039d7SMichael Lange @*/ 171324d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label) 171470034214SMatthew G. Knepley { 171524d039d7SMichael Lange IS rankIS, pointIS; 171624d039d7SMichael Lange const PetscInt *ranks, *points; 171724d039d7SMichael Lange PetscInt numRanks, numPoints, r, p, a, adjSize; 171824d039d7SMichael Lange PetscInt *adj = NULL; 171970034214SMatthew G. Knepley PetscErrorCode ierr; 172070034214SMatthew G. Knepley 172170034214SMatthew G. Knepley PetscFunctionBegin; 172224d039d7SMichael Lange ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr); 172324d039d7SMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 172424d039d7SMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 172524d039d7SMichael Lange for (r = 0; r < numRanks; ++r) { 172624d039d7SMichael Lange const PetscInt rank = ranks[r]; 172770034214SMatthew G. Knepley 172824d039d7SMichael Lange ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr); 172924d039d7SMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 173024d039d7SMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 173170034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 173224d039d7SMichael Lange adjSize = PETSC_DETERMINE; 173324d039d7SMichael Lange ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr); 173424d039d7SMichael Lange for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);} 173570034214SMatthew G. Knepley } 173624d039d7SMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 173724d039d7SMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 173870034214SMatthew G. Knepley } 173924d039d7SMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 174024d039d7SMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 174124d039d7SMichael Lange ierr = PetscFree(adj);CHKERRQ(ierr); 174224d039d7SMichael Lange PetscFunctionReturn(0); 174370034214SMatthew G. Knepley } 174470034214SMatthew G. Knepley 174524d039d7SMichael Lange #undef __FUNCT__ 1746be200f8dSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelPropagate" 1747be200f8dSMichael Lange /*@ 1748be200f8dSMichael Lange DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF 1749be200f8dSMichael Lange 1750be200f8dSMichael Lange Input Parameters: 1751be200f8dSMichael Lange + dm - The DM 1752be200f8dSMichael Lange - label - DMLabel assinging ranks to remote roots 1753be200f8dSMichael Lange 1754be200f8dSMichael Lange Level: developer 1755be200f8dSMichael Lange 1756be200f8dSMichael Lange Note: This is required when generating multi-level overlaps to capture 1757be200f8dSMichael Lange overlap points from non-neighbouring partitions. 1758be200f8dSMichael Lange 1759be200f8dSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 1760be200f8dSMichael Lange @*/ 1761be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label) 1762be200f8dSMichael Lange { 1763be200f8dSMichael Lange MPI_Comm comm; 1764be200f8dSMichael Lange PetscMPIInt rank; 1765be200f8dSMichael Lange PetscSF sfPoint; 17665d04f6ebSMichael Lange DMLabel lblRoots, lblLeaves; 1767be200f8dSMichael Lange IS rankIS, pointIS; 1768be200f8dSMichael Lange const PetscInt *ranks; 1769be200f8dSMichael Lange PetscInt numRanks, r; 1770be200f8dSMichael Lange PetscErrorCode ierr; 1771be200f8dSMichael Lange 1772be200f8dSMichael Lange PetscFunctionBegin; 1773be200f8dSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1774be200f8dSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1775be200f8dSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 17765d04f6ebSMichael Lange /* Pull point contributions from remote leaves into local roots */ 17775d04f6ebSMichael Lange ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 17785d04f6ebSMichael Lange ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr); 17795d04f6ebSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 17805d04f6ebSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 17815d04f6ebSMichael Lange for (r = 0; r < numRanks; ++r) { 17825d04f6ebSMichael Lange const PetscInt remoteRank = ranks[r]; 17835d04f6ebSMichael Lange if (remoteRank == rank) continue; 17845d04f6ebSMichael Lange ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr); 17855d04f6ebSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 17865d04f6ebSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 17875d04f6ebSMichael Lange } 17885d04f6ebSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 17895d04f6ebSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 17905d04f6ebSMichael Lange ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 1791be200f8dSMichael Lange /* Push point contributions from roots into remote leaves */ 1792be200f8dSMichael Lange ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 1793be200f8dSMichael Lange ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr); 1794be200f8dSMichael Lange ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr); 1795be200f8dSMichael Lange ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr); 1796be200f8dSMichael Lange for (r = 0; r < numRanks; ++r) { 1797be200f8dSMichael Lange const PetscInt remoteRank = ranks[r]; 1798be200f8dSMichael Lange if (remoteRank == rank) continue; 1799be200f8dSMichael Lange ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr); 1800be200f8dSMichael Lange ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr); 1801be200f8dSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1802be200f8dSMichael Lange } 1803be200f8dSMichael Lange ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr); 1804be200f8dSMichael Lange ierr = ISDestroy(&rankIS);CHKERRQ(ierr); 1805be200f8dSMichael Lange ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 1806be200f8dSMichael Lange PetscFunctionReturn(0); 1807be200f8dSMichael Lange } 1808be200f8dSMichael Lange 1809be200f8dSMichael Lange #undef __FUNCT__ 18101fd9873aSMichael Lange #define __FUNCT__ "DMPlexPartitionLabelInvert" 18111fd9873aSMichael Lange /*@ 18121fd9873aSMichael Lange DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label 18131fd9873aSMichael Lange 18141fd9873aSMichael Lange Input Parameters: 18151fd9873aSMichael Lange + dm - The DM 18161fd9873aSMichael Lange . rootLabel - DMLabel assinging ranks to local roots 18171fd9873aSMichael Lange . processSF - A star forest mapping into the local index on each remote rank 18181fd9873aSMichael Lange 18191fd9873aSMichael Lange Output Parameter: 18201fd9873aSMichael Lange - leafLabel - DMLabel assinging ranks to remote roots 18211fd9873aSMichael Lange 18221fd9873aSMichael Lange Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The 18231fd9873aSMichael Lange resulting leafLabel is a receiver mapping of remote roots to their parent rank. 18241fd9873aSMichael Lange 18251fd9873aSMichael Lange Level: developer 18261fd9873aSMichael Lange 18271fd9873aSMichael Lange .seealso: DMPlexPartitionLabelCreateSF, DMPlexDistribute(), DMPlexCreateOverlap 18281fd9873aSMichael Lange @*/ 18291fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel) 18301fd9873aSMichael Lange { 18311fd9873aSMichael Lange MPI_Comm comm; 18321fd9873aSMichael Lange PetscMPIInt rank, numProcs; 18331fd9873aSMichael Lange PetscInt p, n, numNeighbors, size, l, nleaves; 18341fd9873aSMichael Lange PetscSF sfPoint; 18351fd9873aSMichael Lange PetscSFNode *rootPoints, *leafPoints; 18361fd9873aSMichael Lange PetscSection rootSection, leafSection; 18371fd9873aSMichael Lange const PetscSFNode *remote; 18381fd9873aSMichael Lange const PetscInt *local, *neighbors; 18391fd9873aSMichael Lange IS valueIS; 18401fd9873aSMichael Lange PetscErrorCode ierr; 18411fd9873aSMichael Lange 18421fd9873aSMichael Lange PetscFunctionBegin; 18431fd9873aSMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 18441fd9873aSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 18451fd9873aSMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 18461fd9873aSMichael Lange ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 18471fd9873aSMichael Lange 18481fd9873aSMichael Lange /* Convert to (point, rank) and use actual owners */ 18491fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr); 18501fd9873aSMichael Lange ierr = PetscSectionSetChart(rootSection, 0, numProcs);CHKERRQ(ierr); 18511fd9873aSMichael Lange ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr); 18521fd9873aSMichael Lange ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 18531fd9873aSMichael Lange ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 18541fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 18551fd9873aSMichael Lange PetscInt numPoints; 18561fd9873aSMichael Lange 18571fd9873aSMichael Lange ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr); 18581fd9873aSMichael Lange ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr); 18591fd9873aSMichael Lange } 18601fd9873aSMichael Lange ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 18611fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr); 18621fd9873aSMichael Lange ierr = PetscMalloc1(size, &rootPoints);CHKERRQ(ierr); 18631fd9873aSMichael Lange ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 18641fd9873aSMichael Lange for (n = 0; n < numNeighbors; ++n) { 18651fd9873aSMichael Lange IS pointIS; 18661fd9873aSMichael Lange const PetscInt *points; 18671fd9873aSMichael Lange PetscInt off, numPoints, p; 18681fd9873aSMichael Lange 18691fd9873aSMichael Lange ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr); 18701fd9873aSMichael Lange ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr); 18711fd9873aSMichael Lange ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 18721fd9873aSMichael Lange ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 18731fd9873aSMichael Lange for (p = 0; p < numPoints; ++p) { 1874f8987ae8SMichael Lange if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);} 1875f8987ae8SMichael Lange else {l = -1;} 18761fd9873aSMichael Lange if (l >= 0) {rootPoints[off+p] = remote[l];} 18771fd9873aSMichael Lange else {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;} 18781fd9873aSMichael Lange } 18791fd9873aSMichael Lange ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 18801fd9873aSMichael Lange ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 18811fd9873aSMichael Lange } 18821fd9873aSMichael Lange ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 18831fd9873aSMichael Lange ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 18841fd9873aSMichael Lange /* Communicate overlap */ 18851fd9873aSMichael Lange ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr); 18861fd9873aSMichael Lange ierr = DMPlexDistributeData(dm, processSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr); 18871fd9873aSMichael Lange /* Filter remote contributions (ovLeafPoints) into the overlapSF */ 18881fd9873aSMichael Lange ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr); 18891fd9873aSMichael Lange for (p = 0; p < size; p++) { 18901fd9873aSMichael Lange ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr); 18911fd9873aSMichael Lange } 18921fd9873aSMichael Lange ierr = PetscFree(rootPoints);CHKERRQ(ierr); 18931fd9873aSMichael Lange ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 18941fd9873aSMichael Lange ierr = PetscFree(leafPoints);CHKERRQ(ierr); 18951fd9873aSMichael Lange ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 18961fd9873aSMichael Lange PetscFunctionReturn(0); 18971fd9873aSMichael Lange } 18981fd9873aSMichael Lange 18991fd9873aSMichael Lange #undef __FUNCT__ 1900aa3148a8SMichael Lange #define __FUNCT__ "DMPlexPartitionLabelCreateSF" 1901aa3148a8SMichael Lange /*@ 1902aa3148a8SMichael Lange DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points 1903aa3148a8SMichael Lange 1904aa3148a8SMichael Lange Input Parameters: 1905aa3148a8SMichael Lange + dm - The DM 1906aa3148a8SMichael Lange . label - DMLabel assinging ranks to remote roots 1907aa3148a8SMichael Lange 1908aa3148a8SMichael Lange Output Parameter: 1909aa3148a8SMichael Lange - sf - The star forest communication context encapsulating the defined mapping 1910aa3148a8SMichael Lange 1911aa3148a8SMichael Lange Note: The incoming label is a receiver mapping of remote points to their parent rank. 1912aa3148a8SMichael Lange 1913aa3148a8SMichael Lange Level: developer 1914aa3148a8SMichael Lange 1915aa3148a8SMichael Lange .seealso: DMPlexDistribute(), DMPlexCreateOverlap 1916aa3148a8SMichael Lange @*/ 1917aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf) 1918aa3148a8SMichael Lange { 191943f7d02bSMichael Lange PetscMPIInt rank, numProcs; 192043f7d02bSMichael Lange PetscInt n, numRemote, p, numPoints, pStart, pEnd, idx = 0; 1921aa3148a8SMichael Lange PetscSFNode *remotePoints; 192243f7d02bSMichael Lange IS remoteRootIS; 192343f7d02bSMichael Lange const PetscInt *remoteRoots; 1924aa3148a8SMichael Lange PetscErrorCode ierr; 1925aa3148a8SMichael Lange 1926aa3148a8SMichael Lange PetscFunctionBegin; 192743f7d02bSMichael Lange ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1928aa3148a8SMichael Lange ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 1929aa3148a8SMichael Lange 1930aa3148a8SMichael Lange for (numRemote = 0, n = 0; n < numProcs; ++n) { 1931aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 1932aa3148a8SMichael Lange numRemote += numPoints; 1933aa3148a8SMichael Lange } 1934aa3148a8SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 193543f7d02bSMichael Lange /* Put owned points first */ 193643f7d02bSMichael Lange ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr); 193743f7d02bSMichael Lange if (numPoints > 0) { 193843f7d02bSMichael Lange ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr); 193943f7d02bSMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 194043f7d02bSMichael Lange for (p = 0; p < numPoints; p++) { 194143f7d02bSMichael Lange remotePoints[idx].index = remoteRoots[p]; 194243f7d02bSMichael Lange remotePoints[idx].rank = rank; 194343f7d02bSMichael Lange idx++; 194443f7d02bSMichael Lange } 194543f7d02bSMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 194643f7d02bSMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 194743f7d02bSMichael Lange } 194843f7d02bSMichael Lange /* Now add remote points */ 194943f7d02bSMichael Lange for (n = 0; n < numProcs; ++n) { 1950aa3148a8SMichael Lange ierr = DMLabelGetStratumSize(label, n, &numPoints);CHKERRQ(ierr); 195143f7d02bSMichael Lange if (numPoints <= 0 || n == rank) continue; 1952aa3148a8SMichael Lange ierr = DMLabelGetStratumIS(label, n, &remoteRootIS);CHKERRQ(ierr); 1953aa3148a8SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1954aa3148a8SMichael Lange for (p = 0; p < numPoints; p++) { 1955aa3148a8SMichael Lange remotePoints[idx].index = remoteRoots[p]; 1956aa3148a8SMichael Lange remotePoints[idx].rank = n; 1957aa3148a8SMichael Lange idx++; 1958aa3148a8SMichael Lange } 1959aa3148a8SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 1960aa3148a8SMichael Lange ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr); 1961aa3148a8SMichael Lange } 1962aa3148a8SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr); 1963aa3148a8SMichael Lange ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1964aa3148a8SMichael Lange ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 196570034214SMatthew G. Knepley PetscFunctionReturn(0); 196670034214SMatthew G. Knepley } 1967