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