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