xref: /petsc/src/dm/impls/plex/plexpartition.c (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h>
3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h>
470034214SMatthew G. Knepley 
54b876568SBarry Smith const char * const DMPlexCSRAlgorithms[] = {"mat", "graph", "overlap", "DMPlexCSRAlgorithm", "DM_PLEX_CSR_",NULL};
65a107427SMatthew G. Knepley 
70134a67bSLisandro Dalcin PETSC_STATIC_INLINE PetscInt DMPlex_GlobalID(PetscInt point) { return point >= 0 ? point : -(point+1); }
80134a67bSLisandro Dalcin 
95a107427SMatthew G. Knepley static PetscErrorCode DMPlexCreatePartitionerGraph_Overlap(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
105a107427SMatthew G. Knepley {
115a107427SMatthew G. Knepley   DM              ovdm;
125a107427SMatthew G. Knepley   PetscSF         sfPoint;
135a107427SMatthew G. Knepley   IS              cellNumbering;
145a107427SMatthew G. Knepley   const PetscInt *cellNum;
155a107427SMatthew G. Knepley   PetscInt       *adj = NULL, *vOffsets = NULL, *vAdj = NULL;
165a107427SMatthew G. Knepley   PetscBool       useCone, useClosure;
175a107427SMatthew G. Knepley   PetscInt        dim, depth, overlap, cStart, cEnd, c, v;
185a107427SMatthew G. Knepley   PetscMPIInt     rank, size;
195a107427SMatthew G. Knepley   PetscErrorCode  ierr;
205a107427SMatthew G. Knepley 
215a107427SMatthew G. Knepley   PetscFunctionBegin;
225a107427SMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
235a107427SMatthew G. Knepley   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRMPI(ierr);
245a107427SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
255a107427SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
265a107427SMatthew G. Knepley   if (dim != depth) {
275a107427SMatthew G. Knepley     /* We do not handle the uninterpolated case here */
285a107427SMatthew G. Knepley     ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr);
295a107427SMatthew G. Knepley     /* DMPlexCreateNeighborCSR does not make a numbering */
305a107427SMatthew G. Knepley     if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);}
315a107427SMatthew G. Knepley     /* Different behavior for empty graphs */
325a107427SMatthew G. Knepley     if (!*numVertices) {
335a107427SMatthew G. Knepley       ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr);
345a107427SMatthew G. Knepley       (*offsets)[0] = 0;
355a107427SMatthew G. Knepley     }
365a107427SMatthew G. Knepley     /* Broken in parallel */
375a107427SMatthew G. Knepley     if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
385a107427SMatthew G. Knepley     PetscFunctionReturn(0);
395a107427SMatthew G. Knepley   }
405a107427SMatthew G. Knepley   /* Always use FVM adjacency to create partitioner graph */
415a107427SMatthew G. Knepley   ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr);
425a107427SMatthew G. Knepley   ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
435a107427SMatthew G. Knepley   /* Need overlap >= 1 */
445a107427SMatthew G. Knepley   ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr);
455a107427SMatthew G. Knepley   if (size && overlap < 1) {
465a107427SMatthew G. Knepley     ierr = DMPlexDistributeOverlap(dm, 1, NULL, &ovdm);CHKERRQ(ierr);
475a107427SMatthew G. Knepley   } else {
485a107427SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
495a107427SMatthew G. Knepley     ovdm = dm;
505a107427SMatthew G. Knepley   }
515a107427SMatthew G. Knepley   ierr = DMGetPointSF(ovdm, &sfPoint);CHKERRQ(ierr);
525a107427SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(ovdm, height, &cStart, &cEnd);CHKERRQ(ierr);
535a107427SMatthew G. Knepley   ierr = DMPlexCreateNumbering_Plex(ovdm, cStart, cEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr);
545a107427SMatthew G. Knepley   if (globalNumbering) {
555a107427SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) cellNumbering);CHKERRQ(ierr);
565a107427SMatthew G. Knepley     *globalNumbering = cellNumbering;
575a107427SMatthew G. Knepley   }
585a107427SMatthew G. Knepley   ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
595a107427SMatthew G. Knepley   /* Determine sizes */
605a107427SMatthew G. Knepley   for (*numVertices = 0, c = cStart; c < cEnd; ++c) {
615a107427SMatthew G. Knepley     /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
625a107427SMatthew G. Knepley     if (cellNum[c] < 0) continue;
635a107427SMatthew G. Knepley     (*numVertices)++;
645a107427SMatthew G. Knepley   }
655a107427SMatthew G. Knepley   ierr = PetscCalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr);
665a107427SMatthew G. Knepley   for (c = cStart, v = 0; c < cEnd; ++c) {
675a107427SMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, a, vsize = 0;
685a107427SMatthew G. Knepley 
695a107427SMatthew G. Knepley     if (cellNum[c] < 0) continue;
705a107427SMatthew G. Knepley     ierr = DMPlexGetAdjacency(ovdm, c, &adjSize, &adj);CHKERRQ(ierr);
715a107427SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
725a107427SMatthew G. Knepley       const PetscInt point = adj[a];
735a107427SMatthew G. Knepley       if (point != c && cStart <= point && point < cEnd) ++vsize;
745a107427SMatthew G. Knepley     }
755a107427SMatthew G. Knepley     vOffsets[v+1] = vOffsets[v] + vsize;
765a107427SMatthew G. Knepley     ++v;
775a107427SMatthew G. Knepley   }
785a107427SMatthew G. Knepley   /* Determine adjacency */
795a107427SMatthew G. Knepley   ierr = PetscMalloc1(vOffsets[*numVertices], &vAdj);CHKERRQ(ierr);
805a107427SMatthew G. Knepley   for (c = cStart, v = 0; c < cEnd; ++c) {
815a107427SMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, a, off = vOffsets[v];
825a107427SMatthew G. Knepley 
835a107427SMatthew G. Knepley     /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
845a107427SMatthew G. Knepley     if (cellNum[c] < 0) continue;
855a107427SMatthew G. Knepley     ierr = DMPlexGetAdjacency(ovdm, c, &adjSize, &adj);CHKERRQ(ierr);
865a107427SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
875a107427SMatthew G. Knepley       const PetscInt point = adj[a];
885a107427SMatthew G. Knepley       if (point != c && cStart <= point && point < cEnd) {
895a107427SMatthew G. Knepley         vAdj[off++] = DMPlex_GlobalID(cellNum[point]);
905a107427SMatthew G. Knepley       }
915a107427SMatthew G. Knepley     }
92*98921bdaSJacob Faibussowitsch     if (off != vOffsets[v+1]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Offsets %D should be %D", off, vOffsets[v+1]);
935a107427SMatthew G. Knepley     /* Sort adjacencies (not strictly necessary) */
945a107427SMatthew G. Knepley     ierr = PetscSortInt(off-vOffsets[v], &vAdj[vOffsets[v]]);CHKERRQ(ierr);
955a107427SMatthew G. Knepley     ++v;
965a107427SMatthew G. Knepley   }
975a107427SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
985a107427SMatthew G. Knepley   ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
995a107427SMatthew G. Knepley   ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr);
1005a107427SMatthew G. Knepley   ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr);
1015a107427SMatthew G. Knepley   ierr = DMDestroy(&ovdm);CHKERRQ(ierr);
1025a107427SMatthew G. Knepley   if (offsets)   {*offsets = vOffsets;}
1035a107427SMatthew G. Knepley   else           {ierr = PetscFree(vOffsets);CHKERRQ(ierr);}
1045a107427SMatthew G. Knepley   if (adjacency) {*adjacency = vAdj;}
1055a107427SMatthew G. Knepley   else           {ierr = PetscFree(vAdj);CHKERRQ(ierr);}
1065a107427SMatthew G. Knepley   PetscFunctionReturn(0);
1075a107427SMatthew G. Knepley }
1085a107427SMatthew G. Knepley 
109bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_Native(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
110532c4e7dSMichael Lange {
111ffbd6163SMatthew G. Knepley   PetscInt       dim, depth, p, pStart, pEnd, a, adjSize, idx, size;
112389e55d8SMichael Lange   PetscInt      *adj = NULL, *vOffsets = NULL, *graph = NULL;
1138cfe4c1fSMichael Lange   IS             cellNumbering;
1148cfe4c1fSMichael Lange   const PetscInt *cellNum;
115532c4e7dSMichael Lange   PetscBool      useCone, useClosure;
116532c4e7dSMichael Lange   PetscSection   section;
117532c4e7dSMichael Lange   PetscSegBuffer adjBuffer;
1188cfe4c1fSMichael Lange   PetscSF        sfPoint;
1198f4e72b9SMatthew G. Knepley   PetscInt       *adjCells = NULL, *remoteCells = NULL;
1208f4e72b9SMatthew G. Knepley   const PetscInt *local;
1218f4e72b9SMatthew G. Knepley   PetscInt       nroots, nleaves, l;
122532c4e7dSMichael Lange   PetscMPIInt    rank;
123532c4e7dSMichael Lange   PetscErrorCode ierr;
124532c4e7dSMichael Lange 
125532c4e7dSMichael Lange   PetscFunctionBegin;
126ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
127ffbd6163SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
128ffbd6163SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
129ffbd6163SMatthew G. Knepley   if (dim != depth) {
130ffbd6163SMatthew G. Knepley     /* We do not handle the uninterpolated case here */
131ffbd6163SMatthew G. Knepley     ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr);
132ffbd6163SMatthew G. Knepley     /* DMPlexCreateNeighborCSR does not make a numbering */
133ffbd6163SMatthew G. Knepley     if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);}
134ffbd6163SMatthew G. Knepley     /* Different behavior for empty graphs */
135ffbd6163SMatthew G. Knepley     if (!*numVertices) {
136ffbd6163SMatthew G. Knepley       ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr);
137ffbd6163SMatthew G. Knepley       (*offsets)[0] = 0;
138ffbd6163SMatthew G. Knepley     }
139ffbd6163SMatthew G. Knepley     /* Broken in parallel */
140ffbd6163SMatthew G. Knepley     if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
141ffbd6163SMatthew G. Knepley     PetscFunctionReturn(0);
142ffbd6163SMatthew G. Knepley   }
1438cfe4c1fSMichael Lange   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
1440134a67bSLisandro Dalcin   ierr = DMPlexGetHeightStratum(dm, height, &pStart, &pEnd);CHKERRQ(ierr);
145532c4e7dSMichael Lange   /* Build adjacency graph via a section/segbuffer */
146532c4e7dSMichael Lange   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &section);CHKERRQ(ierr);
147532c4e7dSMichael Lange   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
148532c4e7dSMichael Lange   ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&adjBuffer);CHKERRQ(ierr);
149532c4e7dSMichael Lange   /* Always use FVM adjacency to create partitioner graph */
150b0441da4SMatthew G. Knepley   ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr);
151b0441da4SMatthew G. Knepley   ierr = DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr);
1529886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, sfPoint, &cellNumbering);CHKERRQ(ierr);
1533fa7752dSToby Isaac   if (globalNumbering) {
1543fa7752dSToby Isaac     ierr = PetscObjectReference((PetscObject)cellNumbering);CHKERRQ(ierr);
1553fa7752dSToby Isaac     *globalNumbering = cellNumbering;
1563fa7752dSToby Isaac   }
1578cfe4c1fSMichael Lange   ierr = ISGetIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
1588f4e72b9SMatthew G. Knepley   /* For all boundary faces (including faces adjacent to a ghost cell), record the local cell in adjCells
1598f4e72b9SMatthew G. Knepley      Broadcast adjCells to remoteCells (to get cells from roots) and Reduce adjCells to remoteCells (to get cells from leaves)
1608f4e72b9SMatthew G. Knepley    */
1610134a67bSLisandro Dalcin   ierr = PetscSFGetGraph(sfPoint, &nroots, &nleaves, &local, NULL);CHKERRQ(ierr);
1628f4e72b9SMatthew G. Knepley   if (nroots >= 0) {
1638f4e72b9SMatthew G. Knepley     PetscInt fStart, fEnd, f;
1648f4e72b9SMatthew G. Knepley 
1658f4e72b9SMatthew G. Knepley     ierr = PetscCalloc2(nroots, &adjCells, nroots, &remoteCells);CHKERRQ(ierr);
1660134a67bSLisandro Dalcin     ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr);
1678f4e72b9SMatthew G. Knepley     for (l = 0; l < nroots; ++l) adjCells[l] = -3;
1688f4e72b9SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1698f4e72b9SMatthew G. Knepley       const PetscInt *support;
1708f4e72b9SMatthew G. Knepley       PetscInt        supportSize;
1718f4e72b9SMatthew G. Knepley 
1728f4e72b9SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1738f4e72b9SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1740134a67bSLisandro Dalcin       if (supportSize == 1) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]);
1758f4e72b9SMatthew G. Knepley       else if (supportSize == 2) {
1768f4e72b9SMatthew G. Knepley         ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr);
1770134a67bSLisandro Dalcin         if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[1]]);
1788f4e72b9SMatthew G. Knepley         ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr);
1790134a67bSLisandro Dalcin         if (p >= 0) adjCells[f] = DMPlex_GlobalID(cellNum[support[0]]);
1800134a67bSLisandro Dalcin       }
1810134a67bSLisandro Dalcin       /* Handle non-conforming meshes */
1820134a67bSLisandro Dalcin       if (supportSize > 2) {
1830134a67bSLisandro Dalcin         PetscInt        numChildren, i;
1840134a67bSLisandro Dalcin         const PetscInt *children;
1850134a67bSLisandro Dalcin 
1860134a67bSLisandro Dalcin         ierr = DMPlexGetTreeChildren(dm, f, &numChildren, &children);CHKERRQ(ierr);
1870134a67bSLisandro Dalcin         for (i = 0; i < numChildren; ++i) {
1880134a67bSLisandro Dalcin           const PetscInt child = children[i];
1890134a67bSLisandro Dalcin           if (fStart <= child && child < fEnd) {
1900134a67bSLisandro Dalcin             ierr = DMPlexGetSupport(dm, child, &support);CHKERRQ(ierr);
1910134a67bSLisandro Dalcin             ierr = DMPlexGetSupportSize(dm, child, &supportSize);CHKERRQ(ierr);
1920134a67bSLisandro Dalcin             if (supportSize == 1) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]);
1930134a67bSLisandro Dalcin             else if (supportSize == 2) {
1940134a67bSLisandro Dalcin               ierr = PetscFindInt(support[0], nleaves, local, &p);CHKERRQ(ierr);
1950134a67bSLisandro Dalcin               if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[1]]);
1960134a67bSLisandro Dalcin               ierr = PetscFindInt(support[1], nleaves, local, &p);CHKERRQ(ierr);
1970134a67bSLisandro Dalcin               if (p >= 0) adjCells[child] = DMPlex_GlobalID(cellNum[support[0]]);
1980134a67bSLisandro Dalcin             }
1990134a67bSLisandro Dalcin           }
2000134a67bSLisandro Dalcin         }
2018f4e72b9SMatthew G. Knepley       }
2028f4e72b9SMatthew G. Knepley     }
2038f4e72b9SMatthew G. Knepley     for (l = 0; l < nroots; ++l) remoteCells[l] = -1;
204ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE);CHKERRQ(ierr);
205ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(dm->sf, MPIU_INT, adjCells, remoteCells,MPI_REPLACE);CHKERRQ(ierr);
2068f4e72b9SMatthew G. Knepley     ierr = PetscSFReduceBegin(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr);
2078f4e72b9SMatthew G. Knepley     ierr = PetscSFReduceEnd(dm->sf, MPIU_INT, adjCells, remoteCells, MPI_MAX);CHKERRQ(ierr);
2088f4e72b9SMatthew G. Knepley   }
2098f4e72b9SMatthew G. Knepley   /* Combine local and global adjacencies */
2108cfe4c1fSMichael Lange   for (*numVertices = 0, p = pStart; p < pEnd; p++) {
2118cfe4c1fSMichael Lange     /* Skip non-owned cells in parallel (ParMetis expects no overlap) */
2128cfe4c1fSMichael Lange     if (nroots > 0) {if (cellNum[p] < 0) continue;}
2138f4e72b9SMatthew G. Knepley     /* Add remote cells */
2148f4e72b9SMatthew G. Knepley     if (remoteCells) {
2150134a67bSLisandro Dalcin       const PetscInt gp = DMPlex_GlobalID(cellNum[p]);
2160134a67bSLisandro Dalcin       PetscInt       coneSize, numChildren, c, i;
2170134a67bSLisandro Dalcin       const PetscInt *cone, *children;
2180134a67bSLisandro Dalcin 
2198f4e72b9SMatthew G. Knepley       ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
2208f4e72b9SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
2218f4e72b9SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
2220134a67bSLisandro Dalcin         const PetscInt point = cone[c];
2230134a67bSLisandro Dalcin         if (remoteCells[point] >= 0 && remoteCells[point] != gp) {
2248f4e72b9SMatthew G. Knepley           PetscInt *PETSC_RESTRICT pBuf;
2258f4e72b9SMatthew G. Knepley           ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2268f4e72b9SMatthew G. Knepley           ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2270134a67bSLisandro Dalcin           *pBuf = remoteCells[point];
2280134a67bSLisandro Dalcin         }
2290134a67bSLisandro Dalcin         /* Handle non-conforming meshes */
2300134a67bSLisandro Dalcin         ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr);
2310134a67bSLisandro Dalcin         for (i = 0; i < numChildren; ++i) {
2320134a67bSLisandro Dalcin           const PetscInt child = children[i];
2330134a67bSLisandro Dalcin           if (remoteCells[child] >= 0 && remoteCells[child] != gp) {
2340134a67bSLisandro Dalcin             PetscInt *PETSC_RESTRICT pBuf;
2350134a67bSLisandro Dalcin             ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
2360134a67bSLisandro Dalcin             ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2370134a67bSLisandro Dalcin             *pBuf = remoteCells[child];
2380134a67bSLisandro Dalcin           }
2398f4e72b9SMatthew G. Knepley         }
2408f4e72b9SMatthew G. Knepley       }
2418f4e72b9SMatthew G. Knepley     }
2428f4e72b9SMatthew G. Knepley     /* Add local cells */
243532c4e7dSMichael Lange     adjSize = PETSC_DETERMINE;
244532c4e7dSMichael Lange     ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
245532c4e7dSMichael Lange     for (a = 0; a < adjSize; ++a) {
246532c4e7dSMichael Lange       const PetscInt point = adj[a];
247532c4e7dSMichael Lange       if (point != p && pStart <= point && point < pEnd) {
248532c4e7dSMichael Lange         PetscInt *PETSC_RESTRICT pBuf;
249532c4e7dSMichael Lange         ierr = PetscSectionAddDof(section, p, 1);CHKERRQ(ierr);
250532c4e7dSMichael Lange         ierr = PetscSegBufferGetInts(adjBuffer, 1, &pBuf);CHKERRQ(ierr);
2510134a67bSLisandro Dalcin         *pBuf = DMPlex_GlobalID(cellNum[point]);
252532c4e7dSMichael Lange       }
253532c4e7dSMichael Lange     }
2548cfe4c1fSMichael Lange     (*numVertices)++;
255532c4e7dSMichael Lange   }
2564e468a93SLisandro Dalcin   ierr = PetscFree(adj);CHKERRQ(ierr);
2578f4e72b9SMatthew G. Knepley   ierr = PetscFree2(adjCells, remoteCells);CHKERRQ(ierr);
258b0441da4SMatthew G. Knepley   ierr = DMSetBasicAdjacency(dm, useCone, useClosure);CHKERRQ(ierr);
2594e468a93SLisandro Dalcin 
260532c4e7dSMichael Lange   /* Derive CSR graph from section/segbuffer */
261532c4e7dSMichael Lange   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
262532c4e7dSMichael Lange   ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
263389e55d8SMichael Lange   ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr);
26443f7d02bSMichael Lange   for (idx = 0, p = pStart; p < pEnd; p++) {
26543f7d02bSMichael Lange     if (nroots > 0) {if (cellNum[p] < 0) continue;}
26643f7d02bSMichael Lange     ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr);
26743f7d02bSMichael Lange   }
268532c4e7dSMichael Lange   vOffsets[*numVertices] = size;
269389e55d8SMichael Lange   ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr);
2704e468a93SLisandro Dalcin 
2714e468a93SLisandro Dalcin   if (nroots >= 0) {
2724e468a93SLisandro Dalcin     /* Filter out duplicate edges using section/segbuffer */
2734e468a93SLisandro Dalcin     ierr = PetscSectionReset(section);CHKERRQ(ierr);
2744e468a93SLisandro Dalcin     ierr = PetscSectionSetChart(section, 0, *numVertices);CHKERRQ(ierr);
2754e468a93SLisandro Dalcin     for (p = 0; p < *numVertices; p++) {
2764e468a93SLisandro Dalcin       PetscInt start = vOffsets[p], end = vOffsets[p+1];
2774e468a93SLisandro Dalcin       PetscInt numEdges = end-start, *PETSC_RESTRICT edges;
2784e468a93SLisandro Dalcin       ierr = PetscSortRemoveDupsInt(&numEdges, &graph[start]);CHKERRQ(ierr);
2794e468a93SLisandro Dalcin       ierr = PetscSectionSetDof(section, p, numEdges);CHKERRQ(ierr);
2804e468a93SLisandro Dalcin       ierr = PetscSegBufferGetInts(adjBuffer, numEdges, &edges);CHKERRQ(ierr);
281580bdb30SBarry Smith       ierr = PetscArraycpy(edges, &graph[start], numEdges);CHKERRQ(ierr);
2824e468a93SLisandro Dalcin     }
2834e468a93SLisandro Dalcin     ierr = PetscFree(vOffsets);CHKERRQ(ierr);
2844e468a93SLisandro Dalcin     ierr = PetscFree(graph);CHKERRQ(ierr);
2854e468a93SLisandro Dalcin     /* Derive CSR graph from section/segbuffer */
2864e468a93SLisandro Dalcin     ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
2874e468a93SLisandro Dalcin     ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2884e468a93SLisandro Dalcin     ierr = PetscMalloc1(*numVertices+1, &vOffsets);CHKERRQ(ierr);
2894e468a93SLisandro Dalcin     for (idx = 0, p = 0; p < *numVertices; p++) {
2904e468a93SLisandro Dalcin       ierr = PetscSectionGetOffset(section, p, &(vOffsets[idx++]));CHKERRQ(ierr);
2914e468a93SLisandro Dalcin     }
2924e468a93SLisandro Dalcin     vOffsets[*numVertices] = size;
2934e468a93SLisandro Dalcin     ierr = PetscSegBufferExtractAlloc(adjBuffer, &graph);CHKERRQ(ierr);
2944e468a93SLisandro Dalcin   } else {
2954e468a93SLisandro Dalcin     /* Sort adjacencies (not strictly necessary) */
2964e468a93SLisandro Dalcin     for (p = 0; p < *numVertices; p++) {
2974e468a93SLisandro Dalcin       PetscInt start = vOffsets[p], end = vOffsets[p+1];
2984e468a93SLisandro Dalcin       ierr = PetscSortInt(end-start, &graph[start]);CHKERRQ(ierr);
2994e468a93SLisandro Dalcin     }
3004e468a93SLisandro Dalcin   }
3014e468a93SLisandro Dalcin 
3024e468a93SLisandro Dalcin   if (offsets) *offsets = vOffsets;
303389e55d8SMichael Lange   if (adjacency) *adjacency = graph;
3044e468a93SLisandro Dalcin 
305532c4e7dSMichael Lange   /* Cleanup */
306532c4e7dSMichael Lange   ierr = PetscSegBufferDestroy(&adjBuffer);CHKERRQ(ierr);
307532c4e7dSMichael Lange   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
3084e468a93SLisandro Dalcin   ierr = ISRestoreIndices(cellNumbering, &cellNum);CHKERRQ(ierr);
3094e468a93SLisandro Dalcin   ierr = ISDestroy(&cellNumbering);CHKERRQ(ierr);
310532c4e7dSMichael Lange   PetscFunctionReturn(0);
311532c4e7dSMichael Lange }
312532c4e7dSMichael Lange 
313bbbc8e51SStefano Zampini static PetscErrorCode DMPlexCreatePartitionerGraph_ViaMat(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
314bbbc8e51SStefano Zampini {
315bbbc8e51SStefano Zampini   Mat            conn, CSR;
316bbbc8e51SStefano Zampini   IS             fis, cis, cis_own;
317bbbc8e51SStefano Zampini   PetscSF        sfPoint;
318bbbc8e51SStefano Zampini   const PetscInt *rows, *cols, *ii, *jj;
319bbbc8e51SStefano Zampini   PetscInt       *idxs,*idxs2;
32083c5d788SMatthew G. Knepley   PetscInt       dim, depth, floc, cloc, i, M, N, c, lm, m, cStart, cEnd, fStart, fEnd;
321bbbc8e51SStefano Zampini   PetscMPIInt    rank;
322bbbc8e51SStefano Zampini   PetscBool      flg;
323bbbc8e51SStefano Zampini   PetscErrorCode ierr;
324bbbc8e51SStefano Zampini 
325bbbc8e51SStefano Zampini   PetscFunctionBegin;
326ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
327bbbc8e51SStefano Zampini   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
328bbbc8e51SStefano Zampini   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
329bbbc8e51SStefano Zampini   if (dim != depth) {
330bbbc8e51SStefano Zampini     /* We do not handle the uninterpolated case here */
331bbbc8e51SStefano Zampini     ierr = DMPlexCreateNeighborCSR(dm, height, numVertices, offsets, adjacency);CHKERRQ(ierr);
332bbbc8e51SStefano Zampini     /* DMPlexCreateNeighborCSR does not make a numbering */
333bbbc8e51SStefano Zampini     if (globalNumbering) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, globalNumbering);CHKERRQ(ierr);}
334bbbc8e51SStefano Zampini     /* Different behavior for empty graphs */
335bbbc8e51SStefano Zampini     if (!*numVertices) {
336bbbc8e51SStefano Zampini       ierr = PetscMalloc1(1, offsets);CHKERRQ(ierr);
337bbbc8e51SStefano Zampini       (*offsets)[0] = 0;
338bbbc8e51SStefano Zampini     }
339bbbc8e51SStefano Zampini     /* Broken in parallel */
340bbbc8e51SStefano Zampini     if (rank && *numVertices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parallel partitioning of uninterpolated meshes not supported");
341bbbc8e51SStefano Zampini     PetscFunctionReturn(0);
342bbbc8e51SStefano Zampini   }
343bbbc8e51SStefano Zampini   /* Interpolated and parallel case */
344bbbc8e51SStefano Zampini 
345bbbc8e51SStefano Zampini   /* numbering */
346bbbc8e51SStefano Zampini   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
347bbbc8e51SStefano Zampini   ierr = DMPlexGetHeightStratum(dm, height, &cStart, &cEnd);CHKERRQ(ierr);
348bbbc8e51SStefano Zampini   ierr = DMPlexGetHeightStratum(dm, height+1, &fStart, &fEnd);CHKERRQ(ierr);
3499886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, &N, sfPoint, &cis);CHKERRQ(ierr);
3509886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, fStart, fEnd, 0, &M, sfPoint, &fis);CHKERRQ(ierr);
351bbbc8e51SStefano Zampini   if (globalNumbering) {
352bbbc8e51SStefano Zampini     ierr = ISDuplicate(cis, globalNumbering);CHKERRQ(ierr);
353bbbc8e51SStefano Zampini   }
354bbbc8e51SStefano Zampini 
355bbbc8e51SStefano Zampini   /* get positive global ids and local sizes for facets and cells */
356bbbc8e51SStefano Zampini   ierr = ISGetLocalSize(fis, &m);CHKERRQ(ierr);
357bbbc8e51SStefano Zampini   ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr);
358bbbc8e51SStefano Zampini   ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr);
359bbbc8e51SStefano Zampini   for (i = 0, floc = 0; i < m; i++) {
360bbbc8e51SStefano Zampini     const PetscInt p = rows[i];
361bbbc8e51SStefano Zampini 
362bbbc8e51SStefano Zampini     if (p < 0) {
363bbbc8e51SStefano Zampini       idxs[i] = -(p+1);
364bbbc8e51SStefano Zampini     } else {
365bbbc8e51SStefano Zampini       idxs[i] = p;
366bbbc8e51SStefano Zampini       floc   += 1;
367bbbc8e51SStefano Zampini     }
368bbbc8e51SStefano Zampini   }
369bbbc8e51SStefano Zampini   ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr);
370bbbc8e51SStefano Zampini   ierr = ISDestroy(&fis);CHKERRQ(ierr);
371bbbc8e51SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF, m, idxs, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr);
372bbbc8e51SStefano Zampini 
373bbbc8e51SStefano Zampini   ierr = ISGetLocalSize(cis, &m);CHKERRQ(ierr);
374bbbc8e51SStefano Zampini   ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr);
375bbbc8e51SStefano Zampini   ierr = PetscMalloc1(m, &idxs);CHKERRQ(ierr);
376bbbc8e51SStefano Zampini   ierr = PetscMalloc1(m, &idxs2);CHKERRQ(ierr);
377bbbc8e51SStefano Zampini   for (i = 0, cloc = 0; i < m; i++) {
378bbbc8e51SStefano Zampini     const PetscInt p = cols[i];
379bbbc8e51SStefano Zampini 
380bbbc8e51SStefano Zampini     if (p < 0) {
381bbbc8e51SStefano Zampini       idxs[i] = -(p+1);
382bbbc8e51SStefano Zampini     } else {
383bbbc8e51SStefano Zampini       idxs[i]       = p;
384bbbc8e51SStefano Zampini       idxs2[cloc++] = p;
385bbbc8e51SStefano Zampini     }
386bbbc8e51SStefano Zampini   }
387bbbc8e51SStefano Zampini   ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr);
388bbbc8e51SStefano Zampini   ierr = ISDestroy(&cis);CHKERRQ(ierr);
389bbbc8e51SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), m, idxs, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr);
390bbbc8e51SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cloc, idxs2, PETSC_OWN_POINTER, &cis_own);CHKERRQ(ierr);
391bbbc8e51SStefano Zampini 
392bbbc8e51SStefano Zampini   /* Create matrix to hold F-C connectivity (MatMatTranspose Mult not supported for MPIAIJ) */
393bbbc8e51SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)dm), &conn);CHKERRQ(ierr);
394bbbc8e51SStefano Zampini   ierr = MatSetSizes(conn, floc, cloc, M, N);CHKERRQ(ierr);
395bbbc8e51SStefano Zampini   ierr = MatSetType(conn, MATMPIAIJ);CHKERRQ(ierr);
39683c5d788SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, NULL, &lm);CHKERRQ(ierr);
397ffc4695bSBarry Smith   ierr = MPI_Allreduce(&lm, &m, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
398bbbc8e51SStefano Zampini   ierr = MatMPIAIJSetPreallocation(conn, m, NULL, m, NULL);CHKERRQ(ierr);
399bbbc8e51SStefano Zampini 
400bbbc8e51SStefano Zampini   /* Assemble matrix */
401bbbc8e51SStefano Zampini   ierr = ISGetIndices(fis, &rows);CHKERRQ(ierr);
402bbbc8e51SStefano Zampini   ierr = ISGetIndices(cis, &cols);CHKERRQ(ierr);
403bbbc8e51SStefano Zampini   for (c = cStart; c < cEnd; c++) {
404bbbc8e51SStefano Zampini     const PetscInt *cone;
405bbbc8e51SStefano Zampini     PetscInt        coneSize, row, col, f;
406bbbc8e51SStefano Zampini 
407bbbc8e51SStefano Zampini     col  = cols[c-cStart];
408bbbc8e51SStefano Zampini     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
409bbbc8e51SStefano Zampini     ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
410bbbc8e51SStefano Zampini     for (f = 0; f < coneSize; f++) {
411bbbc8e51SStefano Zampini       const PetscScalar v = 1.0;
412bbbc8e51SStefano Zampini       const PetscInt *children;
413bbbc8e51SStefano Zampini       PetscInt        numChildren, ch;
414bbbc8e51SStefano Zampini 
415bbbc8e51SStefano Zampini       row  = rows[cone[f]-fStart];
416bbbc8e51SStefano Zampini       ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr);
417bbbc8e51SStefano Zampini 
418bbbc8e51SStefano Zampini       /* non-conforming meshes */
419bbbc8e51SStefano Zampini       ierr = DMPlexGetTreeChildren(dm, cone[f], &numChildren, &children);CHKERRQ(ierr);
420bbbc8e51SStefano Zampini       for (ch = 0; ch < numChildren; ch++) {
421bbbc8e51SStefano Zampini         const PetscInt child = children[ch];
422bbbc8e51SStefano Zampini 
423bbbc8e51SStefano Zampini         if (child < fStart || child >= fEnd) continue;
424bbbc8e51SStefano Zampini         row  = rows[child-fStart];
425bbbc8e51SStefano Zampini         ierr = MatSetValues(conn, 1, &row, 1, &col, &v, INSERT_VALUES);CHKERRQ(ierr);
426bbbc8e51SStefano Zampini       }
427bbbc8e51SStefano Zampini     }
428bbbc8e51SStefano Zampini   }
429bbbc8e51SStefano Zampini   ierr = ISRestoreIndices(fis, &rows);CHKERRQ(ierr);
430bbbc8e51SStefano Zampini   ierr = ISRestoreIndices(cis, &cols);CHKERRQ(ierr);
431bbbc8e51SStefano Zampini   ierr = ISDestroy(&fis);CHKERRQ(ierr);
432bbbc8e51SStefano Zampini   ierr = ISDestroy(&cis);CHKERRQ(ierr);
433bbbc8e51SStefano Zampini   ierr = MatAssemblyBegin(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
434bbbc8e51SStefano Zampini   ierr = MatAssemblyEnd(conn, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
435bbbc8e51SStefano Zampini 
436bbbc8e51SStefano Zampini   /* Get parallel CSR by doing conn^T * conn */
437bbbc8e51SStefano Zampini   ierr = MatTransposeMatMult(conn, conn, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &CSR);CHKERRQ(ierr);
438bbbc8e51SStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
439bbbc8e51SStefano Zampini 
440bbbc8e51SStefano Zampini   /* extract local part of the CSR */
441bbbc8e51SStefano Zampini   ierr = MatMPIAIJGetLocalMat(CSR, MAT_INITIAL_MATRIX, &conn);CHKERRQ(ierr);
442bbbc8e51SStefano Zampini   ierr = MatDestroy(&CSR);CHKERRQ(ierr);
443bbbc8e51SStefano Zampini   ierr = MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr);
444bbbc8e51SStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format");
445bbbc8e51SStefano Zampini 
446bbbc8e51SStefano Zampini   /* get back requested output */
447bbbc8e51SStefano Zampini   if (numVertices) *numVertices = m;
448bbbc8e51SStefano Zampini   if (offsets) {
449bbbc8e51SStefano Zampini     ierr = PetscCalloc1(m+1, &idxs);CHKERRQ(ierr);
450bbbc8e51SStefano Zampini     for (i = 1; i < m+1; i++) idxs[i] = ii[i] - i; /* ParMetis does not like self-connectivity */
451bbbc8e51SStefano Zampini     *offsets = idxs;
452bbbc8e51SStefano Zampini   }
453bbbc8e51SStefano Zampini   if (adjacency) {
454bbbc8e51SStefano Zampini     ierr = PetscMalloc1(ii[m] - m, &idxs);CHKERRQ(ierr);
455bbbc8e51SStefano Zampini     ierr = ISGetIndices(cis_own, &rows);CHKERRQ(ierr);
456bbbc8e51SStefano Zampini     for (i = 0, c = 0; i < m; i++) {
457bbbc8e51SStefano Zampini       PetscInt j, g = rows[i];
458bbbc8e51SStefano Zampini 
459bbbc8e51SStefano Zampini       for (j = ii[i]; j < ii[i+1]; j++) {
460bbbc8e51SStefano Zampini         if (jj[j] == g) continue; /* again, self-connectivity */
461bbbc8e51SStefano Zampini         idxs[c++] = jj[j];
462bbbc8e51SStefano Zampini       }
463bbbc8e51SStefano Zampini     }
464*98921bdaSJacob Faibussowitsch     if (c != ii[m] - m) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %D != %D",c,ii[m]-m);
465bbbc8e51SStefano Zampini     ierr = ISRestoreIndices(cis_own, &rows);CHKERRQ(ierr);
466bbbc8e51SStefano Zampini     *adjacency = idxs;
467bbbc8e51SStefano Zampini   }
468bbbc8e51SStefano Zampini 
469bbbc8e51SStefano Zampini   /* cleanup */
470bbbc8e51SStefano Zampini   ierr = ISDestroy(&cis_own);CHKERRQ(ierr);
471bbbc8e51SStefano Zampini   ierr = MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg);CHKERRQ(ierr);
472bbbc8e51SStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "No IJ format");
473bbbc8e51SStefano Zampini   ierr = MatDestroy(&conn);CHKERRQ(ierr);
474bbbc8e51SStefano Zampini   PetscFunctionReturn(0);
475bbbc8e51SStefano Zampini }
476bbbc8e51SStefano Zampini 
477bbbc8e51SStefano Zampini /*@C
478bbbc8e51SStefano Zampini   DMPlexCreatePartitionerGraph - Create a CSR graph of point connections for the partitioner
479bbbc8e51SStefano Zampini 
480bbbc8e51SStefano Zampini   Input Parameters:
481bbbc8e51SStefano Zampini + dm      - The mesh DM dm
482bbbc8e51SStefano Zampini - height  - Height of the strata from which to construct the graph
483bbbc8e51SStefano Zampini 
484d8d19677SJose E. Roman   Output Parameters:
485bbbc8e51SStefano Zampini + numVertices     - Number of vertices in the graph
486bbbc8e51SStefano Zampini . offsets         - Point offsets in the graph
487bbbc8e51SStefano Zampini . adjacency       - Point connectivity in the graph
488bbbc8e51SStefano Zampini - 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.
489bbbc8e51SStefano Zampini 
490bbbc8e51SStefano Zampini   The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function
491bbbc8e51SStefano Zampini   representation on the mesh. If requested, globalNumbering needs to be destroyed by the caller; offsets and adjacency need to be freed with PetscFree().
492bbbc8e51SStefano Zampini 
4935a107427SMatthew G. Knepley   Options Database Keys:
4945a107427SMatthew G. Knepley . -dm_plex_csr_alg <mat,graph,overlap> - Choose the algorithm for computing the CSR graph
4955a107427SMatthew G. Knepley 
496bbbc8e51SStefano Zampini   Level: developer
497bbbc8e51SStefano Zampini 
498bbbc8e51SStefano Zampini .seealso: PetscPartitionerGetType(), PetscPartitionerCreate(), DMSetAdjacency()
499bbbc8e51SStefano Zampini @*/
500bbbc8e51SStefano Zampini PetscErrorCode DMPlexCreatePartitionerGraph(DM dm, PetscInt height, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency, IS *globalNumbering)
501bbbc8e51SStefano Zampini {
5025a107427SMatthew G. Knepley   DMPlexCSRAlgorithm alg = DM_PLEX_CSR_GRAPH;
503bbbc8e51SStefano Zampini   PetscErrorCode     ierr;
504bbbc8e51SStefano Zampini 
505bbbc8e51SStefano Zampini   PetscFunctionBegin;
5065a107427SMatthew G. Knepley   ierr = PetscOptionsGetEnum(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_csr_alg", DMPlexCSRAlgorithms, (PetscEnum *) &alg, NULL);CHKERRQ(ierr);
5075a107427SMatthew G. Knepley   switch (alg) {
5085a107427SMatthew G. Knepley     case DM_PLEX_CSR_MAT:
5095a107427SMatthew G. Knepley       ierr = DMPlexCreatePartitionerGraph_ViaMat(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break;
5105a107427SMatthew G. Knepley     case DM_PLEX_CSR_GRAPH:
5115a107427SMatthew G. Knepley       ierr = DMPlexCreatePartitionerGraph_Native(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break;
5125a107427SMatthew G. Knepley     case DM_PLEX_CSR_OVERLAP:
5135a107427SMatthew G. Knepley       ierr = DMPlexCreatePartitionerGraph_Overlap(dm, height, numVertices, offsets, adjacency, globalNumbering);CHKERRQ(ierr);break;
514bbbc8e51SStefano Zampini   }
515bbbc8e51SStefano Zampini   PetscFunctionReturn(0);
516bbbc8e51SStefano Zampini }
517bbbc8e51SStefano Zampini 
518d5577e40SMatthew G. Knepley /*@C
519d5577e40SMatthew G. Knepley   DMPlexCreateNeighborCSR - Create a mesh graph (cell-cell adjacency) in parallel CSR format.
520d5577e40SMatthew G. Knepley 
521fe2efc57SMark   Collective on DM
522d5577e40SMatthew G. Knepley 
5234165533cSJose E. Roman   Input Parameters:
524d5577e40SMatthew G. Knepley + dm - The DMPlex
525d5577e40SMatthew G. Knepley - cellHeight - The height of mesh points to treat as cells (default should be 0)
526d5577e40SMatthew G. Knepley 
5274165533cSJose E. Roman   Output Parameters:
528d5577e40SMatthew G. Knepley + numVertices - The number of local vertices in the graph, or cells in the mesh.
529d5577e40SMatthew G. Knepley . offsets     - The offset to the adjacency list for each cell
530d5577e40SMatthew G. Knepley - adjacency   - The adjacency list for all cells
531d5577e40SMatthew G. Knepley 
532d5577e40SMatthew G. Knepley   Note: This is suitable for input to a mesh partitioner like ParMetis.
533d5577e40SMatthew G. Knepley 
534d5577e40SMatthew G. Knepley   Level: advanced
535d5577e40SMatthew G. Knepley 
536d5577e40SMatthew G. Knepley .seealso: DMPlexCreate()
537d5577e40SMatthew G. Knepley @*/
53870034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency)
53970034214SMatthew G. Knepley {
54070034214SMatthew G. Knepley   const PetscInt maxFaceCases = 30;
54170034214SMatthew G. Knepley   PetscInt       numFaceCases = 0;
54270034214SMatthew G. Knepley   PetscInt       numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */
54370034214SMatthew G. Knepley   PetscInt      *off, *adj;
54470034214SMatthew G. Knepley   PetscInt      *neighborCells = NULL;
54570034214SMatthew G. Knepley   PetscInt       dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell;
54670034214SMatthew G. Knepley   PetscErrorCode ierr;
54770034214SMatthew G. Knepley 
54870034214SMatthew G. Knepley   PetscFunctionBegin;
54970034214SMatthew G. Knepley   /* For parallel partitioning, I think you have to communicate supports */
550c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
55170034214SMatthew G. Knepley   cellDim = dim - cellHeight;
55270034214SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
55370034214SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
55470034214SMatthew G. Knepley   if (cEnd - cStart == 0) {
55570034214SMatthew G. Knepley     if (numVertices) *numVertices = 0;
55670034214SMatthew G. Knepley     if (offsets)   *offsets   = NULL;
55770034214SMatthew G. Knepley     if (adjacency) *adjacency = NULL;
55870034214SMatthew G. Knepley     PetscFunctionReturn(0);
55970034214SMatthew G. Knepley   }
56070034214SMatthew G. Knepley   numCells  = cEnd - cStart;
56170034214SMatthew G. Knepley   faceDepth = depth - cellHeight;
56270034214SMatthew G. Knepley   if (dim == depth) {
56370034214SMatthew G. Knepley     PetscInt f, fStart, fEnd;
56470034214SMatthew G. Knepley 
56570034214SMatthew G. Knepley     ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr);
56670034214SMatthew G. Knepley     /* Count neighboring cells */
56770034214SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr);
56870034214SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
56970034214SMatthew G. Knepley       const PetscInt *support;
57070034214SMatthew G. Knepley       PetscInt        supportSize;
57170034214SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
57270034214SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
57370034214SMatthew G. Knepley       if (supportSize == 2) {
5749ffc88e4SToby Isaac         PetscInt numChildren;
5759ffc88e4SToby Isaac 
5769ffc88e4SToby Isaac         ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr);
5779ffc88e4SToby Isaac         if (!numChildren) {
57870034214SMatthew G. Knepley           ++off[support[0]-cStart+1];
57970034214SMatthew G. Knepley           ++off[support[1]-cStart+1];
58070034214SMatthew G. Knepley         }
58170034214SMatthew G. Knepley       }
5829ffc88e4SToby Isaac     }
58370034214SMatthew G. Knepley     /* Prefix sum */
58470034214SMatthew G. Knepley     for (c = 1; c <= numCells; ++c) off[c] += off[c-1];
58570034214SMatthew G. Knepley     if (adjacency) {
58670034214SMatthew G. Knepley       PetscInt *tmp;
58770034214SMatthew G. Knepley 
58870034214SMatthew G. Knepley       ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr);
589854ce69bSBarry Smith       ierr = PetscMalloc1(numCells+1, &tmp);CHKERRQ(ierr);
590580bdb30SBarry Smith       ierr = PetscArraycpy(tmp, off, numCells+1);CHKERRQ(ierr);
59170034214SMatthew G. Knepley       /* Get neighboring cells */
59270034214SMatthew G. Knepley       for (f = fStart; f < fEnd; ++f) {
59370034214SMatthew G. Knepley         const PetscInt *support;
59470034214SMatthew G. Knepley         PetscInt        supportSize;
59570034214SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
59670034214SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
59770034214SMatthew G. Knepley         if (supportSize == 2) {
5989ffc88e4SToby Isaac           PetscInt numChildren;
5999ffc88e4SToby Isaac 
6009ffc88e4SToby Isaac           ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr);
6019ffc88e4SToby Isaac           if (!numChildren) {
60270034214SMatthew G. Knepley             adj[tmp[support[0]-cStart]++] = support[1];
60370034214SMatthew G. Knepley             adj[tmp[support[1]-cStart]++] = support[0];
60470034214SMatthew G. Knepley           }
60570034214SMatthew G. Knepley         }
6069ffc88e4SToby Isaac       }
60776bd3646SJed Brown       if (PetscDefined(USE_DEBUG)) {
608*98921bdaSJacob Faibussowitsch         for (c = 0; c < cEnd-cStart; ++c) if (tmp[c] != off[c+1]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart);
60976bd3646SJed Brown       }
61070034214SMatthew G. Knepley       ierr = PetscFree(tmp);CHKERRQ(ierr);
61170034214SMatthew G. Knepley     }
61270034214SMatthew G. Knepley     if (numVertices) *numVertices = numCells;
61370034214SMatthew G. Knepley     if (offsets)   *offsets   = off;
61470034214SMatthew G. Knepley     if (adjacency) *adjacency = adj;
61570034214SMatthew G. Knepley     PetscFunctionReturn(0);
61670034214SMatthew G. Knepley   }
61770034214SMatthew G. Knepley   /* Setup face recognition */
61870034214SMatthew G. Knepley   if (faceDepth == 1) {
61970034214SMatthew 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 */
62070034214SMatthew G. Knepley 
62170034214SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
62270034214SMatthew G. Knepley       PetscInt corners;
62370034214SMatthew G. Knepley 
62470034214SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr);
62570034214SMatthew G. Knepley       if (!cornersSeen[corners]) {
62670034214SMatthew G. Knepley         PetscInt nFV;
62770034214SMatthew G. Knepley 
62870034214SMatthew G. Knepley         if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases");
62970034214SMatthew G. Knepley         cornersSeen[corners] = 1;
63070034214SMatthew G. Knepley 
63170034214SMatthew G. Knepley         ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr);
63270034214SMatthew G. Knepley 
63370034214SMatthew G. Knepley         numFaceVertices[numFaceCases++] = nFV;
63470034214SMatthew G. Knepley       }
63570034214SMatthew G. Knepley     }
63670034214SMatthew G. Knepley   }
63770034214SMatthew G. Knepley   ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr);
63870034214SMatthew G. Knepley   /* Count neighboring cells */
63970034214SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
64070034214SMatthew G. Knepley     PetscInt numNeighbors = PETSC_DETERMINE, n;
64170034214SMatthew G. Knepley 
6428b0b4c70SToby Isaac     ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr);
64370034214SMatthew G. Knepley     /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
64470034214SMatthew G. Knepley     for (n = 0; n < numNeighbors; ++n) {
64570034214SMatthew G. Knepley       PetscInt        cellPair[2];
64670034214SMatthew G. Knepley       PetscBool       found    = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
64770034214SMatthew G. Knepley       PetscInt        meetSize = 0;
64870034214SMatthew G. Knepley       const PetscInt *meet    = NULL;
64970034214SMatthew G. Knepley 
65070034214SMatthew G. Knepley       cellPair[0] = cell; cellPair[1] = neighborCells[n];
65170034214SMatthew G. Knepley       if (cellPair[0] == cellPair[1]) continue;
65270034214SMatthew G. Knepley       if (!found) {
65370034214SMatthew G. Knepley         ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
65470034214SMatthew G. Knepley         if (meetSize) {
65570034214SMatthew G. Knepley           PetscInt f;
65670034214SMatthew G. Knepley 
65770034214SMatthew G. Knepley           for (f = 0; f < numFaceCases; ++f) {
65870034214SMatthew G. Knepley             if (numFaceVertices[f] == meetSize) {
65970034214SMatthew G. Knepley               found = PETSC_TRUE;
66070034214SMatthew G. Knepley               break;
66170034214SMatthew G. Knepley             }
66270034214SMatthew G. Knepley           }
66370034214SMatthew G. Knepley         }
66470034214SMatthew G. Knepley         ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
66570034214SMatthew G. Knepley       }
66670034214SMatthew G. Knepley       if (found) ++off[cell-cStart+1];
66770034214SMatthew G. Knepley     }
66870034214SMatthew G. Knepley   }
66970034214SMatthew G. Knepley   /* Prefix sum */
67070034214SMatthew G. Knepley   for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1];
67170034214SMatthew G. Knepley 
67270034214SMatthew G. Knepley   if (adjacency) {
67370034214SMatthew G. Knepley     ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr);
67470034214SMatthew G. Knepley     /* Get neighboring cells */
67570034214SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
67670034214SMatthew G. Knepley       PetscInt numNeighbors = PETSC_DETERMINE, n;
67770034214SMatthew G. Knepley       PetscInt cellOffset   = 0;
67870034214SMatthew G. Knepley 
6798b0b4c70SToby Isaac       ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr);
68070034214SMatthew G. Knepley       /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
68170034214SMatthew G. Knepley       for (n = 0; n < numNeighbors; ++n) {
68270034214SMatthew G. Knepley         PetscInt        cellPair[2];
68370034214SMatthew G. Knepley         PetscBool       found    = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
68470034214SMatthew G. Knepley         PetscInt        meetSize = 0;
68570034214SMatthew G. Knepley         const PetscInt *meet    = NULL;
68670034214SMatthew G. Knepley 
68770034214SMatthew G. Knepley         cellPair[0] = cell; cellPair[1] = neighborCells[n];
68870034214SMatthew G. Knepley         if (cellPair[0] == cellPair[1]) continue;
68970034214SMatthew G. Knepley         if (!found) {
69070034214SMatthew G. Knepley           ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
69170034214SMatthew G. Knepley           if (meetSize) {
69270034214SMatthew G. Knepley             PetscInt f;
69370034214SMatthew G. Knepley 
69470034214SMatthew G. Knepley             for (f = 0; f < numFaceCases; ++f) {
69570034214SMatthew G. Knepley               if (numFaceVertices[f] == meetSize) {
69670034214SMatthew G. Knepley                 found = PETSC_TRUE;
69770034214SMatthew G. Knepley                 break;
69870034214SMatthew G. Knepley               }
69970034214SMatthew G. Knepley             }
70070034214SMatthew G. Knepley           }
70170034214SMatthew G. Knepley           ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
70270034214SMatthew G. Knepley         }
70370034214SMatthew G. Knepley         if (found) {
70470034214SMatthew G. Knepley           adj[off[cell-cStart]+cellOffset] = neighborCells[n];
70570034214SMatthew G. Knepley           ++cellOffset;
70670034214SMatthew G. Knepley         }
70770034214SMatthew G. Knepley       }
70870034214SMatthew G. Knepley     }
70970034214SMatthew G. Knepley   }
71070034214SMatthew G. Knepley   ierr = PetscFree(neighborCells);CHKERRQ(ierr);
71170034214SMatthew G. Knepley   if (numVertices) *numVertices = numCells;
71270034214SMatthew G. Knepley   if (offsets)   *offsets   = off;
71370034214SMatthew G. Knepley   if (adjacency) *adjacency = adj;
71470034214SMatthew G. Knepley   PetscFunctionReturn(0);
71570034214SMatthew G. Knepley }
71670034214SMatthew G. Knepley 
71777623264SMatthew G. Knepley /*@
7183c41b853SStefano Zampini   PetscPartitionerDMPlexPartition - Create a non-overlapping partition of the cells in the mesh
71977623264SMatthew G. Knepley 
720fe2efc57SMark   Collective on PetscPartitioner
72177623264SMatthew G. Knepley 
72277623264SMatthew G. Knepley   Input Parameters:
72377623264SMatthew G. Knepley + part    - The PetscPartitioner
7243c41b853SStefano Zampini . targetSection - The PetscSection describing the absolute weight of each partition (can be NULL)
725f8987ae8SMichael Lange - dm      - The mesh DM
72677623264SMatthew G. Knepley 
72777623264SMatthew G. Knepley   Output Parameters:
72877623264SMatthew G. Knepley + partSection     - The PetscSection giving the division of points by partition
729f8987ae8SMichael Lange - partition       - The list of points by partition
73077623264SMatthew G. Knepley 
7313c41b853SStefano Zampini   Notes:
7323c41b853SStefano Zampini     If the DM has a local section associated, each point to be partitioned will be weighted by the total number of dofs identified
7333c41b853SStefano Zampini     by the section in the transitive closure of the point.
73477623264SMatthew G. Knepley 
73577623264SMatthew G. Knepley   Level: developer
73677623264SMatthew G. Knepley 
7373c41b853SStefano Zampini .seealso DMPlexDistribute(), PetscPartitionerCreate(), PetscSectionCreate(), PetscSectionSetChart(), PetscPartitionerPartition()
7384b15ede2SMatthew G. Knepley @*/
7393c41b853SStefano Zampini PetscErrorCode PetscPartitionerDMPlexPartition(PetscPartitioner part, DM dm, PetscSection targetSection, PetscSection partSection, IS *partition)
74077623264SMatthew G. Knepley {
74177623264SMatthew G. Knepley   PetscMPIInt    size;
7423c41b853SStefano Zampini   PetscBool      isplex;
74377623264SMatthew G. Knepley   PetscErrorCode ierr;
7443c41b853SStefano Zampini   PetscSection   vertSection = NULL;
74577623264SMatthew G. Knepley 
74677623264SMatthew G. Knepley   PetscFunctionBegin;
74777623264SMatthew G. Knepley   PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
74877623264SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
7493c41b853SStefano Zampini   if (targetSection) PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 3);
75077623264SMatthew G. Knepley   PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 4);
75177623264SMatthew G. Knepley   PetscValidPointer(partition, 5);
7523c41b853SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isplex);CHKERRQ(ierr);
753*98921bdaSJacob Faibussowitsch   if (!isplex) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not for type %s",((PetscObject)dm)->type_name);
754ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);CHKERRMPI(ierr);
75577623264SMatthew G. Knepley   if (size == 1) {
75677623264SMatthew G. Knepley     PetscInt *points;
75777623264SMatthew G. Knepley     PetscInt  cStart, cEnd, c;
75877623264SMatthew G. Knepley 
75977623264SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr);
7603c41b853SStefano Zampini     ierr = PetscSectionReset(partSection);CHKERRQ(ierr);
76177623264SMatthew G. Knepley     ierr = PetscSectionSetChart(partSection, 0, size);CHKERRQ(ierr);
76277623264SMatthew G. Knepley     ierr = PetscSectionSetDof(partSection, 0, cEnd-cStart);CHKERRQ(ierr);
76377623264SMatthew G. Knepley     ierr = PetscSectionSetUp(partSection);CHKERRQ(ierr);
76477623264SMatthew G. Knepley     ierr = PetscMalloc1(cEnd-cStart, &points);CHKERRQ(ierr);
76577623264SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) points[c] = c;
76677623264SMatthew G. Knepley     ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
76777623264SMatthew G. Knepley     PetscFunctionReturn(0);
76877623264SMatthew G. Knepley   }
76977623264SMatthew G. Knepley   if (part->height == 0) {
770074d466cSStefano Zampini     PetscInt numVertices = 0;
77177623264SMatthew G. Knepley     PetscInt *start     = NULL;
77277623264SMatthew G. Knepley     PetscInt *adjacency = NULL;
7733fa7752dSToby Isaac     IS       globalNumbering;
77477623264SMatthew G. Knepley 
775074d466cSStefano Zampini     if (!part->noGraph || part->viewGraph) {
776074d466cSStefano Zampini       ierr = DMPlexCreatePartitionerGraph(dm, part->height, &numVertices, &start, &adjacency, &globalNumbering);CHKERRQ(ierr);
77713911537SStefano Zampini     } else { /* only compute the number of owned local vertices */
778074d466cSStefano Zampini       const PetscInt *idxs;
779074d466cSStefano Zampini       PetscInt       p, pStart, pEnd;
780074d466cSStefano Zampini 
781074d466cSStefano Zampini       ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr);
7829886b8cfSStefano Zampini       ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, 0, NULL, dm->sf, &globalNumbering);CHKERRQ(ierr);
783074d466cSStefano Zampini       ierr = ISGetIndices(globalNumbering, &idxs);CHKERRQ(ierr);
784074d466cSStefano Zampini       for (p = 0; p < pEnd - pStart; p++) numVertices += idxs[p] < 0 ? 0 : 1;
785074d466cSStefano Zampini       ierr = ISRestoreIndices(globalNumbering, &idxs);CHKERRQ(ierr);
786074d466cSStefano Zampini     }
7873c41b853SStefano Zampini     if (part->usevwgt) {
7883c41b853SStefano Zampini       PetscSection   section = dm->localSection, clSection = NULL;
7893c41b853SStefano Zampini       IS             clPoints = NULL;
7903c41b853SStefano Zampini       const PetscInt *gid,*clIdx;
7913c41b853SStefano Zampini       PetscInt       v, p, pStart, pEnd;
7920358368aSMatthew G. Knepley 
7933c41b853SStefano Zampini       /* dm->localSection encodes degrees of freedom per point, not per cell. We need to get the closure index to properly specify cell weights (aka dofs) */
7943c41b853SStefano Zampini       /* We do this only if the local section has been set */
7953c41b853SStefano Zampini       if (section) {
7963c41b853SStefano Zampini         ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, NULL);CHKERRQ(ierr);
7973c41b853SStefano Zampini         if (!clSection) {
7983c41b853SStefano Zampini           ierr = DMPlexCreateClosureIndex(dm,NULL);CHKERRQ(ierr);
7993c41b853SStefano Zampini         }
8003c41b853SStefano Zampini         ierr = PetscSectionGetClosureIndex(section, (PetscObject)dm, &clSection, &clPoints);CHKERRQ(ierr);
8013c41b853SStefano Zampini         ierr = ISGetIndices(clPoints,&clIdx);CHKERRQ(ierr);
8023c41b853SStefano Zampini       }
8033c41b853SStefano Zampini       ierr = DMPlexGetHeightStratum(dm, part->height, &pStart, &pEnd);CHKERRQ(ierr);
8043c41b853SStefano Zampini       ierr = PetscSectionCreate(PETSC_COMM_SELF, &vertSection);CHKERRQ(ierr);
8053c41b853SStefano Zampini       ierr = PetscSectionSetChart(vertSection, 0, numVertices);CHKERRQ(ierr);
8063c41b853SStefano Zampini       if (globalNumbering) {
8073c41b853SStefano Zampini         ierr = ISGetIndices(globalNumbering,&gid);CHKERRQ(ierr);
8083c41b853SStefano Zampini       } else gid = NULL;
8093c41b853SStefano Zampini       for (p = pStart, v = 0; p < pEnd; ++p) {
8103c41b853SStefano Zampini         PetscInt dof = 1;
8110358368aSMatthew G. Knepley 
8123c41b853SStefano Zampini         /* skip cells in the overlap */
8133c41b853SStefano Zampini         if (gid && gid[p-pStart] < 0) continue;
8143c41b853SStefano Zampini 
8153c41b853SStefano Zampini         if (section) {
8163c41b853SStefano Zampini           PetscInt cl, clSize, clOff;
8173c41b853SStefano Zampini 
8183c41b853SStefano Zampini           dof  = 0;
8193c41b853SStefano Zampini           ierr = PetscSectionGetDof(clSection, p, &clSize);CHKERRQ(ierr);
8203c41b853SStefano Zampini           ierr = PetscSectionGetOffset(clSection, p, &clOff);CHKERRQ(ierr);
8213c41b853SStefano Zampini           for (cl = 0; cl < clSize; cl+=2) {
8223c41b853SStefano Zampini             PetscInt clDof, clPoint = clIdx[clOff + cl]; /* odd indices are reserved for orientations */
8233c41b853SStefano Zampini 
8243c41b853SStefano Zampini             ierr = PetscSectionGetDof(section, clPoint, &clDof);CHKERRQ(ierr);
8253c41b853SStefano Zampini             dof += clDof;
8260358368aSMatthew G. Knepley           }
8270358368aSMatthew G. Knepley         }
828*98921bdaSJacob Faibussowitsch         if (!dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of dofs for point %D in the local section should be positive",p);
8293c41b853SStefano Zampini         ierr = PetscSectionSetDof(vertSection, v, dof);CHKERRQ(ierr);
8303c41b853SStefano Zampini         v++;
8313c41b853SStefano Zampini       }
8323c41b853SStefano Zampini       if (globalNumbering) {
8333c41b853SStefano Zampini         ierr = ISRestoreIndices(globalNumbering,&gid);CHKERRQ(ierr);
8343c41b853SStefano Zampini       }
8353c41b853SStefano Zampini       if (clPoints) {
8363c41b853SStefano Zampini         ierr = ISRestoreIndices(clPoints,&clIdx);CHKERRQ(ierr);
8373c41b853SStefano Zampini       }
8383c41b853SStefano Zampini       ierr = PetscSectionSetUp(vertSection);CHKERRQ(ierr);
8393c41b853SStefano Zampini     }
8403c41b853SStefano Zampini     ierr = PetscPartitionerPartition(part, size, numVertices, start, adjacency, vertSection, targetSection, partSection, partition);CHKERRQ(ierr);
84177623264SMatthew G. Knepley     ierr = PetscFree(start);CHKERRQ(ierr);
84277623264SMatthew G. Knepley     ierr = PetscFree(adjacency);CHKERRQ(ierr);
8433fa7752dSToby Isaac     if (globalNumbering) { /* partition is wrt global unique numbering: change this to be wrt local numbering */
8443fa7752dSToby Isaac       const PetscInt *globalNum;
8453fa7752dSToby Isaac       const PetscInt *partIdx;
8463fa7752dSToby Isaac       PetscInt       *map, cStart, cEnd;
8473fa7752dSToby Isaac       PetscInt       *adjusted, i, localSize, offset;
8483fa7752dSToby Isaac       IS             newPartition;
8493fa7752dSToby Isaac 
8503fa7752dSToby Isaac       ierr = ISGetLocalSize(*partition,&localSize);CHKERRQ(ierr);
8513fa7752dSToby Isaac       ierr = PetscMalloc1(localSize,&adjusted);CHKERRQ(ierr);
8523fa7752dSToby Isaac       ierr = ISGetIndices(globalNumbering,&globalNum);CHKERRQ(ierr);
8533fa7752dSToby Isaac       ierr = ISGetIndices(*partition,&partIdx);CHKERRQ(ierr);
8543fa7752dSToby Isaac       ierr = PetscMalloc1(localSize,&map);CHKERRQ(ierr);
8553fa7752dSToby Isaac       ierr = DMPlexGetHeightStratum(dm, part->height, &cStart, &cEnd);CHKERRQ(ierr);
8563fa7752dSToby Isaac       for (i = cStart, offset = 0; i < cEnd; i++) {
8573fa7752dSToby Isaac         if (globalNum[i - cStart] >= 0) map[offset++] = i;
8583fa7752dSToby Isaac       }
8593fa7752dSToby Isaac       for (i = 0; i < localSize; i++) {
8603fa7752dSToby Isaac         adjusted[i] = map[partIdx[i]];
8613fa7752dSToby Isaac       }
8623fa7752dSToby Isaac       ierr = PetscFree(map);CHKERRQ(ierr);
8633fa7752dSToby Isaac       ierr = ISRestoreIndices(*partition,&partIdx);CHKERRQ(ierr);
8643fa7752dSToby Isaac       ierr = ISRestoreIndices(globalNumbering,&globalNum);CHKERRQ(ierr);
8653fa7752dSToby Isaac       ierr = ISCreateGeneral(PETSC_COMM_SELF,localSize,adjusted,PETSC_OWN_POINTER,&newPartition);CHKERRQ(ierr);
8663fa7752dSToby Isaac       ierr = ISDestroy(&globalNumbering);CHKERRQ(ierr);
8673fa7752dSToby Isaac       ierr = ISDestroy(partition);CHKERRQ(ierr);
8683fa7752dSToby Isaac       *partition = newPartition;
8693fa7752dSToby Isaac     }
870*98921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Invalid height %D for points to partition", part->height);
8713c41b853SStefano Zampini   ierr = PetscSectionDestroy(&vertSection);CHKERRQ(ierr);
87277623264SMatthew G. Knepley   PetscFunctionReturn(0);
87377623264SMatthew G. Knepley }
87477623264SMatthew G. Knepley 
8755680f57bSMatthew G. Knepley /*@
8765680f57bSMatthew G. Knepley   DMPlexGetPartitioner - Get the mesh partitioner
8775680f57bSMatthew G. Knepley 
8785680f57bSMatthew G. Knepley   Not collective
8795680f57bSMatthew G. Knepley 
8805680f57bSMatthew G. Knepley   Input Parameter:
8815680f57bSMatthew G. Knepley . dm - The DM
8825680f57bSMatthew G. Knepley 
8835680f57bSMatthew G. Knepley   Output Parameter:
8845680f57bSMatthew G. Knepley . part - The PetscPartitioner
8855680f57bSMatthew G. Knepley 
8865680f57bSMatthew G. Knepley   Level: developer
8875680f57bSMatthew G. Knepley 
88898599a47SLawrence Mitchell   Note: This gets a borrowed reference, so the user should not destroy this PetscPartitioner.
88998599a47SLawrence Mitchell 
8903c41b853SStefano Zampini .seealso DMPlexDistribute(), DMPlexSetPartitioner(), PetscPartitionerDMPlexPartition(), PetscPartitionerCreate()
8915680f57bSMatthew G. Knepley @*/
8925680f57bSMatthew G. Knepley PetscErrorCode DMPlexGetPartitioner(DM dm, PetscPartitioner *part)
8935680f57bSMatthew G. Knepley {
8945680f57bSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *) dm->data;
8955680f57bSMatthew G. Knepley 
8965680f57bSMatthew G. Knepley   PetscFunctionBegin;
8975680f57bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8985680f57bSMatthew G. Knepley   PetscValidPointer(part, 2);
8995680f57bSMatthew G. Knepley   *part = mesh->partitioner;
9005680f57bSMatthew G. Knepley   PetscFunctionReturn(0);
9015680f57bSMatthew G. Knepley }
9025680f57bSMatthew G. Knepley 
90371bb2955SLawrence Mitchell /*@
90471bb2955SLawrence Mitchell   DMPlexSetPartitioner - Set the mesh partitioner
90571bb2955SLawrence Mitchell 
906fe2efc57SMark   logically collective on DM
90771bb2955SLawrence Mitchell 
90871bb2955SLawrence Mitchell   Input Parameters:
90971bb2955SLawrence Mitchell + dm - The DM
91071bb2955SLawrence Mitchell - part - The partitioner
91171bb2955SLawrence Mitchell 
91271bb2955SLawrence Mitchell   Level: developer
91371bb2955SLawrence Mitchell 
91471bb2955SLawrence Mitchell   Note: Any existing PetscPartitioner will be destroyed.
91571bb2955SLawrence Mitchell 
91671bb2955SLawrence Mitchell .seealso DMPlexDistribute(), DMPlexGetPartitioner(), PetscPartitionerCreate()
91771bb2955SLawrence Mitchell @*/
91871bb2955SLawrence Mitchell PetscErrorCode DMPlexSetPartitioner(DM dm, PetscPartitioner part)
91971bb2955SLawrence Mitchell {
92071bb2955SLawrence Mitchell   DM_Plex       *mesh = (DM_Plex *) dm->data;
92171bb2955SLawrence Mitchell   PetscErrorCode ierr;
92271bb2955SLawrence Mitchell 
92371bb2955SLawrence Mitchell   PetscFunctionBegin;
92471bb2955SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92571bb2955SLawrence Mitchell   PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 2);
92671bb2955SLawrence Mitchell   ierr = PetscObjectReference((PetscObject)part);CHKERRQ(ierr);
92771bb2955SLawrence Mitchell   ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr);
92871bb2955SLawrence Mitchell   mesh->partitioner = part;
92971bb2955SLawrence Mitchell   PetscFunctionReturn(0);
93071bb2955SLawrence Mitchell }
93171bb2955SLawrence Mitchell 
9328e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosure_Private(DM dm, PetscHSetI ht, PetscInt point)
9338e330a33SStefano Zampini {
9348e330a33SStefano Zampini   const PetscInt *cone;
9358e330a33SStefano Zampini   PetscInt       coneSize, c;
9368e330a33SStefano Zampini   PetscBool      missing;
9378e330a33SStefano Zampini   PetscErrorCode ierr;
9388e330a33SStefano Zampini 
9398e330a33SStefano Zampini   PetscFunctionBeginHot;
9408e330a33SStefano Zampini   ierr = PetscHSetIQueryAdd(ht, point, &missing);CHKERRQ(ierr);
9418e330a33SStefano Zampini   if (missing) {
9428e330a33SStefano Zampini     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
9438e330a33SStefano Zampini     ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
9448e330a33SStefano Zampini     for (c = 0; c < coneSize; c++) {
9458e330a33SStefano Zampini       ierr = DMPlexAddClosure_Private(dm, ht, cone[c]);CHKERRQ(ierr);
9468e330a33SStefano Zampini     }
9478e330a33SStefano Zampini   }
9488e330a33SStefano Zampini   PetscFunctionReturn(0);
9498e330a33SStefano Zampini }
9508e330a33SStefano Zampini 
9518e330a33SStefano Zampini PETSC_UNUSED static PetscErrorCode DMPlexAddClosure_Tree(DM dm, PetscHSetI ht, PetscInt point, PetscBool up, PetscBool down)
952270bba0cSToby Isaac {
953270bba0cSToby Isaac   PetscErrorCode ierr;
954270bba0cSToby Isaac 
955270bba0cSToby Isaac   PetscFunctionBegin;
9566a5a2ffdSToby Isaac   if (up) {
9576a5a2ffdSToby Isaac     PetscInt parent;
9586a5a2ffdSToby Isaac 
959270bba0cSToby Isaac     ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr);
9606a5a2ffdSToby Isaac     if (parent != point) {
9616a5a2ffdSToby Isaac       PetscInt closureSize, *closure = NULL, i;
9626a5a2ffdSToby Isaac 
963270bba0cSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
964270bba0cSToby Isaac       for (i = 0; i < closureSize; i++) {
965270bba0cSToby Isaac         PetscInt cpoint = closure[2*i];
966270bba0cSToby Isaac 
967e8f14785SLisandro Dalcin         ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr);
9681b807c88SLisandro Dalcin         ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
969270bba0cSToby Isaac       }
970270bba0cSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
9716a5a2ffdSToby Isaac     }
9726a5a2ffdSToby Isaac   }
9736a5a2ffdSToby Isaac   if (down) {
9746a5a2ffdSToby Isaac     PetscInt numChildren;
9756a5a2ffdSToby Isaac     const PetscInt *children;
9766a5a2ffdSToby Isaac 
9776a5a2ffdSToby Isaac     ierr = DMPlexGetTreeChildren(dm,point,&numChildren,&children);CHKERRQ(ierr);
9786a5a2ffdSToby Isaac     if (numChildren) {
9796a5a2ffdSToby Isaac       PetscInt i;
9806a5a2ffdSToby Isaac 
9816a5a2ffdSToby Isaac       for (i = 0; i < numChildren; i++) {
9826a5a2ffdSToby Isaac         PetscInt cpoint = children[i];
9836a5a2ffdSToby Isaac 
984e8f14785SLisandro Dalcin         ierr = PetscHSetIAdd(ht, cpoint);CHKERRQ(ierr);
9851b807c88SLisandro Dalcin         ierr = DMPlexAddClosure_Tree(dm,ht,cpoint,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
9866a5a2ffdSToby Isaac       }
9876a5a2ffdSToby Isaac     }
9886a5a2ffdSToby Isaac   }
989270bba0cSToby Isaac   PetscFunctionReturn(0);
990270bba0cSToby Isaac }
991270bba0cSToby Isaac 
9928e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Up_Private(DM dm, PetscHSetI ht, PetscInt point)
9938e330a33SStefano Zampini {
9948e330a33SStefano Zampini   PetscInt       parent;
9958e330a33SStefano Zampini   PetscErrorCode ierr;
996825f8a23SLisandro Dalcin 
9978e330a33SStefano Zampini   PetscFunctionBeginHot;
9988e330a33SStefano Zampini   ierr = DMPlexGetTreeParent(dm, point, &parent,NULL);CHKERRQ(ierr);
9998e330a33SStefano Zampini   if (point != parent) {
10008e330a33SStefano Zampini     const PetscInt *cone;
10018e330a33SStefano Zampini     PetscInt       coneSize, c;
10028e330a33SStefano Zampini 
10038e330a33SStefano Zampini     ierr = DMPlexAddClosureTree_Up_Private(dm, ht, parent);CHKERRQ(ierr);
10048e330a33SStefano Zampini     ierr = DMPlexAddClosure_Private(dm, ht, parent);CHKERRQ(ierr);
10058e330a33SStefano Zampini     ierr = DMPlexGetCone(dm, parent, &cone);CHKERRQ(ierr);
10068e330a33SStefano Zampini     ierr = DMPlexGetConeSize(dm, parent, &coneSize);CHKERRQ(ierr);
10078e330a33SStefano Zampini     for (c = 0; c < coneSize; c++) {
10088e330a33SStefano Zampini       const PetscInt cp = cone[c];
10098e330a33SStefano Zampini 
10108e330a33SStefano Zampini       ierr = DMPlexAddClosureTree_Up_Private(dm, ht, cp);CHKERRQ(ierr);
10118e330a33SStefano Zampini     }
10128e330a33SStefano Zampini   }
10138e330a33SStefano Zampini   PetscFunctionReturn(0);
10148e330a33SStefano Zampini }
10158e330a33SStefano Zampini 
10168e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Down_Private(DM dm, PetscHSetI ht, PetscInt point)
10178e330a33SStefano Zampini {
10188e330a33SStefano Zampini   PetscInt       i, numChildren;
10198e330a33SStefano Zampini   const PetscInt *children;
10208e330a33SStefano Zampini   PetscErrorCode ierr;
10218e330a33SStefano Zampini 
10228e330a33SStefano Zampini   PetscFunctionBeginHot;
10238e330a33SStefano Zampini   ierr = DMPlexGetTreeChildren(dm, point, &numChildren, &children);CHKERRQ(ierr);
10248e330a33SStefano Zampini   for (i = 0; i < numChildren; i++) {
10258e330a33SStefano Zampini     ierr = PetscHSetIAdd(ht, children[i]);CHKERRQ(ierr);
10268e330a33SStefano Zampini   }
10278e330a33SStefano Zampini   PetscFunctionReturn(0);
10288e330a33SStefano Zampini }
10298e330a33SStefano Zampini 
10308e330a33SStefano Zampini static PetscErrorCode DMPlexAddClosureTree_Private(DM dm, PetscHSetI ht, PetscInt point)
10318e330a33SStefano Zampini {
10328e330a33SStefano Zampini   const PetscInt *cone;
10338e330a33SStefano Zampini   PetscInt       coneSize, c;
10348e330a33SStefano Zampini   PetscErrorCode ierr;
10358e330a33SStefano Zampini 
10368e330a33SStefano Zampini   PetscFunctionBeginHot;
10378e330a33SStefano Zampini   ierr = PetscHSetIAdd(ht, point);CHKERRQ(ierr);
10388e330a33SStefano Zampini   ierr = DMPlexAddClosureTree_Up_Private(dm, ht, point);CHKERRQ(ierr);
10398e330a33SStefano Zampini   ierr = DMPlexAddClosureTree_Down_Private(dm, ht, point);CHKERRQ(ierr);
10408e330a33SStefano Zampini   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
10418e330a33SStefano Zampini   ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
10428e330a33SStefano Zampini   for (c = 0; c < coneSize; c++) {
10438e330a33SStefano Zampini     ierr = DMPlexAddClosureTree_Private(dm, ht, cone[c]);CHKERRQ(ierr);
10448e330a33SStefano Zampini   }
10458e330a33SStefano Zampini   PetscFunctionReturn(0);
10468e330a33SStefano Zampini }
10478e330a33SStefano Zampini 
10488e330a33SStefano Zampini PetscErrorCode DMPlexClosurePoints_Private(DM dm, PetscInt numPoints, const PetscInt points[], IS *closureIS)
1049825f8a23SLisandro Dalcin {
1050825f8a23SLisandro Dalcin   DM_Plex         *mesh = (DM_Plex *)dm->data;
10518e330a33SStefano Zampini   const PetscBool hasTree = (mesh->parentSection || mesh->childSection) ? PETSC_TRUE : PETSC_FALSE;
10528e330a33SStefano Zampini   PetscInt        nelems, *elems, off = 0, p;
105327104ee2SJacob Faibussowitsch   PetscHSetI      ht = NULL;
1054825f8a23SLisandro Dalcin   PetscErrorCode  ierr;
1055825f8a23SLisandro Dalcin 
1056825f8a23SLisandro Dalcin   PetscFunctionBegin;
1057825f8a23SLisandro Dalcin   ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
1058825f8a23SLisandro Dalcin   ierr = PetscHSetIResize(ht, numPoints*16);CHKERRQ(ierr);
10598e330a33SStefano Zampini   if (!hasTree) {
10608e330a33SStefano Zampini     for (p = 0; p < numPoints; ++p) {
10618e330a33SStefano Zampini       ierr = DMPlexAddClosure_Private(dm, ht, points[p]);CHKERRQ(ierr);
10628e330a33SStefano Zampini     }
10638e330a33SStefano Zampini   } else {
10648e330a33SStefano Zampini #if 1
10658e330a33SStefano Zampini     for (p = 0; p < numPoints; ++p) {
10668e330a33SStefano Zampini       ierr = DMPlexAddClosureTree_Private(dm, ht, points[p]);CHKERRQ(ierr);
10678e330a33SStefano Zampini     }
10688e330a33SStefano Zampini #else
10698e330a33SStefano Zampini     PetscInt  *closure = NULL, closureSize, c;
1070825f8a23SLisandro Dalcin     for (p = 0; p < numPoints; ++p) {
1071825f8a23SLisandro Dalcin       ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
1072825f8a23SLisandro Dalcin       for (c = 0; c < closureSize*2; c += 2) {
1073825f8a23SLisandro Dalcin         ierr = PetscHSetIAdd(ht, closure[c]);CHKERRQ(ierr);
1074825f8a23SLisandro Dalcin         if (hasTree) {ierr = DMPlexAddClosure_Tree(dm, ht, closure[c], PETSC_TRUE, PETSC_TRUE);CHKERRQ(ierr);}
1075825f8a23SLisandro Dalcin       }
1076825f8a23SLisandro Dalcin     }
1077825f8a23SLisandro Dalcin     if (closure) {ierr = DMPlexRestoreTransitiveClosure(dm, 0, PETSC_TRUE, NULL, &closure);CHKERRQ(ierr);}
10788e330a33SStefano Zampini #endif
10798e330a33SStefano Zampini   }
1080825f8a23SLisandro Dalcin   ierr = PetscHSetIGetSize(ht, &nelems);CHKERRQ(ierr);
1081825f8a23SLisandro Dalcin   ierr = PetscMalloc1(nelems, &elems);CHKERRQ(ierr);
1082825f8a23SLisandro Dalcin   ierr = PetscHSetIGetElems(ht, &off, elems);CHKERRQ(ierr);
1083825f8a23SLisandro Dalcin   ierr = PetscHSetIDestroy(&ht);CHKERRQ(ierr);
1084825f8a23SLisandro Dalcin   ierr = PetscSortInt(nelems, elems);CHKERRQ(ierr);
1085825f8a23SLisandro Dalcin   ierr = ISCreateGeneral(PETSC_COMM_SELF, nelems, elems, PETSC_OWN_POINTER, closureIS);CHKERRQ(ierr);
1086825f8a23SLisandro Dalcin   PetscFunctionReturn(0);
1087825f8a23SLisandro Dalcin }
1088825f8a23SLisandro Dalcin 
10895abbe4feSMichael Lange /*@
10905abbe4feSMichael Lange   DMPlexPartitionLabelClosure - Add the closure of all points to the partition label
10915abbe4feSMichael Lange 
10925abbe4feSMichael Lange   Input Parameters:
10935abbe4feSMichael Lange + dm     - The DM
1094a5b23f4aSJose E. Roman - label  - DMLabel assigning ranks to remote roots
10955abbe4feSMichael Lange 
10965abbe4feSMichael Lange   Level: developer
10975abbe4feSMichael Lange 
109830b0ce1bSStefano Zampini .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap()
10995abbe4feSMichael Lange @*/
11005abbe4feSMichael Lange PetscErrorCode DMPlexPartitionLabelClosure(DM dm, DMLabel label)
11019ffc88e4SToby Isaac {
1102825f8a23SLisandro Dalcin   IS              rankIS,   pointIS, closureIS;
11035abbe4feSMichael Lange   const PetscInt *ranks,   *points;
1104825f8a23SLisandro Dalcin   PetscInt        numRanks, numPoints, r;
11059ffc88e4SToby Isaac   PetscErrorCode  ierr;
11069ffc88e4SToby Isaac 
11079ffc88e4SToby Isaac   PetscFunctionBegin;
11085abbe4feSMichael Lange   ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr);
11095abbe4feSMichael Lange   ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr);
11105abbe4feSMichael Lange   ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr);
11115abbe4feSMichael Lange   for (r = 0; r < numRanks; ++r) {
11125abbe4feSMichael Lange     const PetscInt rank = ranks[r];
11135abbe4feSMichael Lange     ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr);
11145abbe4feSMichael Lange     ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
11155abbe4feSMichael Lange     ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
11168e330a33SStefano Zampini     ierr = DMPlexClosurePoints_Private(dm, numPoints, points, &closureIS);CHKERRQ(ierr);
11175abbe4feSMichael Lange     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
11185abbe4feSMichael Lange     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1119825f8a23SLisandro Dalcin     ierr = DMLabelSetStratumIS(label, rank, closureIS);CHKERRQ(ierr);
1120825f8a23SLisandro Dalcin     ierr = ISDestroy(&closureIS);CHKERRQ(ierr);
11219ffc88e4SToby Isaac   }
11225abbe4feSMichael Lange   ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr);
11235abbe4feSMichael Lange   ierr = ISDestroy(&rankIS);CHKERRQ(ierr);
11249ffc88e4SToby Isaac   PetscFunctionReturn(0);
11259ffc88e4SToby Isaac }
11269ffc88e4SToby Isaac 
112724d039d7SMichael Lange /*@
112824d039d7SMichael Lange   DMPlexPartitionLabelAdjacency - Add one level of adjacent points to the partition label
112924d039d7SMichael Lange 
113024d039d7SMichael Lange   Input Parameters:
113124d039d7SMichael Lange + dm     - The DM
1132a5b23f4aSJose E. Roman - label  - DMLabel assigning ranks to remote roots
113324d039d7SMichael Lange 
113424d039d7SMichael Lange   Level: developer
113524d039d7SMichael Lange 
11362d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap()
113724d039d7SMichael Lange @*/
113824d039d7SMichael Lange PetscErrorCode DMPlexPartitionLabelAdjacency(DM dm, DMLabel label)
113970034214SMatthew G. Knepley {
114024d039d7SMichael Lange   IS              rankIS,   pointIS;
114124d039d7SMichael Lange   const PetscInt *ranks,   *points;
114224d039d7SMichael Lange   PetscInt        numRanks, numPoints, r, p, a, adjSize;
114324d039d7SMichael Lange   PetscInt       *adj = NULL;
114470034214SMatthew G. Knepley   PetscErrorCode  ierr;
114570034214SMatthew G. Knepley 
114670034214SMatthew G. Knepley   PetscFunctionBegin;
114724d039d7SMichael Lange   ierr = DMLabelGetValueIS(label, &rankIS);CHKERRQ(ierr);
114824d039d7SMichael Lange   ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr);
114924d039d7SMichael Lange   ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr);
115024d039d7SMichael Lange   for (r = 0; r < numRanks; ++r) {
115124d039d7SMichael Lange     const PetscInt rank = ranks[r];
115270034214SMatthew G. Knepley 
115324d039d7SMichael Lange     ierr = DMLabelGetStratumIS(label, rank, &pointIS);CHKERRQ(ierr);
115424d039d7SMichael Lange     ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
115524d039d7SMichael Lange     ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
115670034214SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
115724d039d7SMichael Lange       adjSize = PETSC_DETERMINE;
115824d039d7SMichael Lange       ierr = DMPlexGetAdjacency(dm, points[p], &adjSize, &adj);CHKERRQ(ierr);
115924d039d7SMichael Lange       for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(label, adj[a], rank);CHKERRQ(ierr);}
116070034214SMatthew G. Knepley     }
116124d039d7SMichael Lange     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
116224d039d7SMichael Lange     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
116370034214SMatthew G. Knepley   }
116424d039d7SMichael Lange   ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr);
116524d039d7SMichael Lange   ierr = ISDestroy(&rankIS);CHKERRQ(ierr);
116624d039d7SMichael Lange   ierr = PetscFree(adj);CHKERRQ(ierr);
116724d039d7SMichael Lange   PetscFunctionReturn(0);
116870034214SMatthew G. Knepley }
116970034214SMatthew G. Knepley 
1170be200f8dSMichael Lange /*@
1171be200f8dSMichael Lange   DMPlexPartitionLabelPropagate - Propagate points in a partition label over the point SF
1172be200f8dSMichael Lange 
1173be200f8dSMichael Lange   Input Parameters:
1174be200f8dSMichael Lange + dm     - The DM
1175a5b23f4aSJose E. Roman - label  - DMLabel assigning ranks to remote roots
1176be200f8dSMichael Lange 
1177be200f8dSMichael Lange   Level: developer
1178be200f8dSMichael Lange 
1179be200f8dSMichael Lange   Note: This is required when generating multi-level overlaps to capture
1180be200f8dSMichael Lange   overlap points from non-neighbouring partitions.
1181be200f8dSMichael Lange 
11822d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap()
1183be200f8dSMichael Lange @*/
1184be200f8dSMichael Lange PetscErrorCode DMPlexPartitionLabelPropagate(DM dm, DMLabel label)
1185be200f8dSMichael Lange {
1186be200f8dSMichael Lange   MPI_Comm        comm;
1187be200f8dSMichael Lange   PetscMPIInt     rank;
1188be200f8dSMichael Lange   PetscSF         sfPoint;
11895d04f6ebSMichael Lange   DMLabel         lblRoots, lblLeaves;
1190be200f8dSMichael Lange   IS              rankIS, pointIS;
1191be200f8dSMichael Lange   const PetscInt *ranks;
1192be200f8dSMichael Lange   PetscInt        numRanks, r;
1193be200f8dSMichael Lange   PetscErrorCode  ierr;
1194be200f8dSMichael Lange 
1195be200f8dSMichael Lange   PetscFunctionBegin;
1196be200f8dSMichael Lange   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1197ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1198be200f8dSMichael Lange   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
11995d04f6ebSMichael Lange   /* Pull point contributions from remote leaves into local roots */
12005d04f6ebSMichael Lange   ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr);
12015d04f6ebSMichael Lange   ierr = DMLabelGetValueIS(lblLeaves, &rankIS);CHKERRQ(ierr);
12025d04f6ebSMichael Lange   ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr);
12035d04f6ebSMichael Lange   ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr);
12045d04f6ebSMichael Lange   for (r = 0; r < numRanks; ++r) {
12055d04f6ebSMichael Lange     const PetscInt remoteRank = ranks[r];
12065d04f6ebSMichael Lange     if (remoteRank == rank) continue;
12075d04f6ebSMichael Lange     ierr = DMLabelGetStratumIS(lblLeaves, remoteRank, &pointIS);CHKERRQ(ierr);
12085d04f6ebSMichael Lange     ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr);
12095d04f6ebSMichael Lange     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
12105d04f6ebSMichael Lange   }
12115d04f6ebSMichael Lange   ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr);
12125d04f6ebSMichael Lange   ierr = ISDestroy(&rankIS);CHKERRQ(ierr);
12135d04f6ebSMichael Lange   ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr);
1214be200f8dSMichael Lange   /* Push point contributions from roots into remote leaves */
1215be200f8dSMichael Lange   ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr);
1216be200f8dSMichael Lange   ierr = DMLabelGetValueIS(lblRoots, &rankIS);CHKERRQ(ierr);
1217be200f8dSMichael Lange   ierr = ISGetLocalSize(rankIS, &numRanks);CHKERRQ(ierr);
1218be200f8dSMichael Lange   ierr = ISGetIndices(rankIS, &ranks);CHKERRQ(ierr);
1219be200f8dSMichael Lange   for (r = 0; r < numRanks; ++r) {
1220be200f8dSMichael Lange     const PetscInt remoteRank = ranks[r];
1221be200f8dSMichael Lange     if (remoteRank == rank) continue;
1222be200f8dSMichael Lange     ierr = DMLabelGetStratumIS(lblRoots, remoteRank, &pointIS);CHKERRQ(ierr);
1223be200f8dSMichael Lange     ierr = DMLabelInsertIS(label, pointIS, remoteRank);CHKERRQ(ierr);
1224be200f8dSMichael Lange     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1225be200f8dSMichael Lange   }
1226be200f8dSMichael Lange   ierr = ISRestoreIndices(rankIS, &ranks);CHKERRQ(ierr);
1227be200f8dSMichael Lange   ierr = ISDestroy(&rankIS);CHKERRQ(ierr);
1228be200f8dSMichael Lange   ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr);
1229be200f8dSMichael Lange   PetscFunctionReturn(0);
1230be200f8dSMichael Lange }
1231be200f8dSMichael Lange 
12321fd9873aSMichael Lange /*@
12331fd9873aSMichael Lange   DMPlexPartitionLabelInvert - Create a partition label of remote roots from a local root label
12341fd9873aSMichael Lange 
12351fd9873aSMichael Lange   Input Parameters:
12361fd9873aSMichael Lange + dm        - The DM
1237a5b23f4aSJose E. Roman . rootLabel - DMLabel assigning ranks to local roots
1238fe2efc57SMark - processSF - A star forest mapping into the local index on each remote rank
12391fd9873aSMichael Lange 
12401fd9873aSMichael Lange   Output Parameter:
1241a5b23f4aSJose E. Roman . leafLabel - DMLabel assigning ranks to remote roots
12421fd9873aSMichael Lange 
12431fd9873aSMichael Lange   Note: The rootLabel defines a send pattern by mapping local points to remote target ranks. The
12441fd9873aSMichael Lange   resulting leafLabel is a receiver mapping of remote roots to their parent rank.
12451fd9873aSMichael Lange 
12461fd9873aSMichael Lange   Level: developer
12471fd9873aSMichael Lange 
12482d4ee042Sprj- .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexCreateOverlap()
12491fd9873aSMichael Lange @*/
12501fd9873aSMichael Lange PetscErrorCode DMPlexPartitionLabelInvert(DM dm, DMLabel rootLabel, PetscSF processSF, DMLabel leafLabel)
12511fd9873aSMichael Lange {
12521fd9873aSMichael Lange   MPI_Comm           comm;
1253874ddda9SLisandro Dalcin   PetscMPIInt        rank, size, r;
1254874ddda9SLisandro Dalcin   PetscInt           p, n, numNeighbors, numPoints, dof, off, rootSize, l, nleaves, leafSize;
12551fd9873aSMichael Lange   PetscSF            sfPoint;
1256874ddda9SLisandro Dalcin   PetscSection       rootSection;
12571fd9873aSMichael Lange   PetscSFNode       *rootPoints, *leafPoints;
12581fd9873aSMichael Lange   const PetscSFNode *remote;
12591fd9873aSMichael Lange   const PetscInt    *local, *neighbors;
12601fd9873aSMichael Lange   IS                 valueIS;
1261874ddda9SLisandro Dalcin   PetscBool          mpiOverflow = PETSC_FALSE;
12621fd9873aSMichael Lange   PetscErrorCode     ierr;
12631fd9873aSMichael Lange 
12641fd9873aSMichael Lange   PetscFunctionBegin;
126530b0ce1bSStefano Zampini   ierr = PetscLogEventBegin(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr);
12661fd9873aSMichael Lange   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1267ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1268ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
12691fd9873aSMichael Lange   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
12701fd9873aSMichael Lange 
12711fd9873aSMichael Lange   /* Convert to (point, rank) and use actual owners */
12721fd9873aSMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
12739852e123SBarry Smith   ierr = PetscSectionSetChart(rootSection, 0, size);CHKERRQ(ierr);
12741fd9873aSMichael Lange   ierr = DMLabelGetValueIS(rootLabel, &valueIS);CHKERRQ(ierr);
12751fd9873aSMichael Lange   ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr);
12761fd9873aSMichael Lange   ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr);
12771fd9873aSMichael Lange   for (n = 0; n < numNeighbors; ++n) {
12781fd9873aSMichael Lange     ierr = DMLabelGetStratumSize(rootLabel, neighbors[n], &numPoints);CHKERRQ(ierr);
12791fd9873aSMichael Lange     ierr = PetscSectionAddDof(rootSection, neighbors[n], numPoints);CHKERRQ(ierr);
12801fd9873aSMichael Lange   }
12811fd9873aSMichael Lange   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
1282874ddda9SLisandro Dalcin   ierr = PetscSectionGetStorageSize(rootSection, &rootSize);CHKERRQ(ierr);
1283874ddda9SLisandro Dalcin   ierr = PetscMalloc1(rootSize, &rootPoints);CHKERRQ(ierr);
12841fd9873aSMichael Lange   ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr);
12851fd9873aSMichael Lange   for (n = 0; n < numNeighbors; ++n) {
12861fd9873aSMichael Lange     IS              pointIS;
12871fd9873aSMichael Lange     const PetscInt *points;
12881fd9873aSMichael Lange 
12891fd9873aSMichael Lange     ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr);
12901fd9873aSMichael Lange     ierr = DMLabelGetStratumIS(rootLabel, neighbors[n], &pointIS);CHKERRQ(ierr);
12911fd9873aSMichael Lange     ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
12921fd9873aSMichael Lange     ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
12931fd9873aSMichael Lange     for (p = 0; p < numPoints; ++p) {
1294f8987ae8SMichael Lange       if (local) {ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr);}
1295f8987ae8SMichael Lange       else       {l = -1;}
12961fd9873aSMichael Lange       if (l >= 0) {rootPoints[off+p] = remote[l];}
12971fd9873aSMichael Lange       else        {rootPoints[off+p].index = points[p]; rootPoints[off+p].rank = rank;}
12981fd9873aSMichael Lange     }
12991fd9873aSMichael Lange     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
13001fd9873aSMichael Lange     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
13011fd9873aSMichael Lange   }
1302874ddda9SLisandro Dalcin 
1303874ddda9SLisandro Dalcin   /* Try to communicate overlap using All-to-All */
1304874ddda9SLisandro Dalcin   if (!processSF) {
1305874ddda9SLisandro Dalcin     PetscInt64  counter = 0;
1306874ddda9SLisandro Dalcin     PetscBool   locOverflow = PETSC_FALSE;
1307874ddda9SLisandro Dalcin     PetscMPIInt *scounts, *sdispls, *rcounts, *rdispls;
1308874ddda9SLisandro Dalcin 
1309874ddda9SLisandro Dalcin     ierr = PetscCalloc4(size, &scounts, size, &sdispls, size, &rcounts, size, &rdispls);CHKERRQ(ierr);
1310874ddda9SLisandro Dalcin     for (n = 0; n < numNeighbors; ++n) {
1311874ddda9SLisandro Dalcin       ierr = PetscSectionGetDof(rootSection, neighbors[n], &dof);CHKERRQ(ierr);
1312874ddda9SLisandro Dalcin       ierr = PetscSectionGetOffset(rootSection, neighbors[n], &off);CHKERRQ(ierr);
1313874ddda9SLisandro Dalcin #if defined(PETSC_USE_64BIT_INDICES)
1314874ddda9SLisandro Dalcin       if (dof > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;}
1315874ddda9SLisandro Dalcin       if (off > PETSC_MPI_INT_MAX) {locOverflow = PETSC_TRUE; break;}
1316874ddda9SLisandro Dalcin #endif
1317874ddda9SLisandro Dalcin       scounts[neighbors[n]] = (PetscMPIInt) dof;
1318874ddda9SLisandro Dalcin       sdispls[neighbors[n]] = (PetscMPIInt) off;
1319874ddda9SLisandro Dalcin     }
1320ffc4695bSBarry Smith     ierr = MPI_Alltoall(scounts, 1, MPI_INT, rcounts, 1, MPI_INT, comm);CHKERRMPI(ierr);
1321874ddda9SLisandro Dalcin     for (r = 0; r < size; ++r) { rdispls[r] = (int)counter; counter += rcounts[r]; }
1322874ddda9SLisandro Dalcin     if (counter > PETSC_MPI_INT_MAX) locOverflow = PETSC_TRUE;
1323ffc4695bSBarry Smith     ierr = MPI_Allreduce(&locOverflow, &mpiOverflow, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRMPI(ierr);
1324874ddda9SLisandro Dalcin     if (!mpiOverflow) {
132594b10faeSStefano Zampini       ierr = PetscInfo(dm,"Using Alltoallv for mesh distribution\n");CHKERRQ(ierr);
1326874ddda9SLisandro Dalcin       leafSize = (PetscInt) counter;
1327874ddda9SLisandro Dalcin       ierr = PetscMalloc1(leafSize, &leafPoints);CHKERRQ(ierr);
1328ffc4695bSBarry Smith       ierr = MPI_Alltoallv(rootPoints, scounts, sdispls, MPIU_2INT, leafPoints, rcounts, rdispls, MPIU_2INT, comm);CHKERRMPI(ierr);
1329874ddda9SLisandro Dalcin     }
1330874ddda9SLisandro Dalcin     ierr = PetscFree4(scounts, sdispls, rcounts, rdispls);CHKERRQ(ierr);
1331874ddda9SLisandro Dalcin   }
1332874ddda9SLisandro Dalcin 
1333874ddda9SLisandro Dalcin   /* Communicate overlap using process star forest */
1334874ddda9SLisandro Dalcin   if (processSF || mpiOverflow) {
1335874ddda9SLisandro Dalcin     PetscSF      procSF;
1336874ddda9SLisandro Dalcin     PetscSection leafSection;
1337874ddda9SLisandro Dalcin 
1338874ddda9SLisandro Dalcin     if (processSF) {
133994b10faeSStefano Zampini       ierr = PetscInfo(dm,"Using processSF for mesh distribution\n");CHKERRQ(ierr);
1340874ddda9SLisandro Dalcin       ierr = PetscObjectReference((PetscObject)processSF);CHKERRQ(ierr);
1341874ddda9SLisandro Dalcin       procSF = processSF;
1342874ddda9SLisandro Dalcin     } else {
134394b10faeSStefano Zampini       ierr = PetscInfo(dm,"Using processSF for mesh distribution (MPI overflow)\n");CHKERRQ(ierr);
1344874ddda9SLisandro Dalcin       ierr = PetscSFCreate(comm,&procSF);CHKERRQ(ierr);
1345900e0f05SJunchao Zhang       ierr = PetscSFSetGraphWithPattern(procSF,NULL,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr);
1346874ddda9SLisandro Dalcin     }
1347874ddda9SLisandro Dalcin 
1348874ddda9SLisandro Dalcin     ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &leafSection);CHKERRQ(ierr);
1349900e0f05SJunchao Zhang     ierr = DMPlexDistributeData(dm, procSF, rootSection, MPIU_2INT, rootPoints, leafSection, (void**) &leafPoints);CHKERRQ(ierr);
1350874ddda9SLisandro Dalcin     ierr = PetscSectionGetStorageSize(leafSection, &leafSize);CHKERRQ(ierr);
1351874ddda9SLisandro Dalcin     ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
1352874ddda9SLisandro Dalcin     ierr = PetscSFDestroy(&procSF);CHKERRQ(ierr);
1353874ddda9SLisandro Dalcin   }
1354874ddda9SLisandro Dalcin 
1355874ddda9SLisandro Dalcin   for (p = 0; p < leafSize; p++) {
13561fd9873aSMichael Lange     ierr = DMLabelSetValue(leafLabel, leafPoints[p].index, leafPoints[p].rank);CHKERRQ(ierr);
13571fd9873aSMichael Lange   }
1358874ddda9SLisandro Dalcin 
1359874ddda9SLisandro Dalcin   ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr);
1360874ddda9SLisandro Dalcin   ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
13611fd9873aSMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
1362874ddda9SLisandro Dalcin   ierr = PetscFree(rootPoints);CHKERRQ(ierr);
13631fd9873aSMichael Lange   ierr = PetscFree(leafPoints);CHKERRQ(ierr);
136430b0ce1bSStefano Zampini   ierr = PetscLogEventEnd(DMPLEX_PartLabelInvert,dm,0,0,0);CHKERRQ(ierr);
13651fd9873aSMichael Lange   PetscFunctionReturn(0);
13661fd9873aSMichael Lange }
13671fd9873aSMichael Lange 
1368aa3148a8SMichael Lange /*@
1369aa3148a8SMichael Lange   DMPlexPartitionLabelCreateSF - Create a star forest from a label that assigns ranks to points
1370aa3148a8SMichael Lange 
1371aa3148a8SMichael Lange   Input Parameters:
1372aa3148a8SMichael Lange + dm    - The DM
1373a5b23f4aSJose E. Roman - label - DMLabel assigning ranks to remote roots
1374aa3148a8SMichael Lange 
1375aa3148a8SMichael Lange   Output Parameter:
1376fe2efc57SMark . sf    - The star forest communication context encapsulating the defined mapping
1377aa3148a8SMichael Lange 
1378aa3148a8SMichael Lange   Note: The incoming label is a receiver mapping of remote points to their parent rank.
1379aa3148a8SMichael Lange 
1380aa3148a8SMichael Lange   Level: developer
1381aa3148a8SMichael Lange 
138230b0ce1bSStefano Zampini .seealso: DMPlexDistribute(), DMPlexCreateOverlap()
1383aa3148a8SMichael Lange @*/
1384aa3148a8SMichael Lange PetscErrorCode DMPlexPartitionLabelCreateSF(DM dm, DMLabel label, PetscSF *sf)
1385aa3148a8SMichael Lange {
13866e203dd9SStefano Zampini   PetscMPIInt     rank;
13876e203dd9SStefano Zampini   PetscInt        n, numRemote, p, numPoints, pStart, pEnd, idx = 0, nNeighbors;
1388aa3148a8SMichael Lange   PetscSFNode    *remotePoints;
13896e203dd9SStefano Zampini   IS              remoteRootIS, neighborsIS;
13906e203dd9SStefano Zampini   const PetscInt *remoteRoots, *neighbors;
1391aa3148a8SMichael Lange   PetscErrorCode ierr;
1392aa3148a8SMichael Lange 
1393aa3148a8SMichael Lange   PetscFunctionBegin;
139430b0ce1bSStefano Zampini   ierr = PetscLogEventBegin(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr);
1395ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
1396aa3148a8SMichael Lange 
13976e203dd9SStefano Zampini   ierr = DMLabelGetValueIS(label, &neighborsIS);CHKERRQ(ierr);
13986e203dd9SStefano Zampini #if 0
13996e203dd9SStefano Zampini   {
14006e203dd9SStefano Zampini     IS is;
14016e203dd9SStefano Zampini     ierr = ISDuplicate(neighborsIS, &is);CHKERRQ(ierr);
14026e203dd9SStefano Zampini     ierr = ISSort(is);CHKERRQ(ierr);
14036e203dd9SStefano Zampini     ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr);
14046e203dd9SStefano Zampini     neighborsIS = is;
14056e203dd9SStefano Zampini   }
14066e203dd9SStefano Zampini #endif
14076e203dd9SStefano Zampini   ierr = ISGetLocalSize(neighborsIS, &nNeighbors);CHKERRQ(ierr);
14086e203dd9SStefano Zampini   ierr = ISGetIndices(neighborsIS, &neighbors);CHKERRQ(ierr);
14096e203dd9SStefano Zampini   for (numRemote = 0, n = 0; n < nNeighbors; ++n) {
14106e203dd9SStefano Zampini     ierr = DMLabelGetStratumSize(label, neighbors[n], &numPoints);CHKERRQ(ierr);
1411aa3148a8SMichael Lange     numRemote += numPoints;
1412aa3148a8SMichael Lange   }
1413aa3148a8SMichael Lange   ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr);
141443f7d02bSMichael Lange   /* Put owned points first */
141543f7d02bSMichael Lange   ierr = DMLabelGetStratumSize(label, rank, &numPoints);CHKERRQ(ierr);
141643f7d02bSMichael Lange   if (numPoints > 0) {
141743f7d02bSMichael Lange     ierr = DMLabelGetStratumIS(label, rank, &remoteRootIS);CHKERRQ(ierr);
141843f7d02bSMichael Lange     ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr);
141943f7d02bSMichael Lange     for (p = 0; p < numPoints; p++) {
142043f7d02bSMichael Lange       remotePoints[idx].index = remoteRoots[p];
142143f7d02bSMichael Lange       remotePoints[idx].rank = rank;
142243f7d02bSMichael Lange       idx++;
142343f7d02bSMichael Lange     }
142443f7d02bSMichael Lange     ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr);
142543f7d02bSMichael Lange     ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr);
142643f7d02bSMichael Lange   }
142743f7d02bSMichael Lange   /* Now add remote points */
14286e203dd9SStefano Zampini   for (n = 0; n < nNeighbors; ++n) {
14296e203dd9SStefano Zampini     const PetscInt nn = neighbors[n];
14306e203dd9SStefano Zampini 
14316e203dd9SStefano Zampini     ierr = DMLabelGetStratumSize(label, nn, &numPoints);CHKERRQ(ierr);
14326e203dd9SStefano Zampini     if (nn == rank || numPoints <= 0) continue;
14336e203dd9SStefano Zampini     ierr = DMLabelGetStratumIS(label, nn, &remoteRootIS);CHKERRQ(ierr);
1434aa3148a8SMichael Lange     ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr);
1435aa3148a8SMichael Lange     for (p = 0; p < numPoints; p++) {
1436aa3148a8SMichael Lange       remotePoints[idx].index = remoteRoots[p];
14376e203dd9SStefano Zampini       remotePoints[idx].rank = nn;
1438aa3148a8SMichael Lange       idx++;
1439aa3148a8SMichael Lange     }
1440aa3148a8SMichael Lange     ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr);
1441aa3148a8SMichael Lange     ierr = ISDestroy(&remoteRootIS);CHKERRQ(ierr);
1442aa3148a8SMichael Lange   }
1443aa3148a8SMichael Lange   ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), sf);CHKERRQ(ierr);
1444aa3148a8SMichael Lange   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1445aa3148a8SMichael Lange   ierr = PetscSFSetGraph(*sf, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
144630b0ce1bSStefano Zampini   ierr = PetscSFSetUp(*sf);CHKERRQ(ierr);
14476e203dd9SStefano Zampini   ierr = ISDestroy(&neighborsIS);CHKERRQ(ierr);
144830b0ce1bSStefano Zampini   ierr = PetscLogEventEnd(DMPLEX_PartLabelCreateSF,dm,0,0,0);CHKERRQ(ierr);
144970034214SMatthew G. Knepley   PetscFunctionReturn(0);
145070034214SMatthew G. Knepley }
1451cb87ef4cSFlorian Wechsung 
1452abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS)
1453abe9303eSLisandro Dalcin #include <parmetis.h>
1454abe9303eSLisandro Dalcin #endif
1455abe9303eSLisandro Dalcin 
14566a3739e5SFlorian Wechsung /* The two functions below are used by DMPlexRebalanceSharedPoints which errors
14576a3739e5SFlorian Wechsung  * when PETSc is built without ParMETIS. To avoid -Wunused-function, we take
14586a3739e5SFlorian Wechsung  * them out in that case. */
14596a3739e5SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS)
14607a82c785SFlorian Wechsung /*@C
14617f57c1a4SFlorian Wechsung 
14627f57c1a4SFlorian Wechsung   DMPlexRewriteSF - Rewrites the ownership of the SF of a DM (in place).
14637f57c1a4SFlorian Wechsung 
14647f57c1a4SFlorian Wechsung   Input parameters:
14657f57c1a4SFlorian Wechsung + dm                - The DMPlex object.
1466fe2efc57SMark . n                 - The number of points.
1467fe2efc57SMark . pointsToRewrite   - The points in the SF whose ownership will change.
1468fe2efc57SMark . targetOwners      - New owner for each element in pointsToRewrite.
1469fe2efc57SMark - degrees           - Degrees of the points in the SF as obtained by PetscSFComputeDegreeBegin/PetscSFComputeDegreeEnd.
14707f57c1a4SFlorian Wechsung 
14717f57c1a4SFlorian Wechsung   Level: developer
14727f57c1a4SFlorian Wechsung 
14737f57c1a4SFlorian Wechsung @*/
14747f57c1a4SFlorian Wechsung static PetscErrorCode DMPlexRewriteSF(DM dm, PetscInt n, PetscInt *pointsToRewrite, PetscInt *targetOwners, const PetscInt *degrees)
14757f57c1a4SFlorian Wechsung {
14767f57c1a4SFlorian Wechsung   PetscInt      ierr, pStart, pEnd, i, j, counter, leafCounter, sumDegrees, nroots, nleafs;
14777f57c1a4SFlorian Wechsung   PetscInt     *cumSumDegrees, *newOwners, *newNumbers, *rankOnLeafs, *locationsOfLeafs, *remoteLocalPointOfLeafs, *points, *leafsNew;
14787f57c1a4SFlorian Wechsung   PetscSFNode  *leafLocationsNew;
14797f57c1a4SFlorian Wechsung   const         PetscSFNode *iremote;
14807f57c1a4SFlorian Wechsung   const         PetscInt *ilocal;
14817f57c1a4SFlorian Wechsung   PetscBool    *isLeaf;
14827f57c1a4SFlorian Wechsung   PetscSF       sf;
14837f57c1a4SFlorian Wechsung   MPI_Comm      comm;
14845a30b08bSFlorian Wechsung   PetscMPIInt   rank, size;
14857f57c1a4SFlorian Wechsung 
14867f57c1a4SFlorian Wechsung   PetscFunctionBegin;
14877f57c1a4SFlorian Wechsung   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1488ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1489ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
14907f57c1a4SFlorian Wechsung   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
14917f57c1a4SFlorian Wechsung 
14927f57c1a4SFlorian Wechsung   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
14937f57c1a4SFlorian Wechsung   ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr);
14947f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr);
14957f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
14967f57c1a4SFlorian Wechsung     isLeaf[i] = PETSC_FALSE;
14977f57c1a4SFlorian Wechsung   }
14987f57c1a4SFlorian Wechsung   for (i=0; i<nleafs; i++) {
14997f57c1a4SFlorian Wechsung     isLeaf[ilocal[i]-pStart] = PETSC_TRUE;
15007f57c1a4SFlorian Wechsung   }
15017f57c1a4SFlorian Wechsung 
15027f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart+1, &cumSumDegrees);CHKERRQ(ierr);
15037f57c1a4SFlorian Wechsung   cumSumDegrees[0] = 0;
15047f57c1a4SFlorian Wechsung   for (i=1; i<=pEnd-pStart; i++) {
15057f57c1a4SFlorian Wechsung     cumSumDegrees[i] = cumSumDegrees[i-1] + degrees[i-1];
15067f57c1a4SFlorian Wechsung   }
15077f57c1a4SFlorian Wechsung   sumDegrees = cumSumDegrees[pEnd-pStart];
15087f57c1a4SFlorian Wechsung   /* get the location of my leafs (we have sumDegrees many leafs pointing at our roots) */
15097f57c1a4SFlorian Wechsung 
15107f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(sumDegrees, &locationsOfLeafs);CHKERRQ(ierr);
15117f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &rankOnLeafs);CHKERRQ(ierr);
15127f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
15137f57c1a4SFlorian Wechsung     rankOnLeafs[i] = rank;
15147f57c1a4SFlorian Wechsung   }
15157f57c1a4SFlorian Wechsung   ierr = PetscSFGatherBegin(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr);
15167f57c1a4SFlorian Wechsung   ierr = PetscSFGatherEnd(sf, MPIU_INT, rankOnLeafs, locationsOfLeafs);CHKERRQ(ierr);
15177f57c1a4SFlorian Wechsung   ierr = PetscFree(rankOnLeafs);CHKERRQ(ierr);
15187f57c1a4SFlorian Wechsung 
15197f57c1a4SFlorian Wechsung   /* get the remote local points of my leaves */
15207f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(sumDegrees, &remoteLocalPointOfLeafs);CHKERRQ(ierr);
15217f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &points);CHKERRQ(ierr);
15227f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
15237f57c1a4SFlorian Wechsung     points[i] = pStart+i;
15247f57c1a4SFlorian Wechsung   }
15257f57c1a4SFlorian Wechsung   ierr = PetscSFGatherBegin(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr);
15267f57c1a4SFlorian Wechsung   ierr = PetscSFGatherEnd(sf, MPIU_INT, points, remoteLocalPointOfLeafs);CHKERRQ(ierr);
15277f57c1a4SFlorian Wechsung   ierr = PetscFree(points);CHKERRQ(ierr);
15287f57c1a4SFlorian Wechsung   /* Figure out the new owners of the vertices that are up for grabs and their numbers on the new owners */
15297f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &newOwners);CHKERRQ(ierr);
15307f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &newNumbers);CHKERRQ(ierr);
15317f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
15327f57c1a4SFlorian Wechsung     newOwners[i] = -1;
15337f57c1a4SFlorian Wechsung     newNumbers[i] = -1;
15347f57c1a4SFlorian Wechsung   }
15357f57c1a4SFlorian Wechsung   {
15367f57c1a4SFlorian Wechsung     PetscInt oldNumber, newNumber, oldOwner, newOwner;
15377f57c1a4SFlorian Wechsung     for (i=0; i<n; i++) {
15387f57c1a4SFlorian Wechsung       oldNumber = pointsToRewrite[i];
15397f57c1a4SFlorian Wechsung       newNumber = -1;
15407f57c1a4SFlorian Wechsung       oldOwner = rank;
15417f57c1a4SFlorian Wechsung       newOwner = targetOwners[i];
15427f57c1a4SFlorian Wechsung       if (oldOwner == newOwner) {
15437f57c1a4SFlorian Wechsung         newNumber = oldNumber;
15447f57c1a4SFlorian Wechsung       } else {
15457f57c1a4SFlorian Wechsung         for (j=0; j<degrees[oldNumber]; j++) {
15467f57c1a4SFlorian Wechsung           if (locationsOfLeafs[cumSumDegrees[oldNumber]+j] == newOwner) {
15477f57c1a4SFlorian Wechsung             newNumber = remoteLocalPointOfLeafs[cumSumDegrees[oldNumber]+j];
15487f57c1a4SFlorian Wechsung             break;
15497f57c1a4SFlorian Wechsung           }
15507f57c1a4SFlorian Wechsung         }
15517f57c1a4SFlorian Wechsung       }
15527f57c1a4SFlorian Wechsung       if (newNumber == -1) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Couldn't find the new owner of vertex.");
15537f57c1a4SFlorian Wechsung 
15547f57c1a4SFlorian Wechsung       newOwners[oldNumber] = newOwner;
15557f57c1a4SFlorian Wechsung       newNumbers[oldNumber] = newNumber;
15567f57c1a4SFlorian Wechsung     }
15577f57c1a4SFlorian Wechsung   }
15587f57c1a4SFlorian Wechsung   ierr = PetscFree(cumSumDegrees);CHKERRQ(ierr);
15597f57c1a4SFlorian Wechsung   ierr = PetscFree(locationsOfLeafs);CHKERRQ(ierr);
15607f57c1a4SFlorian Wechsung   ierr = PetscFree(remoteLocalPointOfLeafs);CHKERRQ(ierr);
15617f57c1a4SFlorian Wechsung 
1562ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE);CHKERRQ(ierr);
1563ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sf, MPIU_INT, newOwners, newOwners,MPI_REPLACE);CHKERRQ(ierr);
1564ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE);CHKERRQ(ierr);
1565ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sf, MPIU_INT, newNumbers, newNumbers,MPI_REPLACE);CHKERRQ(ierr);
15667f57c1a4SFlorian Wechsung 
15677f57c1a4SFlorian Wechsung   /* Now count how many leafs we have on each processor. */
15687f57c1a4SFlorian Wechsung   leafCounter=0;
15697f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
15707f57c1a4SFlorian Wechsung     if (newOwners[i] >= 0) {
15717f57c1a4SFlorian Wechsung       if (newOwners[i] != rank) {
15727f57c1a4SFlorian Wechsung         leafCounter++;
15737f57c1a4SFlorian Wechsung       }
15747f57c1a4SFlorian Wechsung     } else {
15757f57c1a4SFlorian Wechsung       if (isLeaf[i]) {
15767f57c1a4SFlorian Wechsung         leafCounter++;
15777f57c1a4SFlorian Wechsung       }
15787f57c1a4SFlorian Wechsung     }
15797f57c1a4SFlorian Wechsung   }
15807f57c1a4SFlorian Wechsung 
15817f57c1a4SFlorian Wechsung   /* Now set up the new sf by creating the leaf arrays */
15827f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(leafCounter, &leafsNew);CHKERRQ(ierr);
15837f57c1a4SFlorian Wechsung   ierr = PetscMalloc1(leafCounter, &leafLocationsNew);CHKERRQ(ierr);
15847f57c1a4SFlorian Wechsung 
15857f57c1a4SFlorian Wechsung   leafCounter = 0;
15867f57c1a4SFlorian Wechsung   counter = 0;
15877f57c1a4SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
15887f57c1a4SFlorian Wechsung     if (newOwners[i] >= 0) {
15897f57c1a4SFlorian Wechsung       if (newOwners[i] != rank) {
15907f57c1a4SFlorian Wechsung         leafsNew[leafCounter] = i;
15917f57c1a4SFlorian Wechsung         leafLocationsNew[leafCounter].rank = newOwners[i];
15927f57c1a4SFlorian Wechsung         leafLocationsNew[leafCounter].index = newNumbers[i];
15937f57c1a4SFlorian Wechsung         leafCounter++;
15947f57c1a4SFlorian Wechsung       }
15957f57c1a4SFlorian Wechsung     } else {
15967f57c1a4SFlorian Wechsung       if (isLeaf[i]) {
15977f57c1a4SFlorian Wechsung         leafsNew[leafCounter] = i;
15987f57c1a4SFlorian Wechsung         leafLocationsNew[leafCounter].rank = iremote[counter].rank;
15997f57c1a4SFlorian Wechsung         leafLocationsNew[leafCounter].index = iremote[counter].index;
16007f57c1a4SFlorian Wechsung         leafCounter++;
16017f57c1a4SFlorian Wechsung       }
16027f57c1a4SFlorian Wechsung     }
16037f57c1a4SFlorian Wechsung     if (isLeaf[i]) {
16047f57c1a4SFlorian Wechsung       counter++;
16057f57c1a4SFlorian Wechsung     }
16067f57c1a4SFlorian Wechsung   }
16077f57c1a4SFlorian Wechsung 
16087f57c1a4SFlorian Wechsung   ierr = PetscSFSetGraph(sf, nroots, leafCounter, leafsNew, PETSC_OWN_POINTER, leafLocationsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
16097f57c1a4SFlorian Wechsung   ierr = PetscFree(newOwners);CHKERRQ(ierr);
16107f57c1a4SFlorian Wechsung   ierr = PetscFree(newNumbers);CHKERRQ(ierr);
16117f57c1a4SFlorian Wechsung   ierr = PetscFree(isLeaf);CHKERRQ(ierr);
16127f57c1a4SFlorian Wechsung   PetscFunctionReturn(0);
16137f57c1a4SFlorian Wechsung }
16147f57c1a4SFlorian Wechsung 
1615125d2a8fSFlorian Wechsung static PetscErrorCode DMPlexViewDistribution(MPI_Comm comm, PetscInt n, PetscInt skip, PetscInt *vtxwgt, PetscInt *part, PetscViewer viewer)
1616125d2a8fSFlorian Wechsung {
16175a30b08bSFlorian Wechsung   PetscInt *distribution, min, max, sum, i, ierr;
16185a30b08bSFlorian Wechsung   PetscMPIInt rank, size;
1619125d2a8fSFlorian Wechsung   PetscFunctionBegin;
1620ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1621ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1622125d2a8fSFlorian Wechsung   ierr = PetscCalloc1(size, &distribution);CHKERRQ(ierr);
1623125d2a8fSFlorian Wechsung   for (i=0; i<n; i++) {
1624125d2a8fSFlorian Wechsung     if (part) distribution[part[i]] += vtxwgt[skip*i];
1625125d2a8fSFlorian Wechsung     else distribution[rank] += vtxwgt[skip*i];
1626125d2a8fSFlorian Wechsung   }
1627ffc4695bSBarry Smith   ierr = MPI_Allreduce(MPI_IN_PLACE, distribution, size, MPIU_INT, MPI_SUM, comm);CHKERRMPI(ierr);
1628125d2a8fSFlorian Wechsung   min = distribution[0];
1629125d2a8fSFlorian Wechsung   max = distribution[0];
1630125d2a8fSFlorian Wechsung   sum = distribution[0];
1631125d2a8fSFlorian Wechsung   for (i=1; i<size; i++) {
1632125d2a8fSFlorian Wechsung     if (distribution[i]<min) min=distribution[i];
1633125d2a8fSFlorian Wechsung     if (distribution[i]>max) max=distribution[i];
1634125d2a8fSFlorian Wechsung     sum += distribution[i];
1635125d2a8fSFlorian Wechsung   }
1636125d2a8fSFlorian Wechsung   ierr = PetscViewerASCIIPrintf(viewer, "Min: %D, Avg: %D, Max: %D, Balance: %f\n", min, sum/size, max, (max*1.*size)/sum);CHKERRQ(ierr);
1637125d2a8fSFlorian Wechsung   ierr = PetscFree(distribution);CHKERRQ(ierr);
1638125d2a8fSFlorian Wechsung   PetscFunctionReturn(0);
1639125d2a8fSFlorian Wechsung }
1640125d2a8fSFlorian Wechsung 
16416a3739e5SFlorian Wechsung #endif
16426a3739e5SFlorian Wechsung 
1643cb87ef4cSFlorian Wechsung /*@
16445dc86ac1SFlorian Wechsung   DMPlexRebalanceSharedPoints - Redistribute points in the plex that are shared in order to achieve better balancing. This routine updates the PointSF of the DM inplace.
1645cb87ef4cSFlorian Wechsung 
1646cb87ef4cSFlorian Wechsung   Input parameters:
1647ed44d270SFlorian Wechsung + dm               - The DMPlex object.
1648fe2efc57SMark . entityDepth      - depth of the entity to balance (0 -> balance vertices).
1649fe2efc57SMark . useInitialGuess  - whether to use the current distribution as initial guess (only used by ParMETIS).
1650fe2efc57SMark - parallel         - whether to use ParMETIS and do the partition in parallel or whether to gather the graph onto a single process and use METIS.
1651cb87ef4cSFlorian Wechsung 
16528b879b41SFlorian Wechsung   Output parameters:
1653fe2efc57SMark . success          - whether the graph partitioning was successful or not. If not, try useInitialGuess=True and parallel=True.
16548b879b41SFlorian Wechsung 
165590ea27d8SSatish Balay   Level: intermediate
1656cb87ef4cSFlorian Wechsung 
1657cb87ef4cSFlorian Wechsung @*/
1658cb87ef4cSFlorian Wechsung 
16598b879b41SFlorian Wechsung PetscErrorCode DMPlexRebalanceSharedPoints(DM dm, PetscInt entityDepth, PetscBool useInitialGuess, PetscBool parallel, PetscBool *success)
1660cb87ef4cSFlorian Wechsung {
166141525646SFlorian Wechsung #if defined(PETSC_HAVE_PARMETIS)
1662cb87ef4cSFlorian Wechsung   PetscSF     sf;
16630faf6628SFlorian Wechsung   PetscInt    ierr, i, j, idx, jdx;
16647f57c1a4SFlorian Wechsung   PetscInt    eBegin, eEnd, nroots, nleafs, pStart, pEnd;
16657f57c1a4SFlorian Wechsung   const       PetscInt *degrees, *ilocal;
16667f57c1a4SFlorian Wechsung   const       PetscSFNode *iremote;
1667cb87ef4cSFlorian Wechsung   PetscBool   *toBalance, *isLeaf, *isExclusivelyOwned, *isNonExclusivelyOwned;
1668cf818975SFlorian Wechsung   PetscInt    numExclusivelyOwned, numNonExclusivelyOwned;
1669cb87ef4cSFlorian Wechsung   PetscMPIInt rank, size;
16707f57c1a4SFlorian Wechsung   PetscInt    *globalNumbersOfLocalOwnedVertices, *leafGlobalNumbers;
16715dc86ac1SFlorian Wechsung   const       PetscInt *cumSumVertices;
1672cb87ef4cSFlorian Wechsung   PetscInt    offset, counter;
16737f57c1a4SFlorian Wechsung   PetscInt    lenadjncy;
1674cb87ef4cSFlorian Wechsung   PetscInt    *xadj, *adjncy, *vtxwgt;
1675cb87ef4cSFlorian Wechsung   PetscInt    lenxadj;
1676cb87ef4cSFlorian Wechsung   PetscInt    *adjwgt = NULL;
1677cb87ef4cSFlorian Wechsung   PetscInt    *part, *options;
1678cf818975SFlorian Wechsung   PetscInt    nparts, wgtflag, numflag, ncon, edgecut;
1679cb87ef4cSFlorian Wechsung   real_t      *ubvec;
1680cb87ef4cSFlorian Wechsung   PetscInt    *firstVertices, *renumbering;
1681cb87ef4cSFlorian Wechsung   PetscInt    failed, failedGlobal;
1682cb87ef4cSFlorian Wechsung   MPI_Comm    comm;
16834baf1206SFlorian Wechsung   Mat         A, Apre;
168412617df9SFlorian Wechsung   const char *prefix = NULL;
16857d197802SFlorian Wechsung   PetscViewer       viewer;
16867d197802SFlorian Wechsung   PetscViewerFormat format;
16875a30b08bSFlorian Wechsung   PetscLayout layout;
168812617df9SFlorian Wechsung 
168912617df9SFlorian Wechsung   PetscFunctionBegin;
16908b879b41SFlorian Wechsung   if (success) *success = PETSC_FALSE;
16917f57c1a4SFlorian Wechsung   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1692ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1693ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
16947f57c1a4SFlorian Wechsung   if (size==1) PetscFunctionReturn(0);
16957f57c1a4SFlorian Wechsung 
169641525646SFlorian Wechsung   ierr = PetscLogEventBegin(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr);
169741525646SFlorian Wechsung 
16985a30b08bSFlorian Wechsung   ierr = PetscOptionsGetViewer(comm,((PetscObject)dm)->options, prefix,"-dm_rebalance_partition_view",&viewer,&format,NULL);CHKERRQ(ierr);
16995dc86ac1SFlorian Wechsung   if (viewer) {
17005a30b08bSFlorian Wechsung     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
17017d197802SFlorian Wechsung   }
17027d197802SFlorian Wechsung 
1703ed44d270SFlorian Wechsung   /* Figure out all points in the plex that we are interested in balancing. */
1704d5528e35SFlorian Wechsung   ierr = DMPlexGetDepthStratum(dm, entityDepth, &eBegin, &eEnd);CHKERRQ(ierr);
1705cb87ef4cSFlorian Wechsung   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1706cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &toBalance);CHKERRQ(ierr);
1707cf818975SFlorian Wechsung 
1708cb87ef4cSFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
17095a7e692eSFlorian Wechsung     toBalance[i] = (PetscBool)(i-pStart>=eBegin && i-pStart<eEnd);
1710cb87ef4cSFlorian Wechsung   }
1711cb87ef4cSFlorian Wechsung 
1712cf818975SFlorian Wechsung   /* There are three types of points:
1713cf818975SFlorian Wechsung    * exclusivelyOwned: points that are owned by this process and only seen by this process
1714cf818975SFlorian Wechsung    * nonExclusivelyOwned: points that are owned by this process but seen by at least another process
1715cf818975SFlorian Wechsung    * leaf: a point that is seen by this process but owned by a different process
1716cf818975SFlorian Wechsung    */
1717cb87ef4cSFlorian Wechsung   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
1718cb87ef4cSFlorian Wechsung   ierr = PetscSFGetGraph(sf, &nroots, &nleafs, &ilocal, &iremote);CHKERRQ(ierr);
1719cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &isLeaf);CHKERRQ(ierr);
1720cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &isNonExclusivelyOwned);CHKERRQ(ierr);
1721cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &isExclusivelyOwned);CHKERRQ(ierr);
1722cb87ef4cSFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
1723cb87ef4cSFlorian Wechsung     isNonExclusivelyOwned[i] = PETSC_FALSE;
1724cb87ef4cSFlorian Wechsung     isExclusivelyOwned[i] = PETSC_FALSE;
1725cf818975SFlorian Wechsung     isLeaf[i] = PETSC_FALSE;
1726cb87ef4cSFlorian Wechsung   }
1727cf818975SFlorian Wechsung 
1728cf818975SFlorian Wechsung   /* start by marking all the leafs */
1729cb87ef4cSFlorian Wechsung   for (i=0; i<nleafs; i++) {
1730cb87ef4cSFlorian Wechsung     isLeaf[ilocal[i]-pStart] = PETSC_TRUE;
1731cb87ef4cSFlorian Wechsung   }
1732cb87ef4cSFlorian Wechsung 
1733cf818975SFlorian Wechsung   /* for an owned point, we can figure out whether another processor sees it or
1734cf818975SFlorian Wechsung    * not by calculating its degree */
17357f57c1a4SFlorian Wechsung   ierr = PetscSFComputeDegreeBegin(sf, &degrees);CHKERRQ(ierr);
17367f57c1a4SFlorian Wechsung   ierr = PetscSFComputeDegreeEnd(sf, &degrees);CHKERRQ(ierr);
1737cf818975SFlorian Wechsung 
1738cb87ef4cSFlorian Wechsung   numExclusivelyOwned = 0;
1739cb87ef4cSFlorian Wechsung   numNonExclusivelyOwned = 0;
1740cb87ef4cSFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
1741cb87ef4cSFlorian Wechsung     if (toBalance[i]) {
17427f57c1a4SFlorian Wechsung       if (degrees[i] > 0) {
1743cb87ef4cSFlorian Wechsung         isNonExclusivelyOwned[i] = PETSC_TRUE;
1744cb87ef4cSFlorian Wechsung         numNonExclusivelyOwned += 1;
1745cb87ef4cSFlorian Wechsung       } else {
1746cb87ef4cSFlorian Wechsung         if (!isLeaf[i]) {
1747cb87ef4cSFlorian Wechsung           isExclusivelyOwned[i] = PETSC_TRUE;
1748cb87ef4cSFlorian Wechsung           numExclusivelyOwned += 1;
1749cb87ef4cSFlorian Wechsung         }
1750cb87ef4cSFlorian Wechsung       }
1751cb87ef4cSFlorian Wechsung     }
1752cb87ef4cSFlorian Wechsung   }
1753cb87ef4cSFlorian Wechsung 
1754cf818975SFlorian Wechsung   /* We are going to build a graph with one vertex per core representing the
1755cf818975SFlorian Wechsung    * exclusively owned points and then one vertex per nonExclusively owned
1756cf818975SFlorian Wechsung    * point. */
1757cb87ef4cSFlorian Wechsung 
17585dc86ac1SFlorian Wechsung   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
17595dc86ac1SFlorian Wechsung   ierr = PetscLayoutSetLocalSize(layout, 1 + numNonExclusivelyOwned);CHKERRQ(ierr);
17605dc86ac1SFlorian Wechsung   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
17615dc86ac1SFlorian Wechsung   ierr = PetscLayoutGetRanges(layout, &cumSumVertices);CHKERRQ(ierr);
17625dc86ac1SFlorian Wechsung 
1763cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr);
17645a427404SJunchao Zhang   for (i=0; i<pEnd-pStart; i++) {globalNumbersOfLocalOwnedVertices[i] = pStart - 1;}
1765cb87ef4cSFlorian Wechsung   offset = cumSumVertices[rank];
1766cb87ef4cSFlorian Wechsung   counter = 0;
1767cb87ef4cSFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
1768cb87ef4cSFlorian Wechsung     if (toBalance[i]) {
17697f57c1a4SFlorian Wechsung       if (degrees[i] > 0) {
1770cb87ef4cSFlorian Wechsung         globalNumbersOfLocalOwnedVertices[i] = counter + 1 + offset;
1771cb87ef4cSFlorian Wechsung         counter++;
1772cb87ef4cSFlorian Wechsung       }
1773cb87ef4cSFlorian Wechsung     }
1774cb87ef4cSFlorian Wechsung   }
1775cb87ef4cSFlorian Wechsung 
1776cb87ef4cSFlorian Wechsung   /* send the global numbers of vertices I own to the leafs so that they know to connect to it */
1777cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(pEnd-pStart, &leafGlobalNumbers);CHKERRQ(ierr);
1778ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE);CHKERRQ(ierr);
1779ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(sf, MPIU_INT, globalNumbersOfLocalOwnedVertices, leafGlobalNumbers,MPI_REPLACE);CHKERRQ(ierr);
1780cb87ef4cSFlorian Wechsung 
17810faf6628SFlorian Wechsung   /* Now start building the data structure for ParMETIS */
1782cb87ef4cSFlorian Wechsung 
17834baf1206SFlorian Wechsung   ierr = MatCreate(comm, &Apre);CHKERRQ(ierr);
17844baf1206SFlorian Wechsung   ierr = MatSetType(Apre, MATPREALLOCATOR);CHKERRQ(ierr);
17854baf1206SFlorian Wechsung   ierr = MatSetSizes(Apre, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr);
17864baf1206SFlorian Wechsung   ierr = MatSetUp(Apre);CHKERRQ(ierr);
17878c9a1619SFlorian Wechsung 
17888c9a1619SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
17898c9a1619SFlorian Wechsung     if (toBalance[i]) {
17900faf6628SFlorian Wechsung       idx = cumSumVertices[rank];
17910faf6628SFlorian Wechsung       if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i];
17920faf6628SFlorian Wechsung       else if (isLeaf[i]) jdx = leafGlobalNumbers[i];
17930faf6628SFlorian Wechsung       else continue;
17940faf6628SFlorian Wechsung       ierr = MatSetValue(Apre, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr);
17950faf6628SFlorian Wechsung       ierr = MatSetValue(Apre, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr);
17964baf1206SFlorian Wechsung     }
17974baf1206SFlorian Wechsung   }
17984baf1206SFlorian Wechsung 
17994baf1206SFlorian Wechsung   ierr = MatAssemblyBegin(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18004baf1206SFlorian Wechsung   ierr = MatAssemblyEnd(Apre, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18014baf1206SFlorian Wechsung 
18024baf1206SFlorian Wechsung   ierr = MatCreate(comm, &A);CHKERRQ(ierr);
18034baf1206SFlorian Wechsung   ierr = MatSetType(A, MATMPIAIJ);CHKERRQ(ierr);
18044baf1206SFlorian Wechsung   ierr = MatSetSizes(A, 1+numNonExclusivelyOwned, 1+numNonExclusivelyOwned, cumSumVertices[size], cumSumVertices[size]);CHKERRQ(ierr);
18054baf1206SFlorian Wechsung   ierr = MatPreallocatorPreallocate(Apre, PETSC_FALSE, A);CHKERRQ(ierr);
18064baf1206SFlorian Wechsung   ierr = MatDestroy(&Apre);CHKERRQ(ierr);
18074baf1206SFlorian Wechsung 
18084baf1206SFlorian Wechsung   for (i=0; i<pEnd-pStart; i++) {
18094baf1206SFlorian Wechsung     if (toBalance[i]) {
18100faf6628SFlorian Wechsung       idx = cumSumVertices[rank];
18110faf6628SFlorian Wechsung       if (isNonExclusivelyOwned[i]) jdx = globalNumbersOfLocalOwnedVertices[i];
18120faf6628SFlorian Wechsung       else if (isLeaf[i]) jdx = leafGlobalNumbers[i];
18130faf6628SFlorian Wechsung       else continue;
18140faf6628SFlorian Wechsung       ierr = MatSetValue(A, idx, jdx, 1, INSERT_VALUES);CHKERRQ(ierr);
18150faf6628SFlorian Wechsung       ierr = MatSetValue(A, jdx, idx, 1, INSERT_VALUES);CHKERRQ(ierr);
18160941debbSFlorian Wechsung     }
18170941debbSFlorian Wechsung   }
18188c9a1619SFlorian Wechsung 
18198c9a1619SFlorian Wechsung   ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18208c9a1619SFlorian Wechsung   ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18214baf1206SFlorian Wechsung   ierr = PetscFree(leafGlobalNumbers);CHKERRQ(ierr);
18224baf1206SFlorian Wechsung   ierr = PetscFree(globalNumbersOfLocalOwnedVertices);CHKERRQ(ierr);
18234baf1206SFlorian Wechsung 
182441525646SFlorian Wechsung   nparts = size;
182541525646SFlorian Wechsung   wgtflag = 2;
182641525646SFlorian Wechsung   numflag = 0;
182741525646SFlorian Wechsung   ncon = 2;
182841525646SFlorian Wechsung   real_t *tpwgts;
182941525646SFlorian Wechsung   ierr = PetscMalloc1(ncon * nparts, &tpwgts);CHKERRQ(ierr);
183041525646SFlorian Wechsung   for (i=0; i<ncon*nparts; i++) {
183141525646SFlorian Wechsung     tpwgts[i] = 1./(nparts);
183241525646SFlorian Wechsung   }
183341525646SFlorian Wechsung 
183441525646SFlorian Wechsung   ierr = PetscMalloc1(ncon, &ubvec);CHKERRQ(ierr);
183541525646SFlorian Wechsung   ubvec[0] = 1.01;
18365a30b08bSFlorian Wechsung   ubvec[1] = 1.01;
18378c9a1619SFlorian Wechsung   lenadjncy = 0;
18388c9a1619SFlorian Wechsung   for (i=0; i<1+numNonExclusivelyOwned; i++) {
18398c9a1619SFlorian Wechsung     PetscInt temp=0;
18408c9a1619SFlorian Wechsung     ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr);
18418c9a1619SFlorian Wechsung     lenadjncy += temp;
18428c9a1619SFlorian Wechsung     ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, NULL, NULL);CHKERRQ(ierr);
18438c9a1619SFlorian Wechsung   }
18448c9a1619SFlorian Wechsung   ierr = PetscMalloc1(lenadjncy, &adjncy);CHKERRQ(ierr);
18457407ba93SFlorian Wechsung   lenxadj = 2 + numNonExclusivelyOwned;
18460941debbSFlorian Wechsung   ierr = PetscMalloc1(lenxadj, &xadj);CHKERRQ(ierr);
18470941debbSFlorian Wechsung   xadj[0] = 0;
18488c9a1619SFlorian Wechsung   counter = 0;
18498c9a1619SFlorian Wechsung   for (i=0; i<1+numNonExclusivelyOwned; i++) {
18502953a68cSFlorian Wechsung     PetscInt        temp=0;
18512953a68cSFlorian Wechsung     const PetscInt *cols;
18528c9a1619SFlorian Wechsung     ierr = MatGetRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr);
1853580bdb30SBarry Smith     ierr = PetscArraycpy(&adjncy[counter], cols, temp);CHKERRQ(ierr);
18548c9a1619SFlorian Wechsung     counter += temp;
18550941debbSFlorian Wechsung     xadj[i+1] = counter;
18568c9a1619SFlorian Wechsung     ierr = MatRestoreRow(A, cumSumVertices[rank] + i, &temp, &cols, NULL);CHKERRQ(ierr);
18578c9a1619SFlorian Wechsung   }
18588c9a1619SFlorian Wechsung 
1859cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(cumSumVertices[rank+1]-cumSumVertices[rank], &part);CHKERRQ(ierr);
186041525646SFlorian Wechsung   ierr = PetscMalloc1(ncon*(1 + numNonExclusivelyOwned), &vtxwgt);CHKERRQ(ierr);
186141525646SFlorian Wechsung   vtxwgt[0] = numExclusivelyOwned;
186241525646SFlorian Wechsung   if (ncon>1) vtxwgt[1] = 1;
186341525646SFlorian Wechsung   for (i=0; i<numNonExclusivelyOwned; i++) {
186441525646SFlorian Wechsung     vtxwgt[ncon*(i+1)] = 1;
186541525646SFlorian Wechsung     if (ncon>1) vtxwgt[ncon*(i+1)+1] = 0;
186641525646SFlorian Wechsung   }
18678c9a1619SFlorian Wechsung 
18685dc86ac1SFlorian Wechsung   if (viewer) {
18697d197802SFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "Attempt rebalancing of shared points of depth %D on interface of mesh distribution.\n", entityDepth);CHKERRQ(ierr);
18707d197802SFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "Size of generated auxiliary graph: %D\n", cumSumVertices[size]);CHKERRQ(ierr);
187112617df9SFlorian Wechsung   }
187241525646SFlorian Wechsung   if (parallel) {
18735a30b08bSFlorian Wechsung     ierr = PetscMalloc1(4, &options);CHKERRQ(ierr);
18745a30b08bSFlorian Wechsung     options[0] = 1;
18755a30b08bSFlorian Wechsung     options[1] = 0; /* Verbosity */
18765a30b08bSFlorian Wechsung     options[2] = 0; /* Seed */
18775a30b08bSFlorian Wechsung     options[3] = PARMETIS_PSR_COUPLED; /* Seed */
18785dc86ac1SFlorian Wechsung     if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using ParMETIS to partition graph.\n");CHKERRQ(ierr); }
18798c9a1619SFlorian Wechsung     if (useInitialGuess) {
18805dc86ac1SFlorian Wechsung       if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using current distribution of points as initial guess.\n");CHKERRQ(ierr); }
18818c9a1619SFlorian Wechsung       PetscStackPush("ParMETIS_V3_RefineKway");
18825dc86ac1SFlorian Wechsung       ierr = ParMETIS_V3_RefineKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm);
188306b3913eSFlorian Wechsung       if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_RefineKway()");
18848c9a1619SFlorian Wechsung       PetscStackPop;
18858c9a1619SFlorian Wechsung     } else {
18868c9a1619SFlorian Wechsung       PetscStackPush("ParMETIS_V3_PartKway");
18875dc86ac1SFlorian Wechsung       ierr = ParMETIS_V3_PartKway((PetscInt*)cumSumVertices, xadj, adjncy, vtxwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm);
18888c9a1619SFlorian Wechsung       PetscStackPop;
188906b3913eSFlorian Wechsung       if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()");
18908c9a1619SFlorian Wechsung     }
1891ef74bcceSFlorian Wechsung     ierr = PetscFree(options);CHKERRQ(ierr);
189241525646SFlorian Wechsung   } else {
18935dc86ac1SFlorian Wechsung     if (viewer) { ierr = PetscViewerASCIIPrintf(viewer, "Using METIS to partition graph.\n");CHKERRQ(ierr); }
189441525646SFlorian Wechsung     Mat As;
189541525646SFlorian Wechsung     PetscInt numRows;
189641525646SFlorian Wechsung     PetscInt *partGlobal;
189741525646SFlorian Wechsung     ierr = MatCreateRedundantMatrix(A, size, MPI_COMM_NULL, MAT_INITIAL_MATRIX, &As);CHKERRQ(ierr);
1898cb87ef4cSFlorian Wechsung 
189941525646SFlorian Wechsung     PetscInt *numExclusivelyOwnedAll;
190041525646SFlorian Wechsung     ierr = PetscMalloc1(size, &numExclusivelyOwnedAll);CHKERRQ(ierr);
190141525646SFlorian Wechsung     numExclusivelyOwnedAll[rank] = numExclusivelyOwned;
1902ffc4695bSBarry Smith     ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,numExclusivelyOwnedAll,1,MPIU_INT,comm);CHKERRMPI(ierr);
1903cb87ef4cSFlorian Wechsung 
190441525646SFlorian Wechsung     ierr = MatGetSize(As, &numRows, NULL);CHKERRQ(ierr);
190541525646SFlorian Wechsung     ierr = PetscMalloc1(numRows, &partGlobal);CHKERRQ(ierr);
1906dd400576SPatrick Sanan     if (rank == 0) {
190741525646SFlorian Wechsung       PetscInt *adjncy_g, *xadj_g, *vtxwgt_g;
190841525646SFlorian Wechsung       lenadjncy = 0;
190941525646SFlorian Wechsung 
191041525646SFlorian Wechsung       for (i=0; i<numRows; i++) {
191141525646SFlorian Wechsung         PetscInt temp=0;
191241525646SFlorian Wechsung         ierr = MatGetRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr);
191341525646SFlorian Wechsung         lenadjncy += temp;
191441525646SFlorian Wechsung         ierr = MatRestoreRow(As, i, &temp, NULL, NULL);CHKERRQ(ierr);
191541525646SFlorian Wechsung       }
191641525646SFlorian Wechsung       ierr = PetscMalloc1(lenadjncy, &adjncy_g);CHKERRQ(ierr);
191741525646SFlorian Wechsung       lenxadj = 1 + numRows;
191841525646SFlorian Wechsung       ierr = PetscMalloc1(lenxadj, &xadj_g);CHKERRQ(ierr);
191941525646SFlorian Wechsung       xadj_g[0] = 0;
192041525646SFlorian Wechsung       counter = 0;
192141525646SFlorian Wechsung       for (i=0; i<numRows; i++) {
19222953a68cSFlorian Wechsung         PetscInt        temp=0;
19232953a68cSFlorian Wechsung         const PetscInt *cols;
192441525646SFlorian Wechsung         ierr = MatGetRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr);
1925580bdb30SBarry Smith         ierr = PetscArraycpy(&adjncy_g[counter], cols, temp);CHKERRQ(ierr);
192641525646SFlorian Wechsung         counter += temp;
192741525646SFlorian Wechsung         xadj_g[i+1] = counter;
192841525646SFlorian Wechsung         ierr = MatRestoreRow(As, i, &temp, &cols, NULL);CHKERRQ(ierr);
192941525646SFlorian Wechsung       }
193041525646SFlorian Wechsung       ierr = PetscMalloc1(2*numRows, &vtxwgt_g);CHKERRQ(ierr);
193141525646SFlorian Wechsung       for (i=0; i<size; i++) {
193241525646SFlorian Wechsung         vtxwgt_g[ncon*cumSumVertices[i]] = numExclusivelyOwnedAll[i];
193341525646SFlorian Wechsung         if (ncon>1) vtxwgt_g[ncon*cumSumVertices[i]+1] = 1;
193441525646SFlorian Wechsung         for (j=cumSumVertices[i]+1; j<cumSumVertices[i+1]; j++) {
193541525646SFlorian Wechsung           vtxwgt_g[ncon*j] = 1;
193641525646SFlorian Wechsung           if (ncon>1) vtxwgt_g[2*j+1] = 0;
193741525646SFlorian Wechsung         }
193841525646SFlorian Wechsung       }
193941525646SFlorian Wechsung       ierr = PetscMalloc1(64, &options);CHKERRQ(ierr);
194041525646SFlorian Wechsung       ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */
194106b3913eSFlorian Wechsung       if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()");
194241525646SFlorian Wechsung       options[METIS_OPTION_CONTIG] = 1;
194341525646SFlorian Wechsung       PetscStackPush("METIS_PartGraphKway");
194406b3913eSFlorian Wechsung       ierr = METIS_PartGraphKway(&numRows, &ncon, xadj_g, adjncy_g, vtxwgt_g, NULL, NULL, &nparts, tpwgts, ubvec, options, &edgecut, partGlobal);
194541525646SFlorian Wechsung       PetscStackPop;
194606b3913eSFlorian Wechsung       if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()");
1947ef74bcceSFlorian Wechsung       ierr = PetscFree(options);CHKERRQ(ierr);
194841525646SFlorian Wechsung       ierr = PetscFree(xadj_g);CHKERRQ(ierr);
194941525646SFlorian Wechsung       ierr = PetscFree(adjncy_g);CHKERRQ(ierr);
195041525646SFlorian Wechsung       ierr = PetscFree(vtxwgt_g);CHKERRQ(ierr);
195141525646SFlorian Wechsung     }
195241525646SFlorian Wechsung     ierr = PetscFree(numExclusivelyOwnedAll);CHKERRQ(ierr);
195341525646SFlorian Wechsung 
19545dc86ac1SFlorian Wechsung     /* Now scatter the parts array. */
19555dc86ac1SFlorian Wechsung     {
195681a13b52SFlorian Wechsung       PetscMPIInt *counts, *mpiCumSumVertices;
19575dc86ac1SFlorian Wechsung       ierr = PetscMalloc1(size, &counts);CHKERRQ(ierr);
195881a13b52SFlorian Wechsung       ierr = PetscMalloc1(size+1, &mpiCumSumVertices);CHKERRQ(ierr);
19595dc86ac1SFlorian Wechsung       for (i=0; i<size; i++) {
196081a13b52SFlorian Wechsung         ierr = PetscMPIIntCast(cumSumVertices[i+1] - cumSumVertices[i], &(counts[i]));CHKERRQ(ierr);
196141525646SFlorian Wechsung       }
196281a13b52SFlorian Wechsung       for (i=0; i<=size; i++) {
196381a13b52SFlorian Wechsung         ierr = PetscMPIIntCast(cumSumVertices[i], &(mpiCumSumVertices[i]));CHKERRQ(ierr);
196481a13b52SFlorian Wechsung       }
1965ffc4695bSBarry Smith       ierr = MPI_Scatterv(partGlobal, counts, mpiCumSumVertices, MPIU_INT, part, counts[rank], MPIU_INT, 0, comm);CHKERRMPI(ierr);
19665dc86ac1SFlorian Wechsung       ierr = PetscFree(counts);CHKERRQ(ierr);
196781a13b52SFlorian Wechsung       ierr = PetscFree(mpiCumSumVertices);CHKERRQ(ierr);
19685dc86ac1SFlorian Wechsung     }
19695dc86ac1SFlorian Wechsung 
197041525646SFlorian Wechsung     ierr = PetscFree(partGlobal);CHKERRQ(ierr);
19712953a68cSFlorian Wechsung     ierr = MatDestroy(&As);CHKERRQ(ierr);
197241525646SFlorian Wechsung   }
1973cb87ef4cSFlorian Wechsung 
19742953a68cSFlorian Wechsung   ierr = MatDestroy(&A);CHKERRQ(ierr);
1975cb87ef4cSFlorian Wechsung   ierr = PetscFree(ubvec);CHKERRQ(ierr);
1976cb87ef4cSFlorian Wechsung   ierr = PetscFree(tpwgts);CHKERRQ(ierr);
1977cb87ef4cSFlorian Wechsung 
1978cb87ef4cSFlorian Wechsung   /* Now rename the result so that the vertex resembling the exclusively owned points stays on the same rank */
1979cb87ef4cSFlorian Wechsung 
1980cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(size, &firstVertices);CHKERRQ(ierr);
1981cb87ef4cSFlorian Wechsung   ierr = PetscMalloc1(size, &renumbering);CHKERRQ(ierr);
1982cb87ef4cSFlorian Wechsung   firstVertices[rank] = part[0];
1983ffc4695bSBarry Smith   ierr = MPI_Allgather(MPI_IN_PLACE,0,MPI_DATATYPE_NULL,firstVertices,1,MPIU_INT,comm);CHKERRMPI(ierr);
1984cb87ef4cSFlorian Wechsung   for (i=0; i<size; i++) {
1985cb87ef4cSFlorian Wechsung     renumbering[firstVertices[i]] = i;
1986cb87ef4cSFlorian Wechsung   }
1987cb87ef4cSFlorian Wechsung   for (i=0; i<cumSumVertices[rank+1]-cumSumVertices[rank]; i++) {
1988cb87ef4cSFlorian Wechsung     part[i] = renumbering[part[i]];
1989cb87ef4cSFlorian Wechsung   }
1990cb87ef4cSFlorian Wechsung   /* Check if the renumbering worked (this can fail when ParMETIS gives fewer partitions than there are processes) */
1991cb87ef4cSFlorian Wechsung   failed = (PetscInt)(part[0] != rank);
1992ffc4695bSBarry Smith   ierr = MPI_Allreduce(&failed, &failedGlobal, 1, MPIU_INT, MPI_SUM, comm);CHKERRMPI(ierr);
1993cb87ef4cSFlorian Wechsung 
19947f57c1a4SFlorian Wechsung   ierr = PetscFree(firstVertices);CHKERRQ(ierr);
19957f57c1a4SFlorian Wechsung   ierr = PetscFree(renumbering);CHKERRQ(ierr);
19967f57c1a4SFlorian Wechsung 
1997cb87ef4cSFlorian Wechsung   if (failedGlobal > 0) {
19987f57c1a4SFlorian Wechsung     ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
19997f57c1a4SFlorian Wechsung     ierr = PetscFree(xadj);CHKERRQ(ierr);
20007f57c1a4SFlorian Wechsung     ierr = PetscFree(adjncy);CHKERRQ(ierr);
20017f57c1a4SFlorian Wechsung     ierr = PetscFree(vtxwgt);CHKERRQ(ierr);
20027f57c1a4SFlorian Wechsung     ierr = PetscFree(toBalance);CHKERRQ(ierr);
20037f57c1a4SFlorian Wechsung     ierr = PetscFree(isLeaf);CHKERRQ(ierr);
20047f57c1a4SFlorian Wechsung     ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr);
20057f57c1a4SFlorian Wechsung     ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr);
20067f57c1a4SFlorian Wechsung     ierr = PetscFree(part);CHKERRQ(ierr);
20077f57c1a4SFlorian Wechsung     if (viewer) {
200806b3913eSFlorian Wechsung       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
200906b3913eSFlorian Wechsung       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
20107f57c1a4SFlorian Wechsung     }
20117f57c1a4SFlorian Wechsung     ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr);
20128b879b41SFlorian Wechsung     PetscFunctionReturn(0);
2013cb87ef4cSFlorian Wechsung   }
2014cb87ef4cSFlorian Wechsung 
20157407ba93SFlorian Wechsung   /*Let's check how well we did distributing points*/
20165dc86ac1SFlorian Wechsung   if (viewer) {
20177d197802SFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "Comparing number of owned entities of depth %D on each process before rebalancing, after rebalancing, and after consistency checks.\n", entityDepth);CHKERRQ(ierr);
2018125d2a8fSFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "Initial.     ");CHKERRQ(ierr);
2019125d2a8fSFlorian Wechsung     ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, NULL, viewer);CHKERRQ(ierr);
2020125d2a8fSFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "Rebalanced.  ");CHKERRQ(ierr);
2021125d2a8fSFlorian Wechsung     ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr);
20227407ba93SFlorian Wechsung   }
20237407ba93SFlorian Wechsung 
2024cb87ef4cSFlorian Wechsung   /* Now check that every vertex is owned by a process that it is actually connected to. */
202541525646SFlorian Wechsung   for (i=1; i<=numNonExclusivelyOwned; i++) {
2026cb87ef4cSFlorian Wechsung     PetscInt loc = 0;
202741525646SFlorian Wechsung     ierr = PetscFindInt(cumSumVertices[part[i]], xadj[i+1]-xadj[i], &adjncy[xadj[i]], &loc);CHKERRQ(ierr);
20287407ba93SFlorian Wechsung     /* If not, then just set the owner to the original owner (hopefully a rare event, it means that a vertex has been isolated) */
2029cb87ef4cSFlorian Wechsung     if (loc<0) {
203041525646SFlorian Wechsung       part[i] = rank;
2031cb87ef4cSFlorian Wechsung     }
2032cb87ef4cSFlorian Wechsung   }
2033cb87ef4cSFlorian Wechsung 
20347407ba93SFlorian Wechsung   /* Let's see how significant the influences of the previous fixing up step was.*/
20355dc86ac1SFlorian Wechsung   if (viewer) {
2036125d2a8fSFlorian Wechsung     ierr = PetscViewerASCIIPrintf(viewer, "After.       ");CHKERRQ(ierr);
2037125d2a8fSFlorian Wechsung     ierr = DMPlexViewDistribution(comm, cumSumVertices[rank+1]-cumSumVertices[rank], ncon, vtxwgt, part, viewer);CHKERRQ(ierr);
20387407ba93SFlorian Wechsung   }
20397407ba93SFlorian Wechsung 
20405dc86ac1SFlorian Wechsung   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
2041cb87ef4cSFlorian Wechsung   ierr = PetscFree(xadj);CHKERRQ(ierr);
2042cb87ef4cSFlorian Wechsung   ierr = PetscFree(adjncy);CHKERRQ(ierr);
204341525646SFlorian Wechsung   ierr = PetscFree(vtxwgt);CHKERRQ(ierr);
2044cb87ef4cSFlorian Wechsung 
20457f57c1a4SFlorian Wechsung   /* Almost done, now rewrite the SF to reflect the new ownership. */
2046cf818975SFlorian Wechsung   {
20477f57c1a4SFlorian Wechsung     PetscInt *pointsToRewrite;
204806b3913eSFlorian Wechsung     ierr = PetscMalloc1(numNonExclusivelyOwned, &pointsToRewrite);CHKERRQ(ierr);
20497f57c1a4SFlorian Wechsung     counter = 0;
2050cb87ef4cSFlorian Wechsung     for (i=0; i<pEnd-pStart; i++) {
2051cb87ef4cSFlorian Wechsung       if (toBalance[i]) {
2052cb87ef4cSFlorian Wechsung         if (isNonExclusivelyOwned[i]) {
20537f57c1a4SFlorian Wechsung           pointsToRewrite[counter] = i + pStart;
2054cb87ef4cSFlorian Wechsung           counter++;
2055cb87ef4cSFlorian Wechsung         }
2056cb87ef4cSFlorian Wechsung       }
2057cb87ef4cSFlorian Wechsung     }
20587f57c1a4SFlorian Wechsung     ierr = DMPlexRewriteSF(dm, numNonExclusivelyOwned, pointsToRewrite, part+1, degrees);CHKERRQ(ierr);
20597f57c1a4SFlorian Wechsung     ierr = PetscFree(pointsToRewrite);CHKERRQ(ierr);
2060cf818975SFlorian Wechsung   }
2061cb87ef4cSFlorian Wechsung 
2062cb87ef4cSFlorian Wechsung   ierr = PetscFree(toBalance);CHKERRQ(ierr);
2063cb87ef4cSFlorian Wechsung   ierr = PetscFree(isLeaf);CHKERRQ(ierr);
2064cf818975SFlorian Wechsung   ierr = PetscFree(isNonExclusivelyOwned);CHKERRQ(ierr);
2065cf818975SFlorian Wechsung   ierr = PetscFree(isExclusivelyOwned);CHKERRQ(ierr);
20667f57c1a4SFlorian Wechsung   ierr = PetscFree(part);CHKERRQ(ierr);
20675dc86ac1SFlorian Wechsung   if (viewer) {
206806b3913eSFlorian Wechsung     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
206906b3913eSFlorian Wechsung     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
20707d197802SFlorian Wechsung   }
20718b879b41SFlorian Wechsung   if (success) *success = PETSC_TRUE;
207241525646SFlorian Wechsung   ierr = PetscLogEventEnd(DMPLEX_RebalanceSharedPoints, dm, 0, 0, 0);CHKERRQ(ierr);
2073b458e8f1SJose E. Roman   PetscFunctionReturn(0);
2074240408d3SFlorian Wechsung #else
20755f441e9bSFlorian Wechsung   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis.");
207641525646SFlorian Wechsung #endif
2077cb87ef4cSFlorian Wechsung }
2078