170034214SMatthew G. Knepley #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 270034214SMatthew G. Knepley 3*77623264SMatthew G. Knepley PetscClassId PETSCPARTITIONER_CLASSID = 0; 4*77623264SMatthew G. Knepley 5*77623264SMatthew G. Knepley PetscFunctionList PetscPartitionerList = NULL; 6*77623264SMatthew G. Knepley PetscBool PetscPartitionerRegisterAllCalled = PETSC_FALSE; 7*77623264SMatthew G. Knepley 8*77623264SMatthew G. Knepley PetscBool ChacoPartitionercite = PETSC_FALSE; 9*77623264SMatthew G. Knepley const char ChacoPartitionerCitation[] = "@inproceedings{Chaco95,\n" 10*77623264SMatthew G. Knepley " author = {Bruce Hendrickson and Robert Leland},\n" 11*77623264SMatthew G. Knepley " title = {A multilevel algorithm for partitioning graphs},\n" 12*77623264SMatthew G. Knepley " booktitle = {Supercomputing '95: Proceedings of the 1995 ACM/IEEE Conference on Supercomputing (CDROM)}," 13*77623264SMatthew G. Knepley " isbn = {0-89791-816-9},\n" 14*77623264SMatthew G. Knepley " pages = {28},\n" 15*77623264SMatthew G. Knepley " doi = {http://doi.acm.org/10.1145/224170.224228},\n" 16*77623264SMatthew G. Knepley " publisher = {ACM Press},\n" 17*77623264SMatthew G. Knepley " address = {New York},\n" 18*77623264SMatthew G. Knepley " year = {1995}\n}\n"; 19*77623264SMatthew G. Knepley 20*77623264SMatthew G. Knepley PetscBool ParMetisPartitionercite = PETSC_FALSE; 21*77623264SMatthew G. Knepley const char ParMetisPartitionerCitation[] = "@article{KarypisKumar98,\n" 22*77623264SMatthew G. Knepley " author = {George Karypis and Vipin Kumar},\n" 23*77623264SMatthew G. Knepley " title = {A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering},\n" 24*77623264SMatthew G. Knepley " journal = {Journal of Parallel and Distributed Computing},\n" 25*77623264SMatthew G. Knepley " volume = {48},\n" 26*77623264SMatthew G. Knepley " pages = {71--85},\n" 27*77623264SMatthew G. Knepley " year = {1998}\n}\n"; 28*77623264SMatthew G. Knepley 2970034214SMatthew G. Knepley #undef __FUNCT__ 3070034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 3170034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 3270034214SMatthew G. Knepley { 3370034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 3470034214SMatthew G. Knepley PetscInt numFaceCases = 0; 3570034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 3670034214SMatthew G. Knepley PetscInt *off, *adj; 3770034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 3870034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 3970034214SMatthew G. Knepley PetscErrorCode ierr; 4070034214SMatthew G. Knepley 4170034214SMatthew G. Knepley PetscFunctionBegin; 4270034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 43c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4470034214SMatthew G. Knepley cellDim = dim - cellHeight; 4570034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4670034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 4770034214SMatthew G. Knepley if (cEnd - cStart == 0) { 4870034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 4970034214SMatthew G. Knepley if (offsets) *offsets = NULL; 5070034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 5170034214SMatthew G. Knepley PetscFunctionReturn(0); 5270034214SMatthew G. Knepley } 5370034214SMatthew G. Knepley numCells = cEnd - cStart; 5470034214SMatthew G. Knepley faceDepth = depth - cellHeight; 5570034214SMatthew G. Knepley if (dim == depth) { 5670034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 5770034214SMatthew G. Knepley 5870034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 5970034214SMatthew G. Knepley /* Count neighboring cells */ 6070034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 6170034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 6270034214SMatthew G. Knepley const PetscInt *support; 6370034214SMatthew G. Knepley PetscInt supportSize; 6470034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6570034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6670034214SMatthew G. Knepley if (supportSize == 2) { 679ffc88e4SToby Isaac PetscInt numChildren; 689ffc88e4SToby Isaac 699ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 709ffc88e4SToby Isaac if (!numChildren) { 7170034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 7270034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 7370034214SMatthew G. Knepley } 7470034214SMatthew G. Knepley } 759ffc88e4SToby Isaac } 7670034214SMatthew G. Knepley /* Prefix sum */ 7770034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 7870034214SMatthew G. Knepley if (adjacency) { 7970034214SMatthew G. Knepley PetscInt *tmp; 8070034214SMatthew G. Knepley 8170034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 8270034214SMatthew G. Knepley ierr = PetscMalloc1((numCells+1), &tmp);CHKERRQ(ierr); 8370034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 8470034214SMatthew G. Knepley /* Get neighboring cells */ 8570034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 8670034214SMatthew G. Knepley const PetscInt *support; 8770034214SMatthew G. Knepley PetscInt supportSize; 8870034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 8970034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 9070034214SMatthew G. Knepley if (supportSize == 2) { 919ffc88e4SToby Isaac PetscInt numChildren; 929ffc88e4SToby Isaac 939ffc88e4SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 949ffc88e4SToby Isaac if (!numChildren) { 9570034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 9670034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 9770034214SMatthew G. Knepley } 9870034214SMatthew G. Knepley } 999ffc88e4SToby Isaac } 10070034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 10170034214SMatthew 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); 10270034214SMatthew G. Knepley #endif 10370034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 10470034214SMatthew G. Knepley } 10570034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 10670034214SMatthew G. Knepley if (offsets) *offsets = off; 10770034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 10870034214SMatthew G. Knepley PetscFunctionReturn(0); 10970034214SMatthew G. Knepley } 11070034214SMatthew G. Knepley /* Setup face recognition */ 11170034214SMatthew G. Knepley if (faceDepth == 1) { 11270034214SMatthew 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 */ 11370034214SMatthew G. Knepley 11470034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 11570034214SMatthew G. Knepley PetscInt corners; 11670034214SMatthew G. Knepley 11770034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 11870034214SMatthew G. Knepley if (!cornersSeen[corners]) { 11970034214SMatthew G. Knepley PetscInt nFV; 12070034214SMatthew G. Knepley 12170034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 12270034214SMatthew G. Knepley cornersSeen[corners] = 1; 12370034214SMatthew G. Knepley 12470034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 12570034214SMatthew G. Knepley 12670034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 12770034214SMatthew G. Knepley } 12870034214SMatthew G. Knepley } 12970034214SMatthew G. Knepley } 13070034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 13170034214SMatthew G. Knepley /* Count neighboring cells */ 13270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 13370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 13470034214SMatthew G. Knepley 1358b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 13670034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 13770034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 13870034214SMatthew G. Knepley PetscInt cellPair[2]; 13970034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 14070034214SMatthew G. Knepley PetscInt meetSize = 0; 14170034214SMatthew G. Knepley const PetscInt *meet = NULL; 14270034214SMatthew G. Knepley 14370034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 14470034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 14570034214SMatthew G. Knepley if (!found) { 14670034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 14770034214SMatthew G. Knepley if (meetSize) { 14870034214SMatthew G. Knepley PetscInt f; 14970034214SMatthew G. Knepley 15070034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 15170034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 15270034214SMatthew G. Knepley found = PETSC_TRUE; 15370034214SMatthew G. Knepley break; 15470034214SMatthew G. Knepley } 15570034214SMatthew G. Knepley } 15670034214SMatthew G. Knepley } 15770034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 15870034214SMatthew G. Knepley } 15970034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 16070034214SMatthew G. Knepley } 16170034214SMatthew G. Knepley } 16270034214SMatthew G. Knepley /* Prefix sum */ 16370034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 16470034214SMatthew G. Knepley 16570034214SMatthew G. Knepley if (adjacency) { 16670034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 16770034214SMatthew G. Knepley /* Get neighboring cells */ 16870034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 16970034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 17070034214SMatthew G. Knepley PetscInt cellOffset = 0; 17170034214SMatthew G. Knepley 1728b0b4c70SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 17370034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 17470034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 17570034214SMatthew G. Knepley PetscInt cellPair[2]; 17670034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 17770034214SMatthew G. Knepley PetscInt meetSize = 0; 17870034214SMatthew G. Knepley const PetscInt *meet = NULL; 17970034214SMatthew G. Knepley 18070034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 18170034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 18270034214SMatthew G. Knepley if (!found) { 18370034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 18470034214SMatthew G. Knepley if (meetSize) { 18570034214SMatthew G. Knepley PetscInt f; 18670034214SMatthew G. Knepley 18770034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 18870034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 18970034214SMatthew G. Knepley found = PETSC_TRUE; 19070034214SMatthew G. Knepley break; 19170034214SMatthew G. Knepley } 19270034214SMatthew G. Knepley } 19370034214SMatthew G. Knepley } 19470034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 19570034214SMatthew G. Knepley } 19670034214SMatthew G. Knepley if (found) { 19770034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 19870034214SMatthew G. Knepley ++cellOffset; 19970034214SMatthew G. Knepley } 20070034214SMatthew G. Knepley } 20170034214SMatthew G. Knepley } 20270034214SMatthew G. Knepley } 20370034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 20470034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 20570034214SMatthew G. Knepley if (offsets) *offsets = off; 20670034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 20770034214SMatthew G. Knepley PetscFunctionReturn(0); 20870034214SMatthew G. Knepley } 20970034214SMatthew G. Knepley 210*77623264SMatthew G. Knepley #undef __FUNCT__ 211*77623264SMatthew G. Knepley #define __FUNCT__ "DMPlexEnlargePartition" 212*77623264SMatthew G. Knepley /* Expand the partition by BFS on the adjacency graph */ 213*77623264SMatthew G. Knepley PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection partSection, IS *partition) 214*77623264SMatthew G. Knepley { 215*77623264SMatthew G. Knepley PetscHashI h; 216*77623264SMatthew G. Knepley const PetscInt *points; 217*77623264SMatthew G. Knepley PetscInt **tmpPoints, *newPoints, totPoints = 0; 218*77623264SMatthew G. Knepley PetscInt pStart, pEnd, part, q; 219*77623264SMatthew G. Knepley PetscBool useCone; 220*77623264SMatthew G. Knepley PetscErrorCode ierr; 221*77623264SMatthew G. Knepley 222*77623264SMatthew G. Knepley PetscFunctionBegin; 223*77623264SMatthew G. Knepley PetscHashICreate(h); 224*77623264SMatthew G. Knepley ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 225*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, pStart, pEnd);CHKERRQ(ierr); 226*77623264SMatthew G. Knepley ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 227*77623264SMatthew G. Knepley ierr = PetscMalloc1((pEnd - pStart), &tmpPoints);CHKERRQ(ierr); 228*77623264SMatthew G. Knepley ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 229*77623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 230*77623264SMatthew G. Knepley for (part = pStart; part < pEnd; ++part) { 231*77623264SMatthew G. Knepley PetscInt *adj = NULL; 232*77623264SMatthew G. Knepley PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 233*77623264SMatthew G. Knepley 234*77623264SMatthew G. Knepley PetscHashIClear(h); 235*77623264SMatthew G. Knepley ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 236*77623264SMatthew G. Knepley ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 237*77623264SMatthew G. Knepley /* Add all existing points to h */ 238*77623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 239*77623264SMatthew G. Knepley const PetscInt point = points[off+p]; 240*77623264SMatthew G. Knepley PetscHashIAdd(h, point, 1); 241*77623264SMatthew G. Knepley } 242*77623264SMatthew G. Knepley PetscHashISize(h, nP); 243*77623264SMatthew G. Knepley if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 244*77623264SMatthew G. Knepley /* Add all points in next BFS level */ 245*77623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 246*77623264SMatthew G. Knepley const PetscInt point = points[off+p]; 247*77623264SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 248*77623264SMatthew G. Knepley 249*77623264SMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, point, &adjSize, &adj);CHKERRQ(ierr); 250*77623264SMatthew G. Knepley for (a = 0; a < adjSize; ++a) PetscHashIAdd(h, adj[a], 1); 251*77623264SMatthew G. Knepley } 252*77623264SMatthew G. Knepley PetscHashISize(h, numNewPoints); 253*77623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, part, numNewPoints);CHKERRQ(ierr); 254*77623264SMatthew G. Knepley ierr = PetscMalloc1(numNewPoints, &tmpPoints[part]);CHKERRQ(ierr); 255*77623264SMatthew G. Knepley ierr = PetscHashIGetKeys(h, &n, tmpPoints[part]);CHKERRQ(ierr); 256*77623264SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 257*77623264SMatthew G. Knepley totPoints += numNewPoints; 258*77623264SMatthew G. Knepley } 259*77623264SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 260*77623264SMatthew G. Knepley ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 261*77623264SMatthew G. Knepley PetscHashIDestroy(h); 262*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 263*77623264SMatthew G. Knepley ierr = PetscMalloc1(totPoints, &newPoints);CHKERRQ(ierr); 264*77623264SMatthew G. Knepley for (part = pStart, q = 0; part < pEnd; ++part) { 265*77623264SMatthew G. Knepley PetscInt numPoints, p; 266*77623264SMatthew G. Knepley 267*77623264SMatthew G. Knepley ierr = PetscSectionGetDof(partSection, part, &numPoints);CHKERRQ(ierr); 268*77623264SMatthew G. Knepley for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 269*77623264SMatthew G. Knepley ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 270*77623264SMatthew G. Knepley } 271*77623264SMatthew G. Knepley ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 272*77623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 273*77623264SMatthew G. Knepley PetscFunctionReturn(0); 274*77623264SMatthew G. Knepley } 275*77623264SMatthew G. Knepley 276*77623264SMatthew G. Knepley #undef __FUNCT__ 277*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerRegister" 278*77623264SMatthew G. Knepley /*@C 279*77623264SMatthew G. Knepley PetscPartitionerRegister - Adds a new PetscPartitioner implementation 280*77623264SMatthew G. Knepley 281*77623264SMatthew G. Knepley Not Collective 282*77623264SMatthew G. Knepley 283*77623264SMatthew G. Knepley Input Parameters: 284*77623264SMatthew G. Knepley + name - The name of a new user-defined creation routine 285*77623264SMatthew G. Knepley - create_func - The creation routine itself 286*77623264SMatthew G. Knepley 287*77623264SMatthew G. Knepley Notes: 288*77623264SMatthew G. Knepley PetscPartitionerRegister() may be called multiple times to add several user-defined PetscPartitioners 289*77623264SMatthew G. Knepley 290*77623264SMatthew G. Knepley Sample usage: 291*77623264SMatthew G. Knepley .vb 292*77623264SMatthew G. Knepley PetscPartitionerRegister("my_part", MyPetscPartitionerCreate); 293*77623264SMatthew G. Knepley .ve 294*77623264SMatthew G. Knepley 295*77623264SMatthew G. Knepley Then, your PetscPartitioner type can be chosen with the procedural interface via 296*77623264SMatthew G. Knepley .vb 297*77623264SMatthew G. Knepley PetscPartitionerCreate(MPI_Comm, PetscPartitioner *); 298*77623264SMatthew G. Knepley PetscPartitionerSetType(PetscPartitioner, "my_part"); 299*77623264SMatthew G. Knepley .ve 300*77623264SMatthew G. Knepley or at runtime via the option 301*77623264SMatthew G. Knepley .vb 302*77623264SMatthew G. Knepley -petscpartitioner_type my_part 303*77623264SMatthew G. Knepley .ve 304*77623264SMatthew G. Knepley 305*77623264SMatthew G. Knepley Level: advanced 306*77623264SMatthew G. Knepley 307*77623264SMatthew G. Knepley .keywords: PetscPartitioner, register 308*77623264SMatthew G. Knepley .seealso: PetscPartitionerRegisterAll(), PetscPartitionerRegisterDestroy() 309*77623264SMatthew G. Knepley 310*77623264SMatthew G. Knepley @*/ 311*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerRegister(const char sname[], PetscErrorCode (*function)(PetscPartitioner)) 312*77623264SMatthew G. Knepley { 313*77623264SMatthew G. Knepley PetscErrorCode ierr; 314*77623264SMatthew G. Knepley 315*77623264SMatthew G. Knepley PetscFunctionBegin; 316*77623264SMatthew G. Knepley ierr = PetscFunctionListAdd(&PetscPartitionerList, sname, function);CHKERRQ(ierr); 317*77623264SMatthew G. Knepley PetscFunctionReturn(0); 318*77623264SMatthew G. Knepley } 319*77623264SMatthew G. Knepley 320*77623264SMatthew G. Knepley #undef __FUNCT__ 321*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetType" 322*77623264SMatthew G. Knepley /*@C 323*77623264SMatthew G. Knepley PetscPartitionerSetType - Builds a particular PetscPartitioner 324*77623264SMatthew G. Knepley 325*77623264SMatthew G. Knepley Collective on PetscPartitioner 326*77623264SMatthew G. Knepley 327*77623264SMatthew G. Knepley Input Parameters: 328*77623264SMatthew G. Knepley + part - The PetscPartitioner object 329*77623264SMatthew G. Knepley - name - The kind of partitioner 330*77623264SMatthew G. Knepley 331*77623264SMatthew G. Knepley Options Database Key: 332*77623264SMatthew G. Knepley . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types 333*77623264SMatthew G. Knepley 334*77623264SMatthew G. Knepley Level: intermediate 335*77623264SMatthew G. Knepley 336*77623264SMatthew G. Knepley .keywords: PetscPartitioner, set, type 337*77623264SMatthew G. Knepley .seealso: PetscPartitionerGetType(), PetscPartitionerCreate() 338*77623264SMatthew G. Knepley @*/ 339*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name) 340*77623264SMatthew G. Knepley { 341*77623264SMatthew G. Knepley PetscErrorCode (*r)(PetscPartitioner); 342*77623264SMatthew G. Knepley PetscBool match; 343*77623264SMatthew G. Knepley PetscErrorCode ierr; 344*77623264SMatthew G. Knepley 345*77623264SMatthew G. Knepley PetscFunctionBegin; 346*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 347*77623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) part, name, &match);CHKERRQ(ierr); 348*77623264SMatthew G. Knepley if (match) PetscFunctionReturn(0); 349*77623264SMatthew G. Knepley 350*77623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 351*77623264SMatthew G. Knepley ierr = PetscFunctionListFind(PetscPartitionerList, name, &r);CHKERRQ(ierr); 352*77623264SMatthew G. Knepley if (!r) SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name); 353*77623264SMatthew G. Knepley 354*77623264SMatthew G. Knepley if (part->ops->destroy) { 355*77623264SMatthew G. Knepley ierr = (*part->ops->destroy)(part);CHKERRQ(ierr); 356*77623264SMatthew G. Knepley part->ops->destroy = NULL; 357*77623264SMatthew G. Knepley } 358*77623264SMatthew G. Knepley ierr = (*r)(part);CHKERRQ(ierr); 359*77623264SMatthew G. Knepley ierr = PetscObjectChangeTypeName((PetscObject) part, name);CHKERRQ(ierr); 360*77623264SMatthew G. Knepley PetscFunctionReturn(0); 361*77623264SMatthew G. Knepley } 362*77623264SMatthew G. Knepley 363*77623264SMatthew G. Knepley #undef __FUNCT__ 364*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerGetType" 365*77623264SMatthew G. Knepley /*@C 366*77623264SMatthew G. Knepley PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object. 367*77623264SMatthew G. Knepley 368*77623264SMatthew G. Knepley Not Collective 369*77623264SMatthew G. Knepley 370*77623264SMatthew G. Knepley Input Parameter: 371*77623264SMatthew G. Knepley . part - The PetscPartitioner 372*77623264SMatthew G. Knepley 373*77623264SMatthew G. Knepley Output Parameter: 374*77623264SMatthew G. Knepley . name - The PetscPartitioner type name 375*77623264SMatthew G. Knepley 376*77623264SMatthew G. Knepley Level: intermediate 377*77623264SMatthew G. Knepley 378*77623264SMatthew G. Knepley .keywords: PetscPartitioner, get, type, name 379*77623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PetscPartitionerCreate() 380*77623264SMatthew G. Knepley @*/ 381*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name) 382*77623264SMatthew G. Knepley { 383*77623264SMatthew G. Knepley PetscErrorCode ierr; 384*77623264SMatthew G. Knepley 385*77623264SMatthew G. Knepley PetscFunctionBegin; 386*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 387*77623264SMatthew G. Knepley PetscValidPointer(name, 2); 388*77623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 389*77623264SMatthew G. Knepley *name = ((PetscObject) part)->type_name; 390*77623264SMatthew G. Knepley PetscFunctionReturn(0); 391*77623264SMatthew G. Knepley } 392*77623264SMatthew G. Knepley 393*77623264SMatthew G. Knepley #undef __FUNCT__ 394*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView" 395*77623264SMatthew G. Knepley /*@C 396*77623264SMatthew G. Knepley PetscPartitionerView - Views a PetscPartitioner 397*77623264SMatthew G. Knepley 398*77623264SMatthew G. Knepley Collective on PetscPartitioner 399*77623264SMatthew G. Knepley 400*77623264SMatthew G. Knepley Input Parameter: 401*77623264SMatthew G. Knepley + part - the PetscPartitioner object to view 402*77623264SMatthew G. Knepley - v - the viewer 403*77623264SMatthew G. Knepley 404*77623264SMatthew G. Knepley Level: developer 405*77623264SMatthew G. Knepley 406*77623264SMatthew G. Knepley .seealso: PetscPartitionerDestroy() 407*77623264SMatthew G. Knepley @*/ 408*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v) 409*77623264SMatthew G. Knepley { 410*77623264SMatthew G. Knepley PetscErrorCode ierr; 411*77623264SMatthew G. Knepley 412*77623264SMatthew G. Knepley PetscFunctionBegin; 413*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 414*77623264SMatthew G. Knepley if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);CHKERRQ(ierr);} 415*77623264SMatthew G. Knepley if (part->ops->view) {ierr = (*part->ops->view)(part, v);CHKERRQ(ierr);} 416*77623264SMatthew G. Knepley PetscFunctionReturn(0); 417*77623264SMatthew G. Knepley } 418*77623264SMatthew G. Knepley 419*77623264SMatthew G. Knepley #undef __FUNCT__ 420*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerViewFromOptions" 421*77623264SMatthew G. Knepley /* 422*77623264SMatthew G. Knepley PetscPartitionerViewFromOptions - Processes command line options to determine if/how a PetscPartitioner is to be viewed. 423*77623264SMatthew G. Knepley 424*77623264SMatthew G. Knepley Collective on PetscPartitioner 425*77623264SMatthew G. Knepley 426*77623264SMatthew G. Knepley Input Parameters: 427*77623264SMatthew G. Knepley + part - the PetscPartitioner 428*77623264SMatthew G. Knepley . prefix - prefix to use for viewing, or NULL 429*77623264SMatthew G. Knepley - optionname - option to activate viewing 430*77623264SMatthew G. Knepley 431*77623264SMatthew G. Knepley Level: intermediate 432*77623264SMatthew G. Knepley 433*77623264SMatthew G. Knepley .keywords: PetscPartitioner, view, options, database 434*77623264SMatthew G. Knepley .seealso: VecViewFromOptions(), MatViewFromOptions() 435*77623264SMatthew G. Knepley */ 436*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner part, const char prefix[], const char optionname[]) 437*77623264SMatthew G. Knepley { 438*77623264SMatthew G. Knepley PetscViewer viewer; 439*77623264SMatthew G. Knepley PetscViewerFormat format; 440*77623264SMatthew G. Knepley PetscBool flg; 441*77623264SMatthew G. Knepley PetscErrorCode ierr; 442*77623264SMatthew G. Knepley 443*77623264SMatthew G. Knepley PetscFunctionBegin; 444*77623264SMatthew G. Knepley if (prefix) {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 445*77623264SMatthew G. Knepley else {ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) part), ((PetscObject) part)->prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);} 446*77623264SMatthew G. Knepley if (flg) { 447*77623264SMatthew G. Knepley ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr); 448*77623264SMatthew G. Knepley ierr = PetscPartitionerView(part, viewer);CHKERRQ(ierr); 449*77623264SMatthew G. Knepley ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 450*77623264SMatthew G. Knepley ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 451*77623264SMatthew G. Knepley } 452*77623264SMatthew G. Knepley PetscFunctionReturn(0); 453*77623264SMatthew G. Knepley } 454*77623264SMatthew G. Knepley #undef __FUNCT__ 455*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetTypeFromOptions_Internal" 456*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetTypeFromOptions_Internal(PetscPartitioner part) 457*77623264SMatthew G. Knepley { 458*77623264SMatthew G. Knepley const char *defaultType; 459*77623264SMatthew G. Knepley char name[256]; 460*77623264SMatthew G. Knepley PetscBool flg; 461*77623264SMatthew G. Knepley PetscErrorCode ierr; 462*77623264SMatthew G. Knepley 463*77623264SMatthew G. Knepley PetscFunctionBegin; 464*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 465*77623264SMatthew G. Knepley if (!((PetscObject) part)->type_name) defaultType = PETSCPARTITIONERCHACO; 466*77623264SMatthew G. Knepley else defaultType = ((PetscObject) part)->type_name; 467*77623264SMatthew G. Knepley if (!PetscPartitionerRegisterAllCalled) {ierr = PetscPartitionerRegisterAll();CHKERRQ(ierr);} 468*77623264SMatthew G. Knepley 469*77623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 470*77623264SMatthew G. Knepley ierr = PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, defaultType, name, 256, &flg);CHKERRQ(ierr); 471*77623264SMatthew G. Knepley if (flg) { 472*77623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, name);CHKERRQ(ierr); 473*77623264SMatthew G. Knepley } else if (!((PetscObject) part)->type_name) { 474*77623264SMatthew G. Knepley ierr = PetscPartitionerSetType(part, defaultType);CHKERRQ(ierr); 475*77623264SMatthew G. Knepley } 476*77623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 477*77623264SMatthew G. Knepley PetscFunctionReturn(0); 478*77623264SMatthew G. Knepley } 479*77623264SMatthew G. Knepley 480*77623264SMatthew G. Knepley #undef __FUNCT__ 481*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetFromOptions" 482*77623264SMatthew G. Knepley /*@ 483*77623264SMatthew G. Knepley PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database 484*77623264SMatthew G. Knepley 485*77623264SMatthew G. Knepley Collective on PetscPartitioner 486*77623264SMatthew G. Knepley 487*77623264SMatthew G. Knepley Input Parameter: 488*77623264SMatthew G. Knepley . part - the PetscPartitioner object to set options for 489*77623264SMatthew G. Knepley 490*77623264SMatthew G. Knepley Level: developer 491*77623264SMatthew G. Knepley 492*77623264SMatthew G. Knepley .seealso: PetscPartitionerView() 493*77623264SMatthew G. Knepley @*/ 494*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part) 495*77623264SMatthew G. Knepley { 496*77623264SMatthew G. Knepley PetscErrorCode ierr; 497*77623264SMatthew G. Knepley 498*77623264SMatthew G. Knepley PetscFunctionBegin; 499*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 500*77623264SMatthew G. Knepley ierr = PetscPartitionerSetTypeFromOptions_Internal(part);CHKERRQ(ierr); 501*77623264SMatthew G. Knepley 502*77623264SMatthew G. Knepley ierr = PetscObjectOptionsBegin((PetscObject) part);CHKERRQ(ierr); 503*77623264SMatthew G. Knepley if (part->ops->setfromoptions) {ierr = (*part->ops->setfromoptions)(part);CHKERRQ(ierr);} 504*77623264SMatthew G. Knepley /* process any options handlers added with PetscObjectAddOptionsHandler() */ 505*77623264SMatthew G. Knepley ierr = PetscObjectProcessOptionsHandlers((PetscObject) part);CHKERRQ(ierr); 506*77623264SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 507*77623264SMatthew G. Knepley ierr = PetscPartitionerViewFromOptions(part, NULL, "-petscpartitioner_view");CHKERRQ(ierr); 508*77623264SMatthew G. Knepley PetscFunctionReturn(0); 509*77623264SMatthew G. Knepley } 510*77623264SMatthew G. Knepley 511*77623264SMatthew G. Knepley #undef __FUNCT__ 512*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerSetUp" 513*77623264SMatthew G. Knepley /*@C 514*77623264SMatthew G. Knepley PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 515*77623264SMatthew G. Knepley 516*77623264SMatthew G. Knepley Collective on PetscPartitioner 517*77623264SMatthew G. Knepley 518*77623264SMatthew G. Knepley Input Parameter: 519*77623264SMatthew G. Knepley . part - the PetscPartitioner object to setup 520*77623264SMatthew G. Knepley 521*77623264SMatthew G. Knepley Level: developer 522*77623264SMatthew G. Knepley 523*77623264SMatthew G. Knepley .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 524*77623264SMatthew G. Knepley @*/ 525*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 526*77623264SMatthew G. Knepley { 527*77623264SMatthew G. Knepley PetscErrorCode ierr; 528*77623264SMatthew G. Knepley 529*77623264SMatthew G. Knepley PetscFunctionBegin; 530*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 531*77623264SMatthew G. Knepley if (part->ops->setup) {ierr = (*part->ops->setup)(part);CHKERRQ(ierr);} 532*77623264SMatthew G. Knepley PetscFunctionReturn(0); 533*77623264SMatthew G. Knepley } 534*77623264SMatthew G. Knepley 535*77623264SMatthew G. Knepley #undef __FUNCT__ 536*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy" 537*77623264SMatthew G. Knepley /*@ 538*77623264SMatthew G. Knepley PetscPartitionerDestroy - Destroys a PetscPartitioner object 539*77623264SMatthew G. Knepley 540*77623264SMatthew G. Knepley Collective on PetscPartitioner 541*77623264SMatthew G. Knepley 542*77623264SMatthew G. Knepley Input Parameter: 543*77623264SMatthew G. Knepley . part - the PetscPartitioner object to destroy 544*77623264SMatthew G. Knepley 545*77623264SMatthew G. Knepley Level: developer 546*77623264SMatthew G. Knepley 547*77623264SMatthew G. Knepley .seealso: PetscPartitionerView() 548*77623264SMatthew G. Knepley @*/ 549*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 550*77623264SMatthew G. Knepley { 551*77623264SMatthew G. Knepley PetscErrorCode ierr; 552*77623264SMatthew G. Knepley 553*77623264SMatthew G. Knepley PetscFunctionBegin; 554*77623264SMatthew G. Knepley if (!*part) PetscFunctionReturn(0); 555*77623264SMatthew G. Knepley PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 556*77623264SMatthew G. Knepley 557*77623264SMatthew G. Knepley if (--((PetscObject)(*part))->refct > 0) {*part = 0; PetscFunctionReturn(0);} 558*77623264SMatthew G. Knepley ((PetscObject) (*part))->refct = 0; 559*77623264SMatthew G. Knepley 560*77623264SMatthew G. Knepley if ((*part)->ops->destroy) {ierr = (*(*part)->ops->destroy)(*part);CHKERRQ(ierr);} 561*77623264SMatthew G. Knepley ierr = PetscHeaderDestroy(part);CHKERRQ(ierr); 562*77623264SMatthew G. Knepley PetscFunctionReturn(0); 563*77623264SMatthew G. Knepley } 564*77623264SMatthew G. Knepley 565*77623264SMatthew G. Knepley #undef __FUNCT__ 566*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate" 567*77623264SMatthew G. Knepley /*@ 568*77623264SMatthew G. Knepley PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 569*77623264SMatthew G. Knepley 570*77623264SMatthew G. Knepley Collective on MPI_Comm 571*77623264SMatthew G. Knepley 572*77623264SMatthew G. Knepley Input Parameter: 573*77623264SMatthew G. Knepley . comm - The communicator for the PetscPartitioner object 574*77623264SMatthew G. Knepley 575*77623264SMatthew G. Knepley Output Parameter: 576*77623264SMatthew G. Knepley . part - The PetscPartitioner object 577*77623264SMatthew G. Knepley 578*77623264SMatthew G. Knepley Level: beginner 579*77623264SMatthew G. Knepley 580*77623264SMatthew G. Knepley .seealso: PetscPartitionerSetType(), PETSCPARTITIONERCHACO, PETSCPARTITIONERPARMETIS, PETSCPARTITIONERSHELL 581*77623264SMatthew G. Knepley @*/ 582*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 583*77623264SMatthew G. Knepley { 584*77623264SMatthew G. Knepley PetscPartitioner p; 585*77623264SMatthew G. Knepley PetscErrorCode ierr; 586*77623264SMatthew G. Knepley 587*77623264SMatthew G. Knepley PetscFunctionBegin; 588*77623264SMatthew G. Knepley PetscValidPointer(part, 2); 589*77623264SMatthew G. Knepley *part = NULL; 590*77623264SMatthew G. Knepley ierr = PetscFVInitializePackage();CHKERRQ(ierr); 591*77623264SMatthew G. Knepley 592*77623264SMatthew G. Knepley ierr = PetscHeaderCreate(p, _p_PetscPartitioner, struct _PetscPartitionerOps, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);CHKERRQ(ierr); 593*77623264SMatthew G. Knepley ierr = PetscMemzero(p->ops, sizeof(struct _PetscPartitionerOps));CHKERRQ(ierr); 594*77623264SMatthew G. Knepley 595*77623264SMatthew G. Knepley *part = p; 596*77623264SMatthew G. Knepley PetscFunctionReturn(0); 597*77623264SMatthew G. Knepley } 598*77623264SMatthew G. Knepley 599*77623264SMatthew G. Knepley #undef __FUNCT__ 600*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition" 601*77623264SMatthew G. Knepley /*@ 602*77623264SMatthew G. Knepley PetscPartitionerPartition - Create a non-overlapping partition of the cells in the mesh 603*77623264SMatthew G. Knepley 604*77623264SMatthew G. Knepley Collective on DM 605*77623264SMatthew G. Knepley 606*77623264SMatthew G. Knepley Input Parameters: 607*77623264SMatthew G. Knepley + part - The PetscPartitioner 608*77623264SMatthew G. Knepley . dm - The mesh DM 609*77623264SMatthew G. Knepley - enlarge - Expand each partition with neighbors 610*77623264SMatthew G. Knepley 611*77623264SMatthew G. Knepley Output Parameters: 612*77623264SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 613*77623264SMatthew G. Knepley . partition - The list of points by partition 614*77623264SMatthew G. Knepley . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 615*77623264SMatthew G. Knepley - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 616*77623264SMatthew G. Knepley 617*77623264SMatthew G. Knepley Note: Instead of cells, points at a given height can be partitioned by calling PetscPartitionerSetPointHeight() 618*77623264SMatthew G. Knepley 619*77623264SMatthew G. Knepley Level: developer 620*77623264SMatthew G. Knepley 621*77623264SMatthew G. Knepley .seealso DMPlexDistribute(), PetscPartitionerSetPointHeight(), PetscPartitionerCreate() 622*77623264SMatthew G. Knepley */ 623*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, DM dm, PetscBool enlarge, PetscSection partSection, IS *partition, PetscSection origPartSection, IS *origPartition) 624*77623264SMatthew G. Knepley { 625*77623264SMatthew G. Knepley PetscMPIInt size; 626*77623264SMatthew G. Knepley PetscErrorCode ierr; 627*77623264SMatthew G. Knepley 628*77623264SMatthew G. Knepley PetscFunctionBegin; 629*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 630*77623264SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 631*77623264SMatthew G. Knepley PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4); 632*77623264SMatthew G. Knepley PetscValidPointer(partition, 5); 633*77623264SMatthew G. Knepley if (enlarge) {PetscValidHeaderSpecific(origPartSection, PETSC_SECTION_CLASSID, 6);} 634*77623264SMatthew G. Knepley if (enlarge) {PetscValidPointer(origPartition, 7);} 635*77623264SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRQ(ierr); 636*77623264SMatthew G. Knepley *origPartition = NULL; 637*77623264SMatthew G. Knepley if (size == 1) { 638*77623264SMatthew G. Knepley PetscInt *points; 639*77623264SMatthew G. Knepley PetscInt cStart, cEnd, c; 640*77623264SMatthew G. Knepley 641*77623264SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr); 642*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr); 643*77623264SMatthew G. Knepley ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr); 644*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 645*77623264SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr); 646*77623264SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 647*77623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 648*77623264SMatthew G. Knepley PetscFunctionReturn(0); 649*77623264SMatthew G. Knepley } 650*77623264SMatthew G. Knepley if (part->height == 0) { 651*77623264SMatthew G. Knepley PetscInt numVertices; 652*77623264SMatthew G. Knepley PetscInt *start = NULL; 653*77623264SMatthew G. Knepley PetscInt *adjacency = NULL; 654*77623264SMatthew G. Knepley 655*77623264SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 656*77623264SMatthew G. Knepley if (!part->ops->partition) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONGSTATE, "PetscPartitioner has no type"); 657*77623264SMatthew G. Knepley ierr = (*part->ops->partition)(part, dm, size, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 658*77623264SMatthew G. Knepley if (enlarge) { 659*77623264SMatthew G. Knepley origPartSection = partSection; 660*77623264SMatthew G. Knepley *origPartition = *partition; 661*77623264SMatthew G. Knepley 662*77623264SMatthew G. Knepley ierr = DMPlexEnlargePartition(dm, start, adjacency, origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 663*77623264SMatthew G. Knepley } 664*77623264SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 665*77623264SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 666*77623264SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height); 667*77623264SMatthew G. Knepley PetscFunctionReturn(0); 668*77623264SMatthew G. Knepley } 669*77623264SMatthew G. Knepley 670*77623264SMatthew G. Knepley #undef __FUNCT__ 671*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Shell" 672*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 673*77623264SMatthew G. Knepley { 674*77623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 675*77623264SMatthew G. Knepley PetscErrorCode ierr; 676*77623264SMatthew G. Knepley 677*77623264SMatthew G. Knepley PetscFunctionBegin; 678*77623264SMatthew G. Knepley ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 679*77623264SMatthew G. Knepley ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 680*77623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 681*77623264SMatthew G. Knepley PetscFunctionReturn(0); 682*77623264SMatthew G. Knepley } 683*77623264SMatthew G. Knepley 684*77623264SMatthew G. Knepley #undef __FUNCT__ 685*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell_Ascii" 686*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell_Ascii(PetscPartitioner part, PetscViewer viewer) 687*77623264SMatthew G. Knepley { 688*77623264SMatthew G. Knepley PetscViewerFormat format; 689*77623264SMatthew G. Knepley PetscErrorCode ierr; 690*77623264SMatthew G. Knepley 691*77623264SMatthew G. Knepley PetscFunctionBegin; 692*77623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 693*77623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Shell Graph Partitioner:\n");CHKERRQ(ierr); 694*77623264SMatthew G. Knepley PetscFunctionReturn(0); 695*77623264SMatthew G. Knepley } 696*77623264SMatthew G. Knepley 697*77623264SMatthew G. Knepley #undef __FUNCT__ 698*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Shell" 699*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 700*77623264SMatthew G. Knepley { 701*77623264SMatthew G. Knepley PetscBool iascii; 702*77623264SMatthew G. Knepley PetscErrorCode ierr; 703*77623264SMatthew G. Knepley 704*77623264SMatthew G. Knepley PetscFunctionBegin; 705*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 706*77623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 707*77623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 708*77623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Shell_Ascii(part, viewer);CHKERRQ(ierr);} 709*77623264SMatthew G. Knepley PetscFunctionReturn(0); 710*77623264SMatthew G. Knepley } 711*77623264SMatthew G. Knepley 712*77623264SMatthew G. Knepley #undef __FUNCT__ 713*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Shell" 714*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 715*77623264SMatthew G. Knepley { 716*77623264SMatthew G. Knepley PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 717*77623264SMatthew G. Knepley PetscInt np; 718*77623264SMatthew G. Knepley PetscErrorCode ierr; 719*77623264SMatthew G. Knepley 720*77623264SMatthew G. Knepley PetscFunctionBegin; 721*77623264SMatthew G. Knepley if (!numVertices) { 722*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 723*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 724*77623264SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 725*77623264SMatthew G. Knepley PetscFunctionReturn(0); 726*77623264SMatthew G. Knepley } 727*77623264SMatthew G. Knepley ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 728*77623264SMatthew G. Knepley if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 729*77623264SMatthew G. Knepley ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 730*77623264SMatthew G. Knepley if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 731*77623264SMatthew G. Knepley partSection = p->section; 732*77623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->section);CHKERRQ(ierr); 733*77623264SMatthew G. Knepley *partition = p->partition; 734*77623264SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 735*77623264SMatthew G. Knepley PetscFunctionReturn(0); 736*77623264SMatthew G. Knepley } 737*77623264SMatthew G. Knepley 738*77623264SMatthew G. Knepley #undef __FUNCT__ 739*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Shell" 740*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 741*77623264SMatthew G. Knepley { 742*77623264SMatthew G. Knepley PetscFunctionBegin; 743*77623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Shell; 744*77623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Shell; 745*77623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Shell; 746*77623264SMatthew G. Knepley PetscFunctionReturn(0); 747*77623264SMatthew G. Knepley } 748*77623264SMatthew G. Knepley 749*77623264SMatthew G. Knepley /*MC 750*77623264SMatthew G. Knepley PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 751*77623264SMatthew G. Knepley 752*77623264SMatthew G. Knepley Level: intermediate 753*77623264SMatthew G. Knepley 754*77623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 755*77623264SMatthew G. Knepley M*/ 756*77623264SMatthew G. Knepley 757*77623264SMatthew G. Knepley #undef __FUNCT__ 758*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Shell" 759*77623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 760*77623264SMatthew G. Knepley { 761*77623264SMatthew G. Knepley PetscPartitioner_Shell *p; 762*77623264SMatthew G. Knepley PetscErrorCode ierr; 763*77623264SMatthew G. Knepley 764*77623264SMatthew G. Knepley PetscFunctionBegin; 765*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 766*77623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 767*77623264SMatthew G. Knepley part->data = p; 768*77623264SMatthew G. Knepley 769*77623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 770*77623264SMatthew G. Knepley PetscFunctionReturn(0); 771*77623264SMatthew G. Knepley } 772*77623264SMatthew G. Knepley 773*77623264SMatthew G. Knepley #undef __FUNCT__ 774*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_Chaco" 775*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_Chaco(PetscPartitioner part) 776*77623264SMatthew G. Knepley { 777*77623264SMatthew G. Knepley PetscPartitioner_Chaco *p = (PetscPartitioner_Chaco *) part->data; 778*77623264SMatthew G. Knepley PetscErrorCode ierr; 779*77623264SMatthew G. Knepley 780*77623264SMatthew G. Knepley PetscFunctionBegin; 781*77623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 782*77623264SMatthew G. Knepley PetscFunctionReturn(0); 783*77623264SMatthew G. Knepley } 784*77623264SMatthew G. Knepley 785*77623264SMatthew G. Knepley #undef __FUNCT__ 786*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco_Ascii" 787*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco_Ascii(PetscPartitioner part, PetscViewer viewer) 788*77623264SMatthew G. Knepley { 789*77623264SMatthew G. Knepley PetscViewerFormat format; 790*77623264SMatthew G. Knepley PetscErrorCode ierr; 791*77623264SMatthew G. Knepley 792*77623264SMatthew G. Knepley PetscFunctionBegin; 793*77623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 794*77623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Chaco Graph Partitioner:\n");CHKERRQ(ierr); 795*77623264SMatthew G. Knepley PetscFunctionReturn(0); 796*77623264SMatthew G. Knepley } 797*77623264SMatthew G. Knepley 798*77623264SMatthew G. Knepley #undef __FUNCT__ 799*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_Chaco" 800*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_Chaco(PetscPartitioner part, PetscViewer viewer) 801*77623264SMatthew G. Knepley { 802*77623264SMatthew G. Knepley PetscBool iascii; 803*77623264SMatthew G. Knepley PetscErrorCode ierr; 804*77623264SMatthew G. Knepley 805*77623264SMatthew G. Knepley PetscFunctionBegin; 806*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 807*77623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 808*77623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 809*77623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_Chaco_Ascii(part, viewer);CHKERRQ(ierr);} 810*77623264SMatthew G. Knepley PetscFunctionReturn(0); 811*77623264SMatthew G. Knepley } 812*77623264SMatthew G. Knepley 81370034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 81470034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 81570034214SMatthew G. Knepley #include <unistd.h> 81670034214SMatthew G. Knepley #endif 81770034214SMatthew G. Knepley /* Chaco does not have an include file */ 81870034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 81970034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 82070034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 82170034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 82270034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 82370034214SMatthew G. Knepley 82470034214SMatthew G. Knepley extern int FREE_GRAPH; 825*77623264SMatthew G. Knepley #endif 82670034214SMatthew G. Knepley 82770034214SMatthew G. Knepley #undef __FUNCT__ 828*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_Chaco" 829*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_Chaco(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 83070034214SMatthew G. Knepley { 831*77623264SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 83270034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 83370034214SMatthew G. Knepley MPI_Comm comm; 83470034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 83570034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 83670034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 83770034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 83870034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 83970034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 84070034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 84170034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 84270034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 84370034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 84470034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 84570034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 84670034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 84770034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 84870034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 84970034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 85070034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 85170034214SMatthew G. Knepley short int *assignment; /* Output partition */ 85270034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 85370034214SMatthew G. Knepley PetscInt *points; 85470034214SMatthew G. Knepley int i, v, p; 85570034214SMatthew G. Knepley PetscErrorCode ierr; 85670034214SMatthew G. Knepley 85770034214SMatthew G. Knepley PetscFunctionBegin; 85870034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 85970034214SMatthew G. Knepley if (!numVertices) { 860*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 861*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 86270034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 86370034214SMatthew G. Knepley PetscFunctionReturn(0); 86470034214SMatthew G. Knepley } 86570034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 86670034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 86770034214SMatthew G. Knepley 86870034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 86970034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 87070034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 87170034214SMatthew G. Knepley } 872*77623264SMatthew G. Knepley mesh_dims[0] = nparts; 87370034214SMatthew G. Knepley mesh_dims[1] = 1; 87470034214SMatthew G. Knepley mesh_dims[2] = 1; 87570034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 87670034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 87770034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 87870034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 87970034214SMatthew G. Knepley { 88070034214SMatthew G. Knepley int piperet; 88170034214SMatthew G. Knepley piperet = pipe(fd_pipe); 88270034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 88370034214SMatthew G. Knepley fd_stdout = dup(1); 88470034214SMatthew G. Knepley close(1); 88570034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 88670034214SMatthew G. Knepley } 88770034214SMatthew G. Knepley #endif 88870034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 88970034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 89070034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 89170034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 89270034214SMatthew G. Knepley { 89370034214SMatthew G. Knepley char msgLog[10000]; 89470034214SMatthew G. Knepley int count; 89570034214SMatthew G. Knepley 89670034214SMatthew G. Knepley fflush(stdout); 89770034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 89870034214SMatthew G. Knepley if (count < 0) count = 0; 89970034214SMatthew G. Knepley msgLog[count] = 0; 90070034214SMatthew G. Knepley close(1); 90170034214SMatthew G. Knepley dup2(fd_stdout, 1); 90270034214SMatthew G. Knepley close(fd_stdout); 90370034214SMatthew G. Knepley close(fd_pipe[0]); 90470034214SMatthew G. Knepley close(fd_pipe[1]); 90570034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 90670034214SMatthew G. Knepley } 90770034214SMatthew G. Knepley #endif 90870034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 909*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 91070034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 911*77623264SMatthew G. Knepley ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr); 91270034214SMatthew G. Knepley } 913*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 91470034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 915*77623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 91670034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 91770034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 91870034214SMatthew G. Knepley } 91970034214SMatthew G. Knepley } 92070034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 92170034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 92270034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 92370034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 92470034214SMatthew G. Knepley } 92570034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 92670034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 92770034214SMatthew G. Knepley PetscFunctionReturn(0); 928*77623264SMatthew G. Knepley #else 929*77623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 93070034214SMatthew G. Knepley #endif 931*77623264SMatthew G. Knepley } 932*77623264SMatthew G. Knepley 933*77623264SMatthew G. Knepley #undef __FUNCT__ 934*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_Chaco" 935*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_Chaco(PetscPartitioner part) 936*77623264SMatthew G. Knepley { 937*77623264SMatthew G. Knepley PetscFunctionBegin; 938*77623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_Chaco; 939*77623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_Chaco; 940*77623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_Chaco; 941*77623264SMatthew G. Knepley PetscFunctionReturn(0); 942*77623264SMatthew G. Knepley } 943*77623264SMatthew G. Knepley 944*77623264SMatthew G. Knepley /*MC 945*77623264SMatthew G. Knepley PETSCPARTITIONERCHACO = "chaco" - A PetscPartitioner object using the Chaco library 946*77623264SMatthew G. Knepley 947*77623264SMatthew G. Knepley Level: intermediate 948*77623264SMatthew G. Knepley 949*77623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 950*77623264SMatthew G. Knepley M*/ 951*77623264SMatthew G. Knepley 952*77623264SMatthew G. Knepley #undef __FUNCT__ 953*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_Chaco" 954*77623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Chaco(PetscPartitioner part) 955*77623264SMatthew G. Knepley { 956*77623264SMatthew G. Knepley PetscPartitioner_Chaco *p; 957*77623264SMatthew G. Knepley PetscErrorCode ierr; 958*77623264SMatthew G. Knepley 959*77623264SMatthew G. Knepley PetscFunctionBegin; 960*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 961*77623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 962*77623264SMatthew G. Knepley part->data = p; 963*77623264SMatthew G. Knepley 964*77623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_Chaco(part);CHKERRQ(ierr); 965*77623264SMatthew G. Knepley ierr = PetscCitationsRegister(ChacoPartitionerCitation, &ChacoPartitionercite);CHKERRQ(ierr); 966*77623264SMatthew G. Knepley PetscFunctionReturn(0); 967*77623264SMatthew G. Knepley } 968*77623264SMatthew G. Knepley 969*77623264SMatthew G. Knepley #undef __FUNCT__ 970*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerDestroy_ParMetis" 971*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 972*77623264SMatthew G. Knepley { 973*77623264SMatthew G. Knepley PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 974*77623264SMatthew G. Knepley PetscErrorCode ierr; 975*77623264SMatthew G. Knepley 976*77623264SMatthew G. Knepley PetscFunctionBegin; 977*77623264SMatthew G. Knepley ierr = PetscFree(p);CHKERRQ(ierr); 978*77623264SMatthew G. Knepley PetscFunctionReturn(0); 979*77623264SMatthew G. Knepley } 980*77623264SMatthew G. Knepley 981*77623264SMatthew G. Knepley #undef __FUNCT__ 982*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis_Ascii" 983*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis_Ascii(PetscPartitioner part, PetscViewer viewer) 984*77623264SMatthew G. Knepley { 985*77623264SMatthew G. Knepley PetscViewerFormat format; 986*77623264SMatthew G. Knepley PetscErrorCode ierr; 987*77623264SMatthew G. Knepley 988*77623264SMatthew G. Knepley PetscFunctionBegin; 989*77623264SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 990*77623264SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "ParMetis Graph Partitioner:\n");CHKERRQ(ierr); 991*77623264SMatthew G. Knepley PetscFunctionReturn(0); 992*77623264SMatthew G. Knepley } 993*77623264SMatthew G. Knepley 994*77623264SMatthew G. Knepley #undef __FUNCT__ 995*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerView_ParMetis" 996*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 997*77623264SMatthew G. Knepley { 998*77623264SMatthew G. Knepley PetscBool iascii; 999*77623264SMatthew G. Knepley PetscErrorCode ierr; 1000*77623264SMatthew G. Knepley 1001*77623264SMatthew G. Knepley PetscFunctionBegin; 1002*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1003*77623264SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1004*77623264SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1005*77623264SMatthew G. Knepley if (iascii) {ierr = PetscPartitionerView_ParMetis_Ascii(part, viewer);CHKERRQ(ierr);} 1006*77623264SMatthew G. Knepley PetscFunctionReturn(0); 1007*77623264SMatthew G. Knepley } 100870034214SMatthew G. Knepley 100970034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 101070034214SMatthew G. Knepley #include <parmetis.h> 1011*77623264SMatthew G. Knepley #endif 101270034214SMatthew G. Knepley 101370034214SMatthew G. Knepley #undef __FUNCT__ 1014*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerPartition_ParMetis" 1015*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, DM dm, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection partSection, IS *partition) 101670034214SMatthew G. Knepley { 1017*77623264SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 101870034214SMatthew G. Knepley MPI_Comm comm; 101970034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 102070034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 102170034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 102270034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 102370034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 102470034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 102570034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 102670034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 102770034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 102870034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 102970034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 103070034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 103170034214SMatthew G. Knepley /* Outputs */ 103270034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 103370034214SMatthew G. Knepley PetscInt *assignment, *points; 1034*77623264SMatthew G. Knepley PetscMPIInt rank, p, v, i; 103570034214SMatthew G. Knepley PetscErrorCode ierr; 103670034214SMatthew G. Knepley 103770034214SMatthew G. Knepley PetscFunctionBegin; 1038*77623264SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 103970034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 104070034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 104170034214SMatthew G. Knepley /* Calculate vertex distribution */ 104270034214SMatthew G. Knepley ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 104370034214SMatthew G. Knepley vtxdist[0] = 0; 104470034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 104570034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 104670034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 104770034214SMatthew G. Knepley } 104870034214SMatthew G. Knepley /* Calculate weights */ 104970034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 105070034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 105170034214SMatthew G. Knepley } 105270034214SMatthew G. Knepley ubvec[0] = 1.05; 105370034214SMatthew G. Knepley 105470034214SMatthew G. Knepley if (nparts == 1) { 105570034214SMatthew G. Knepley ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 105670034214SMatthew G. Knepley } else { 105770034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 105870034214SMatthew G. Knepley if (!rank) { 105970034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 106070034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 106170034214SMatthew G. Knepley PetscStackPop; 106270034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 106370034214SMatthew G. Knepley } 106470034214SMatthew G. Knepley } else { 106570034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 106670034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 106770034214SMatthew G. Knepley PetscStackPop; 106870034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 106970034214SMatthew G. Knepley } 107070034214SMatthew G. Knepley } 107170034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 1072*77623264SMatthew G. Knepley ierr = PetscSectionSetChart(partSection, 0, nparts);CHKERRQ(ierr); 1073*77623264SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 1074*77623264SMatthew G. Knepley ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr); 107570034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 1076*77623264SMatthew G. Knepley for (p = 0, i = 0; p < nparts; ++p) { 107770034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 107870034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 107970034214SMatthew G. Knepley } 108070034214SMatthew G. Knepley } 108170034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 108270034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 108370034214SMatthew G. Knepley ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 108470034214SMatthew G. Knepley #else 1085*77623264SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 108670034214SMatthew G. Knepley #endif 1087*77623264SMatthew G. Knepley PetscFunctionReturn(0); 108870034214SMatthew G. Knepley } 108970034214SMatthew G. Knepley 1090*77623264SMatthew G. Knepley #undef __FUNCT__ 1091*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerInitialize_ParMetis" 1092*77623264SMatthew G. Knepley PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 1093*77623264SMatthew G. Knepley { 1094*77623264SMatthew G. Knepley PetscFunctionBegin; 1095*77623264SMatthew G. Knepley part->ops->view = PetscPartitionerView_ParMetis; 1096*77623264SMatthew G. Knepley part->ops->destroy = PetscPartitionerDestroy_ParMetis; 1097*77623264SMatthew G. Knepley part->ops->partition = PetscPartitionerPartition_ParMetis; 1098*77623264SMatthew G. Knepley PetscFunctionReturn(0); 1099*77623264SMatthew G. Knepley } 1100*77623264SMatthew G. Knepley 1101*77623264SMatthew G. Knepley /*MC 1102*77623264SMatthew G. Knepley PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMetis library 1103*77623264SMatthew G. Knepley 1104*77623264SMatthew G. Knepley Level: intermediate 1105*77623264SMatthew G. Knepley 1106*77623264SMatthew G. Knepley .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 1107*77623264SMatthew G. Knepley M*/ 1108*77623264SMatthew G. Knepley 1109*77623264SMatthew G. Knepley #undef __FUNCT__ 1110*77623264SMatthew G. Knepley #define __FUNCT__ "PetscPartitionerCreate_ParMetis" 1111*77623264SMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 1112*77623264SMatthew G. Knepley { 1113*77623264SMatthew G. Knepley PetscPartitioner_ParMetis *p; 1114*77623264SMatthew G. Knepley PetscErrorCode ierr; 1115*77623264SMatthew G. Knepley 1116*77623264SMatthew G. Knepley PetscFunctionBegin; 1117*77623264SMatthew G. Knepley PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1118*77623264SMatthew G. Knepley ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 1119*77623264SMatthew G. Knepley part->data = p; 1120*77623264SMatthew G. Knepley 1121*77623264SMatthew G. Knepley ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 1122*77623264SMatthew G. Knepley ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionercite);CHKERRQ(ierr); 112370034214SMatthew G. Knepley PetscFunctionReturn(0); 112470034214SMatthew G. Knepley } 112570034214SMatthew G. Knepley 112670034214SMatthew G. Knepley #undef __FUNCT__ 11279ffc88e4SToby Isaac #define __FUNCT__ "DMPlexMarkTreeClosure" 11289ffc88e4SToby Isaac static PetscErrorCode DMPlexMarkTreeClosure(DM dm, PetscSegBuffer segpart, PetscBT bt, PetscInt point, PetscInt *partSize) 11299ffc88e4SToby Isaac { 11309ffc88e4SToby Isaac PetscInt parent, closureSize, *closure = NULL, i, pStart, pEnd; 11319ffc88e4SToby Isaac PetscErrorCode ierr; 11329ffc88e4SToby Isaac 11339ffc88e4SToby Isaac PetscFunctionBegin; 11349ffc88e4SToby Isaac ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr); 11359ffc88e4SToby Isaac if (parent == point) PetscFunctionReturn(0); 11369ffc88e4SToby Isaac ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 11379ffc88e4SToby Isaac ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 11389ffc88e4SToby Isaac for (i = 0; i < closureSize; i++) { 11399ffc88e4SToby Isaac PetscInt cpoint = closure[2*i]; 11409ffc88e4SToby Isaac 11419ffc88e4SToby Isaac if (!PetscBTLookupSet(bt,cpoint-pStart)) { 11429ffc88e4SToby Isaac PetscInt *PETSC_RESTRICT pt; 11439ffc88e4SToby Isaac (*partSize)++; 11449ffc88e4SToby Isaac ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 11459ffc88e4SToby Isaac *pt = cpoint; 11469ffc88e4SToby Isaac } 11479ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,partSize);CHKERRQ(ierr); 11489ffc88e4SToby Isaac } 11499ffc88e4SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 11509ffc88e4SToby Isaac PetscFunctionReturn(0); 11519ffc88e4SToby Isaac } 11529ffc88e4SToby Isaac 11539ffc88e4SToby Isaac #undef __FUNCT__ 115470034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreatePartitionClosure" 115570034214SMatthew G. Knepley PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 115670034214SMatthew G. Knepley { 115770034214SMatthew G. Knepley /* const PetscInt height = 0; */ 115870034214SMatthew G. Knepley const PetscInt *partArray; 115970034214SMatthew G. Knepley PetscInt *allPoints, *packPoints; 116070034214SMatthew G. Knepley PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 116170034214SMatthew G. Knepley PetscErrorCode ierr; 116270034214SMatthew G. Knepley PetscBT bt; 116370034214SMatthew G. Knepley PetscSegBuffer segpack,segpart; 116470034214SMatthew G. Knepley 116570034214SMatthew G. Knepley PetscFunctionBegin; 116670034214SMatthew G. Knepley ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 116770034214SMatthew G. Knepley ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 116870034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 116970034214SMatthew G. Knepley ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 117070034214SMatthew G. Knepley ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 117170034214SMatthew G. Knepley ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 117270034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 117370034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 117470034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 117570034214SMatthew G. Knepley PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 117670034214SMatthew G. Knepley 117770034214SMatthew G. Knepley ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 117870034214SMatthew G. Knepley ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 117970034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 118070034214SMatthew G. Knepley PetscInt point = partArray[offset+p], closureSize, c; 118170034214SMatthew G. Knepley PetscInt *closure = NULL; 118270034214SMatthew G. Knepley 118370034214SMatthew G. Knepley /* TODO Include support for height > 0 case */ 118470034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 118570034214SMatthew G. Knepley for (c=0; c<closureSize; c++) { 118670034214SMatthew G. Knepley PetscInt cpoint = closure[c*2]; 118770034214SMatthew G. Knepley if (!PetscBTLookupSet(bt,cpoint-pStart)) { 118870034214SMatthew G. Knepley PetscInt *PETSC_RESTRICT pt; 118970034214SMatthew G. Knepley partSize++; 119070034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 119170034214SMatthew G. Knepley *pt = cpoint; 119270034214SMatthew G. Knepley } 11939ffc88e4SToby Isaac ierr = DMPlexMarkTreeClosure(dm,segpart,bt,cpoint,&partSize);CHKERRQ(ierr); 119470034214SMatthew G. Knepley } 119570034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 119670034214SMatthew G. Knepley } 119770034214SMatthew G. Knepley ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 119870034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 119970034214SMatthew G. Knepley ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 120070034214SMatthew G. Knepley ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 120170034214SMatthew G. Knepley for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 120270034214SMatthew G. Knepley } 120370034214SMatthew G. Knepley ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 120470034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 120570034214SMatthew G. Knepley 120670034214SMatthew G. Knepley ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 120770034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 120870034214SMatthew G. Knepley ierr = PetscMalloc1(newSize, &allPoints);CHKERRQ(ierr); 120970034214SMatthew G. Knepley 121070034214SMatthew G. Knepley ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 121170034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 121270034214SMatthew G. Knepley PetscInt numPoints, offset; 121370034214SMatthew G. Knepley 121470034214SMatthew G. Knepley ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 121570034214SMatthew G. Knepley ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 121670034214SMatthew G. Knepley ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 121770034214SMatthew G. Knepley packPoints += numPoints; 121870034214SMatthew G. Knepley } 121970034214SMatthew G. Knepley 122070034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 122170034214SMatthew G. Knepley ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 122270034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 122370034214SMatthew G. Knepley PetscFunctionReturn(0); 122470034214SMatthew G. Knepley } 1225