xref: /petsc/src/dm/impls/plex/plexpartition.c (revision 7762326432740f597a4bdfe5e2040f271ba9dd28)
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