170034214SMatthew G. Knepley #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 270034214SMatthew G. Knepley 370034214SMatthew G. Knepley #undef __FUNCT__ 470034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreateNeighborCSR" 570034214SMatthew G. Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 670034214SMatthew G. Knepley { 770034214SMatthew G. Knepley const PetscInt maxFaceCases = 30; 870034214SMatthew G. Knepley PetscInt numFaceCases = 0; 970034214SMatthew G. Knepley PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 1070034214SMatthew G. Knepley PetscInt *off, *adj; 1170034214SMatthew G. Knepley PetscInt *neighborCells = NULL; 1270034214SMatthew G. Knepley PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 1370034214SMatthew G. Knepley PetscErrorCode ierr; 1470034214SMatthew G. Knepley 1570034214SMatthew G. Knepley PetscFunctionBegin; 1670034214SMatthew G. Knepley /* For parallel partitioning, I think you have to communicate supports */ 17*c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1870034214SMatthew G. Knepley cellDim = dim - cellHeight; 1970034214SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2070034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 2170034214SMatthew G. Knepley if (cEnd - cStart == 0) { 2270034214SMatthew G. Knepley if (numVertices) *numVertices = 0; 2370034214SMatthew G. Knepley if (offsets) *offsets = NULL; 2470034214SMatthew G. Knepley if (adjacency) *adjacency = NULL; 2570034214SMatthew G. Knepley PetscFunctionReturn(0); 2670034214SMatthew G. Knepley } 2770034214SMatthew G. Knepley numCells = cEnd - cStart; 2870034214SMatthew G. Knepley faceDepth = depth - cellHeight; 2970034214SMatthew G. Knepley if (dim == depth) { 3070034214SMatthew G. Knepley PetscInt f, fStart, fEnd; 3170034214SMatthew G. Knepley 3270034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 3370034214SMatthew G. Knepley /* Count neighboring cells */ 3470034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 3570034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 3670034214SMatthew G. Knepley const PetscInt *support; 3770034214SMatthew G. Knepley PetscInt supportSize; 3870034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 3970034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 4070034214SMatthew G. Knepley if (supportSize == 2) { 4170034214SMatthew G. Knepley ++off[support[0]-cStart+1]; 4270034214SMatthew G. Knepley ++off[support[1]-cStart+1]; 4370034214SMatthew G. Knepley } 4470034214SMatthew G. Knepley } 4570034214SMatthew G. Knepley /* Prefix sum */ 4670034214SMatthew G. Knepley for (c = 1; c <= numCells; ++c) off[c] += off[c-1]; 4770034214SMatthew G. Knepley if (adjacency) { 4870034214SMatthew G. Knepley PetscInt *tmp; 4970034214SMatthew G. Knepley 5070034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 5170034214SMatthew G. Knepley ierr = PetscMalloc1((numCells+1), &tmp);CHKERRQ(ierr); 5270034214SMatthew G. Knepley ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 5370034214SMatthew G. Knepley /* Get neighboring cells */ 5470034214SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 5570034214SMatthew G. Knepley const PetscInt *support; 5670034214SMatthew G. Knepley PetscInt supportSize; 5770034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5870034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5970034214SMatthew G. Knepley if (supportSize == 2) { 6070034214SMatthew G. Knepley adj[tmp[support[0]-cStart]++] = support[1]; 6170034214SMatthew G. Knepley adj[tmp[support[1]-cStart]++] = support[0]; 6270034214SMatthew G. Knepley } 6370034214SMatthew G. Knepley } 6470034214SMatthew G. Knepley #if defined(PETSC_USE_DEBUG) 6570034214SMatthew G. Knepley for (c = 0; c < cEnd-cStart; ++c) if (tmp[c] != off[c+1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart); 6670034214SMatthew G. Knepley #endif 6770034214SMatthew G. Knepley ierr = PetscFree(tmp);CHKERRQ(ierr); 6870034214SMatthew G. Knepley } 6970034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 7070034214SMatthew G. Knepley if (offsets) *offsets = off; 7170034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 7270034214SMatthew G. Knepley PetscFunctionReturn(0); 7370034214SMatthew G. Knepley } 7470034214SMatthew G. Knepley /* Setup face recognition */ 7570034214SMatthew G. Knepley if (faceDepth == 1) { 7670034214SMatthew 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 */ 7770034214SMatthew G. Knepley 7870034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 7970034214SMatthew G. Knepley PetscInt corners; 8070034214SMatthew G. Knepley 8170034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 8270034214SMatthew G. Knepley if (!cornersSeen[corners]) { 8370034214SMatthew G. Knepley PetscInt nFV; 8470034214SMatthew G. Knepley 8570034214SMatthew G. Knepley if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 8670034214SMatthew G. Knepley cornersSeen[corners] = 1; 8770034214SMatthew G. Knepley 8870034214SMatthew G. Knepley ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 8970034214SMatthew G. Knepley 9070034214SMatthew G. Knepley numFaceVertices[numFaceCases++] = nFV; 9170034214SMatthew G. Knepley } 9270034214SMatthew G. Knepley } 9370034214SMatthew G. Knepley } 9470034214SMatthew G. Knepley ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr); 9570034214SMatthew G. Knepley /* Count neighboring cells */ 9670034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 9770034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 9870034214SMatthew G. Knepley 9979bad331SMatthew G. Knepley ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 10070034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 10170034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 10270034214SMatthew G. Knepley PetscInt cellPair[2]; 10370034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 10470034214SMatthew G. Knepley PetscInt meetSize = 0; 10570034214SMatthew G. Knepley const PetscInt *meet = NULL; 10670034214SMatthew G. Knepley 10770034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 10870034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 10970034214SMatthew G. Knepley if (!found) { 11070034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 11170034214SMatthew G. Knepley if (meetSize) { 11270034214SMatthew G. Knepley PetscInt f; 11370034214SMatthew G. Knepley 11470034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 11570034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 11670034214SMatthew G. Knepley found = PETSC_TRUE; 11770034214SMatthew G. Knepley break; 11870034214SMatthew G. Knepley } 11970034214SMatthew G. Knepley } 12070034214SMatthew G. Knepley } 12170034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 12270034214SMatthew G. Knepley } 12370034214SMatthew G. Knepley if (found) ++off[cell-cStart+1]; 12470034214SMatthew G. Knepley } 12570034214SMatthew G. Knepley } 12670034214SMatthew G. Knepley /* Prefix sum */ 12770034214SMatthew G. Knepley for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 12870034214SMatthew G. Knepley 12970034214SMatthew G. Knepley if (adjacency) { 13070034214SMatthew G. Knepley ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr); 13170034214SMatthew G. Knepley /* Get neighboring cells */ 13270034214SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 13370034214SMatthew G. Knepley PetscInt numNeighbors = PETSC_DETERMINE, n; 13470034214SMatthew G. Knepley PetscInt cellOffset = 0; 13570034214SMatthew G. Knepley 13679bad331SMatthew G. Knepley ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, &numNeighbors, &neighborCells);CHKERRQ(ierr); 13770034214SMatthew G. Knepley /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 13870034214SMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 13970034214SMatthew G. Knepley PetscInt cellPair[2]; 14070034214SMatthew G. Knepley PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 14170034214SMatthew G. Knepley PetscInt meetSize = 0; 14270034214SMatthew G. Knepley const PetscInt *meet = NULL; 14370034214SMatthew G. Knepley 14470034214SMatthew G. Knepley cellPair[0] = cell; cellPair[1] = neighborCells[n]; 14570034214SMatthew G. Knepley if (cellPair[0] == cellPair[1]) continue; 14670034214SMatthew G. Knepley if (!found) { 14770034214SMatthew G. Knepley ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 14870034214SMatthew G. Knepley if (meetSize) { 14970034214SMatthew G. Knepley PetscInt f; 15070034214SMatthew G. Knepley 15170034214SMatthew G. Knepley for (f = 0; f < numFaceCases; ++f) { 15270034214SMatthew G. Knepley if (numFaceVertices[f] == meetSize) { 15370034214SMatthew G. Knepley found = PETSC_TRUE; 15470034214SMatthew G. Knepley break; 15570034214SMatthew G. Knepley } 15670034214SMatthew G. Knepley } 15770034214SMatthew G. Knepley } 15870034214SMatthew G. Knepley ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 15970034214SMatthew G. Knepley } 16070034214SMatthew G. Knepley if (found) { 16170034214SMatthew G. Knepley adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 16270034214SMatthew G. Knepley ++cellOffset; 16370034214SMatthew G. Knepley } 16470034214SMatthew G. Knepley } 16570034214SMatthew G. Knepley } 16670034214SMatthew G. Knepley } 16770034214SMatthew G. Knepley ierr = PetscFree(neighborCells);CHKERRQ(ierr); 16870034214SMatthew G. Knepley if (numVertices) *numVertices = numCells; 16970034214SMatthew G. Knepley if (offsets) *offsets = off; 17070034214SMatthew G. Knepley if (adjacency) *adjacency = adj; 17170034214SMatthew G. Knepley PetscFunctionReturn(0); 17270034214SMatthew G. Knepley } 17370034214SMatthew G. Knepley 17470034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 17570034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 17670034214SMatthew G. Knepley #include <unistd.h> 17770034214SMatthew G. Knepley #endif 17870034214SMatthew G. Knepley /* Chaco does not have an include file */ 17970034214SMatthew G. Knepley PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 18070034214SMatthew G. Knepley float *ewgts, float *x, float *y, float *z, char *outassignname, 18170034214SMatthew G. Knepley char *outfilename, short *assignment, int architecture, int ndims_tot, 18270034214SMatthew G. Knepley int mesh_dims[3], double *goal, int global_method, int local_method, 18370034214SMatthew G. Knepley int rqi_flag, int vmax, int ndims, double eigtol, long seed); 18470034214SMatthew G. Knepley 18570034214SMatthew G. Knepley extern int FREE_GRAPH; 18670034214SMatthew G. Knepley 18770034214SMatthew G. Knepley #undef __FUNCT__ 18870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexPartition_Chaco" 18970034214SMatthew G. Knepley PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 19070034214SMatthew G. Knepley { 19170034214SMatthew G. Knepley enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 19270034214SMatthew G. Knepley MPI_Comm comm; 19370034214SMatthew G. Knepley int nvtxs = numVertices; /* number of vertices in full graph */ 19470034214SMatthew G. Knepley int *vwgts = NULL; /* weights for all vertices */ 19570034214SMatthew G. Knepley float *ewgts = NULL; /* weights for all edges */ 19670034214SMatthew G. Knepley float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 19770034214SMatthew G. Knepley char *outassignname = NULL; /* name of assignment output file */ 19870034214SMatthew G. Knepley char *outfilename = NULL; /* output file name */ 19970034214SMatthew G. Knepley int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 20070034214SMatthew G. Knepley int ndims_tot = 0; /* total number of cube dimensions to divide */ 20170034214SMatthew G. Knepley int mesh_dims[3]; /* dimensions of mesh of processors */ 20270034214SMatthew G. Knepley double *goal = NULL; /* desired set sizes for each set */ 20370034214SMatthew G. Knepley int global_method = 1; /* global partitioning algorithm */ 20470034214SMatthew G. Knepley int local_method = 1; /* local partitioning algorithm */ 20570034214SMatthew G. Knepley int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 20670034214SMatthew G. Knepley int vmax = 200; /* how many vertices to coarsen down to? */ 20770034214SMatthew G. Knepley int ndims = 1; /* number of eigenvectors (2^d sets) */ 20870034214SMatthew G. Knepley double eigtol = 0.001; /* tolerance on eigenvectors */ 20970034214SMatthew G. Knepley long seed = 123636512; /* for random graph mutations */ 21070034214SMatthew G. Knepley short int *assignment; /* Output partition */ 21170034214SMatthew G. Knepley int fd_stdout, fd_pipe[2]; 21270034214SMatthew G. Knepley PetscInt *points; 21370034214SMatthew G. Knepley PetscMPIInt commSize; 21470034214SMatthew G. Knepley int i, v, p; 21570034214SMatthew G. Knepley PetscErrorCode ierr; 21670034214SMatthew G. Knepley 21770034214SMatthew G. Knepley PetscFunctionBegin; 21870034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 21970034214SMatthew G. Knepley ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 22070034214SMatthew G. Knepley if (!numVertices) { 22170034214SMatthew G. Knepley ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 22270034214SMatthew G. Knepley ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 22370034214SMatthew G. Knepley ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 22470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 22570034214SMatthew G. Knepley PetscFunctionReturn(0); 22670034214SMatthew G. Knepley } 22770034214SMatthew G. Knepley FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 22870034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 22970034214SMatthew G. Knepley 23070034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 23170034214SMatthew G. Knepley /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 23270034214SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 23370034214SMatthew G. Knepley } 23470034214SMatthew G. Knepley mesh_dims[0] = commSize; 23570034214SMatthew G. Knepley mesh_dims[1] = 1; 23670034214SMatthew G. Knepley mesh_dims[2] = 1; 23770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr); 23870034214SMatthew G. Knepley /* Chaco outputs to stdout. We redirect this to a buffer. */ 23970034214SMatthew G. Knepley /* TODO: check error codes for UNIX calls */ 24070034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 24170034214SMatthew G. Knepley { 24270034214SMatthew G. Knepley int piperet; 24370034214SMatthew G. Knepley piperet = pipe(fd_pipe); 24470034214SMatthew G. Knepley if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 24570034214SMatthew G. Knepley fd_stdout = dup(1); 24670034214SMatthew G. Knepley close(1); 24770034214SMatthew G. Knepley dup2(fd_pipe[1], 1); 24870034214SMatthew G. Knepley } 24970034214SMatthew G. Knepley #endif 25070034214SMatthew G. Knepley ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 25170034214SMatthew G. Knepley assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 25270034214SMatthew G. Knepley vmax, ndims, eigtol, seed); 25370034214SMatthew G. Knepley #if defined(PETSC_HAVE_UNISTD_H) 25470034214SMatthew G. Knepley { 25570034214SMatthew G. Knepley char msgLog[10000]; 25670034214SMatthew G. Knepley int count; 25770034214SMatthew G. Knepley 25870034214SMatthew G. Knepley fflush(stdout); 25970034214SMatthew G. Knepley count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 26070034214SMatthew G. Knepley if (count < 0) count = 0; 26170034214SMatthew G. Knepley msgLog[count] = 0; 26270034214SMatthew G. Knepley close(1); 26370034214SMatthew G. Knepley dup2(fd_stdout, 1); 26470034214SMatthew G. Knepley close(fd_stdout); 26570034214SMatthew G. Knepley close(fd_pipe[0]); 26670034214SMatthew G. Knepley close(fd_pipe[1]); 26770034214SMatthew G. Knepley if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 26870034214SMatthew G. Knepley } 26970034214SMatthew G. Knepley #endif 27070034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 27170034214SMatthew G. Knepley ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 27270034214SMatthew G. Knepley ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 27370034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 27470034214SMatthew G. Knepley ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 27570034214SMatthew G. Knepley } 27670034214SMatthew G. Knepley ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 27770034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 27870034214SMatthew G. Knepley for (p = 0, i = 0; p < commSize; ++p) { 27970034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 28070034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 28170034214SMatthew G. Knepley } 28270034214SMatthew G. Knepley } 28370034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 28470034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 28570034214SMatthew G. Knepley if (global_method == INERTIAL_METHOD) { 28670034214SMatthew G. Knepley /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 28770034214SMatthew G. Knepley } 28870034214SMatthew G. Knepley ierr = PetscFree(assignment);CHKERRQ(ierr); 28970034214SMatthew G. Knepley for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 29070034214SMatthew G. Knepley PetscFunctionReturn(0); 29170034214SMatthew G. Knepley } 29270034214SMatthew G. Knepley #endif 29370034214SMatthew G. Knepley 29470034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 29570034214SMatthew G. Knepley #include <parmetis.h> 29670034214SMatthew G. Knepley 29770034214SMatthew G. Knepley #undef __FUNCT__ 29870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexPartition_ParMetis" 29970034214SMatthew G. Knepley PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 30070034214SMatthew G. Knepley { 30170034214SMatthew G. Knepley MPI_Comm comm; 30270034214SMatthew G. Knepley PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 30370034214SMatthew G. Knepley PetscInt *vtxdist; /* Distribution of vertices across processes */ 30470034214SMatthew G. Knepley PetscInt *xadj = start; /* Start of edge list for each vertex */ 30570034214SMatthew G. Knepley PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 30670034214SMatthew G. Knepley PetscInt *vwgt = NULL; /* Vertex weights */ 30770034214SMatthew G. Knepley PetscInt *adjwgt = NULL; /* Edge weights */ 30870034214SMatthew G. Knepley PetscInt wgtflag = 0; /* Indicates which weights are present */ 30970034214SMatthew G. Knepley PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 31070034214SMatthew G. Knepley PetscInt ncon = 1; /* The number of weights per vertex */ 31170034214SMatthew G. Knepley PetscInt nparts; /* The number of partitions */ 31270034214SMatthew G. Knepley PetscReal *tpwgts; /* The fraction of vertex weights assigned to each partition */ 31370034214SMatthew G. Knepley PetscReal *ubvec; /* The balance intolerance for vertex weights */ 31470034214SMatthew G. Knepley PetscInt options[5]; /* Options */ 31570034214SMatthew G. Knepley /* Outputs */ 31670034214SMatthew G. Knepley PetscInt edgeCut; /* The number of edges cut by the partition */ 31770034214SMatthew G. Knepley PetscInt *assignment, *points; 31870034214SMatthew G. Knepley PetscMPIInt commSize, rank, p, v, i; 31970034214SMatthew G. Knepley PetscErrorCode ierr; 32070034214SMatthew G. Knepley 32170034214SMatthew G. Knepley PetscFunctionBegin; 32270034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 32370034214SMatthew G. Knepley ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 32470034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 32570034214SMatthew G. Knepley nparts = commSize; 32670034214SMatthew G. Knepley options[0] = 0; /* Use all defaults */ 32770034214SMatthew G. Knepley /* Calculate vertex distribution */ 32870034214SMatthew G. Knepley ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 32970034214SMatthew G. Knepley vtxdist[0] = 0; 33070034214SMatthew G. Knepley ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 33170034214SMatthew G. Knepley for (p = 2; p <= nparts; ++p) { 33270034214SMatthew G. Knepley vtxdist[p] += vtxdist[p-1]; 33370034214SMatthew G. Knepley } 33470034214SMatthew G. Knepley /* Calculate weights */ 33570034214SMatthew G. Knepley for (p = 0; p < nparts; ++p) { 33670034214SMatthew G. Knepley tpwgts[p] = 1.0/nparts; 33770034214SMatthew G. Knepley } 33870034214SMatthew G. Knepley ubvec[0] = 1.05; 33970034214SMatthew G. Knepley 34070034214SMatthew G. Knepley if (nparts == 1) { 34170034214SMatthew G. Knepley ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt)); 34270034214SMatthew G. Knepley } else { 34370034214SMatthew G. Knepley if (vtxdist[1] == vtxdist[nparts]) { 34470034214SMatthew G. Knepley if (!rank) { 34570034214SMatthew G. Knepley PetscStackPush("METIS_PartGraphKway"); 34670034214SMatthew G. Knepley ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment); 34770034214SMatthew G. Knepley PetscStackPop; 34870034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 34970034214SMatthew G. Knepley } 35070034214SMatthew G. Knepley } else { 35170034214SMatthew G. Knepley PetscStackPush("ParMETIS_V3_PartKway"); 35270034214SMatthew G. Knepley ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm); 35370034214SMatthew G. Knepley PetscStackPop; 35470034214SMatthew G. Knepley if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()"); 35570034214SMatthew G. Knepley } 35670034214SMatthew G. Knepley } 35770034214SMatthew G. Knepley /* Convert to PetscSection+IS */ 35870034214SMatthew G. Knepley ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 35970034214SMatthew G. Knepley ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 36070034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 36170034214SMatthew G. Knepley ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 36270034214SMatthew G. Knepley } 36370034214SMatthew G. Knepley ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 36470034214SMatthew G. Knepley ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 36570034214SMatthew G. Knepley for (p = 0, i = 0; p < commSize; ++p) { 36670034214SMatthew G. Knepley for (v = 0; v < nvtxs; ++v) { 36770034214SMatthew G. Knepley if (assignment[v] == p) points[i++] = v; 36870034214SMatthew G. Knepley } 36970034214SMatthew G. Knepley } 37070034214SMatthew G. Knepley if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 37170034214SMatthew G. Knepley ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 37270034214SMatthew G. Knepley ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 37370034214SMatthew G. Knepley PetscFunctionReturn(0); 37470034214SMatthew G. Knepley } 37570034214SMatthew G. Knepley #endif 37670034214SMatthew G. Knepley 37770034214SMatthew G. Knepley #undef __FUNCT__ 37870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexEnlargePartition" 37970034214SMatthew G. Knepley /* Expand the partition by BFS on the adjacency graph */ 38070034214SMatthew G. Knepley PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 38170034214SMatthew G. Knepley { 38270034214SMatthew G. Knepley PetscHashI h; 38370034214SMatthew G. Knepley const PetscInt *points; 38470034214SMatthew G. Knepley PetscInt **tmpPoints, *newPoints, totPoints = 0; 38570034214SMatthew G. Knepley PetscInt pStart, pEnd, part, q; 38670034214SMatthew G. Knepley PetscBool useCone; 38770034214SMatthew G. Knepley PetscErrorCode ierr; 38870034214SMatthew G. Knepley 38970034214SMatthew G. Knepley PetscFunctionBegin; 39070034214SMatthew G. Knepley PetscHashICreate(h); 39170034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 39270034214SMatthew G. Knepley ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 39370034214SMatthew G. Knepley ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 39470034214SMatthew G. Knepley ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 39570034214SMatthew G. Knepley ierr = PetscMalloc1((pEnd - pStart), &tmpPoints);CHKERRQ(ierr); 39670034214SMatthew G. Knepley ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr); 39770034214SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, PETSC_TRUE);CHKERRQ(ierr); 39870034214SMatthew G. Knepley for (part = pStart; part < pEnd; ++part) { 39970034214SMatthew G. Knepley PetscInt *adj = NULL; 40070034214SMatthew G. Knepley PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 40170034214SMatthew G. Knepley 40270034214SMatthew G. Knepley PetscHashIClear(h); 40370034214SMatthew G. Knepley ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 40470034214SMatthew G. Knepley ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 40570034214SMatthew G. Knepley /* Add all existing points to h */ 40670034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 40770034214SMatthew G. Knepley const PetscInt point = points[off+p]; 40870034214SMatthew G. Knepley PetscHashIAdd(h, point, 1); 40970034214SMatthew G. Knepley } 41070034214SMatthew G. Knepley PetscHashISize(h, nP); 41170034214SMatthew G. Knepley if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 41270034214SMatthew G. Knepley /* Add all points in next BFS level */ 41370034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 41470034214SMatthew G. Knepley const PetscInt point = points[off+p]; 41570034214SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 41670034214SMatthew G. Knepley 41770034214SMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, point, &adjSize, &adj);CHKERRQ(ierr); 41870034214SMatthew G. Knepley for (a = 0; a < adjSize; ++a) PetscHashIAdd(h, adj[a], 1); 41970034214SMatthew G. Knepley } 42070034214SMatthew G. Knepley PetscHashISize(h, numNewPoints); 42170034214SMatthew G. Knepley ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 42270034214SMatthew G. Knepley ierr = PetscMalloc1(numNewPoints, &tmpPoints[part]);CHKERRQ(ierr); 42370034214SMatthew G. Knepley ierr = PetscHashIGetKeys(h, &n, tmpPoints[part]);CHKERRQ(ierr); 42470034214SMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 42570034214SMatthew G. Knepley totPoints += numNewPoints; 42670034214SMatthew G. Knepley } 42770034214SMatthew G. Knepley ierr = DMPlexSetAdjacencyUseCone(dm, useCone);CHKERRQ(ierr); 42870034214SMatthew G. Knepley ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 42970034214SMatthew G. Knepley PetscHashIDestroy(h); 43070034214SMatthew G. Knepley ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 43170034214SMatthew G. Knepley ierr = PetscMalloc1(totPoints, &newPoints);CHKERRQ(ierr); 43270034214SMatthew G. Knepley for (part = pStart, q = 0; part < pEnd; ++part) { 43370034214SMatthew G. Knepley PetscInt numPoints, p; 43470034214SMatthew G. Knepley 43570034214SMatthew G. Knepley ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 43670034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 43770034214SMatthew G. Knepley ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 43870034214SMatthew G. Knepley } 43970034214SMatthew G. Knepley ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 44070034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 44170034214SMatthew G. Knepley PetscFunctionReturn(0); 44270034214SMatthew G. Knepley } 44370034214SMatthew G. Knepley 44470034214SMatthew G. Knepley #undef __FUNCT__ 44570034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreatePartition" 44670034214SMatthew G. Knepley /* 44770034214SMatthew G. Knepley DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 44870034214SMatthew G. Knepley 44970034214SMatthew G. Knepley Collective on DM 45070034214SMatthew G. Knepley 45170034214SMatthew G. Knepley Input Parameters: 45270034214SMatthew G. Knepley + dm - The DM 45370034214SMatthew G. Knepley . height - The height for points in the partition 45470034214SMatthew G. Knepley - enlarge - Expand each partition with neighbors 45570034214SMatthew G. Knepley 45670034214SMatthew G. Knepley Output Parameters: 45770034214SMatthew G. Knepley + partSection - The PetscSection giving the division of points by partition 45870034214SMatthew G. Knepley . partition - The list of points by partition 45970034214SMatthew G. Knepley . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 46070034214SMatthew G. Knepley - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 46170034214SMatthew G. Knepley 46270034214SMatthew G. Knepley Level: developer 46370034214SMatthew G. Knepley 46470034214SMatthew G. Knepley .seealso DMPlexDistribute() 46570034214SMatthew G. Knepley */ 46670034214SMatthew G. Knepley PetscErrorCode DMPlexCreatePartition(DM dm, const char name[], PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 46770034214SMatthew G. Knepley { 46870034214SMatthew G. Knepley char partname[1024]; 46970034214SMatthew G. Knepley PetscBool isChaco = PETSC_FALSE, isMetis = PETSC_FALSE, flg; 47070034214SMatthew G. Knepley PetscMPIInt size; 47170034214SMatthew G. Knepley PetscErrorCode ierr; 47270034214SMatthew G. Knepley 47370034214SMatthew G. Knepley PetscFunctionBegin; 47470034214SMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 47570034214SMatthew G. Knepley 47670034214SMatthew G. Knepley *origPartSection = NULL; 47770034214SMatthew G. Knepley *origPartition = NULL; 47870034214SMatthew G. Knepley if (size == 1) { 47970034214SMatthew G. Knepley PetscInt *points; 48070034214SMatthew G. Knepley PetscInt cStart, cEnd, c; 48170034214SMatthew G. Knepley 48270034214SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 48370034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 48470034214SMatthew G. Knepley ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 48570034214SMatthew G. Knepley ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 48670034214SMatthew G. Knepley ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 48770034214SMatthew G. Knepley ierr = PetscMalloc1((cEnd - cStart), &points);CHKERRQ(ierr); 48870034214SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) points[c] = c; 48970034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 49070034214SMatthew G. Knepley PetscFunctionReturn(0); 49170034214SMatthew G. Knepley } 49270034214SMatthew G. Knepley ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_partitioner", partname, 1024, &flg);CHKERRQ(ierr); 49370034214SMatthew G. Knepley if (flg) name = partname; 49470034214SMatthew G. Knepley if (name) { 49570034214SMatthew G. Knepley ierr = PetscStrcmp(name, "chaco", &isChaco);CHKERRQ(ierr); 49670034214SMatthew G. Knepley ierr = PetscStrcmp(name, "metis", &isMetis);CHKERRQ(ierr); 49770034214SMatthew G. Knepley } 49870034214SMatthew G. Knepley if (height == 0) { 49970034214SMatthew G. Knepley PetscInt numVertices; 50070034214SMatthew G. Knepley PetscInt *start = NULL; 50170034214SMatthew G. Knepley PetscInt *adjacency = NULL; 50270034214SMatthew G. Knepley 50370034214SMatthew G. Knepley ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 50470034214SMatthew G. Knepley if (!name || isChaco) { 50570034214SMatthew G. Knepley #if defined(PETSC_HAVE_CHACO) 50670034214SMatthew G. Knepley ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 50770034214SMatthew G. Knepley #else 50870034214SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco."); 50970034214SMatthew G. Knepley #endif 51070034214SMatthew G. Knepley } else if (isMetis) { 51170034214SMatthew G. Knepley #if defined(PETSC_HAVE_PARMETIS) 51270034214SMatthew G. Knepley ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 51370034214SMatthew G. Knepley #endif 51470034214SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unknown mesh partitioning package %s", name); 51570034214SMatthew G. Knepley if (enlarge) { 51670034214SMatthew G. Knepley *origPartSection = *partSection; 51770034214SMatthew G. Knepley *origPartition = *partition; 51870034214SMatthew G. Knepley 51970034214SMatthew G. Knepley ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 52070034214SMatthew G. Knepley } 52170034214SMatthew G. Knepley ierr = PetscFree(start);CHKERRQ(ierr); 52270034214SMatthew G. Knepley ierr = PetscFree(adjacency);CHKERRQ(ierr); 52370034214SMatthew G. Knepley # if 0 52470034214SMatthew G. Knepley } else if (height == 1) { 52570034214SMatthew G. Knepley /* Build the dual graph for faces and partition the hypergraph */ 52670034214SMatthew G. Knepley PetscInt numEdges; 52770034214SMatthew G. Knepley 52870034214SMatthew G. Knepley buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 52970034214SMatthew G. Knepley GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 53070034214SMatthew G. Knepley destroyCSR(numEdges, start, adjacency); 53170034214SMatthew G. Knepley #endif 53270034214SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 53370034214SMatthew G. Knepley PetscFunctionReturn(0); 53470034214SMatthew G. Knepley } 53570034214SMatthew G. Knepley 53670034214SMatthew G. Knepley #undef __FUNCT__ 53770034214SMatthew G. Knepley #define __FUNCT__ "DMPlexCreatePartitionClosure" 53870034214SMatthew G. Knepley PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 53970034214SMatthew G. Knepley { 54070034214SMatthew G. Knepley /* const PetscInt height = 0; */ 54170034214SMatthew G. Knepley const PetscInt *partArray; 54270034214SMatthew G. Knepley PetscInt *allPoints, *packPoints; 54370034214SMatthew G. Knepley PetscInt rStart, rEnd, rank, pStart, pEnd, newSize; 54470034214SMatthew G. Knepley PetscErrorCode ierr; 54570034214SMatthew G. Knepley PetscBT bt; 54670034214SMatthew G. Knepley PetscSegBuffer segpack,segpart; 54770034214SMatthew G. Knepley 54870034214SMatthew G. Knepley PetscFunctionBegin; 54970034214SMatthew G. Knepley ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 55070034214SMatthew G. Knepley ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 55170034214SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 55270034214SMatthew G. Knepley ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 55370034214SMatthew G. Knepley ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 55470034214SMatthew G. Knepley ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr); 55570034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr); 55670034214SMatthew G. Knepley ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr); 55770034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 55870034214SMatthew G. Knepley PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints; 55970034214SMatthew G. Knepley 56070034214SMatthew G. Knepley ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 56170034214SMatthew G. Knepley ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 56270034214SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 56370034214SMatthew G. Knepley PetscInt point = partArray[offset+p], closureSize, c; 56470034214SMatthew G. Knepley PetscInt *closure = NULL; 56570034214SMatthew G. Knepley 56670034214SMatthew G. Knepley /* TODO Include support for height > 0 case */ 56770034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 56870034214SMatthew G. Knepley for (c=0; c<closureSize; c++) { 56970034214SMatthew G. Knepley PetscInt cpoint = closure[c*2]; 57070034214SMatthew G. Knepley if (!PetscBTLookupSet(bt,cpoint-pStart)) { 57170034214SMatthew G. Knepley PetscInt *PETSC_RESTRICT pt; 57270034214SMatthew G. Knepley partSize++; 57370034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr); 57470034214SMatthew G. Knepley *pt = cpoint; 57570034214SMatthew G. Knepley } 57670034214SMatthew G. Knepley } 57770034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 57870034214SMatthew G. Knepley } 57970034214SMatthew G. Knepley ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 58070034214SMatthew G. Knepley ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr); 58170034214SMatthew G. Knepley ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr); 58270034214SMatthew G. Knepley ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr); 58370034214SMatthew G. Knepley for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);} 58470034214SMatthew G. Knepley } 58570034214SMatthew G. Knepley ierr = PetscBTDestroy(&bt);CHKERRQ(ierr); 58670034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr); 58770034214SMatthew G. Knepley 58870034214SMatthew G. Knepley ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 58970034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 59070034214SMatthew G. Knepley ierr = PetscMalloc1(newSize, &allPoints);CHKERRQ(ierr); 59170034214SMatthew G. Knepley 59270034214SMatthew G. Knepley ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr); 59370034214SMatthew G. Knepley for (rank = rStart; rank < rEnd; ++rank) { 59470034214SMatthew G. Knepley PetscInt numPoints, offset; 59570034214SMatthew G. Knepley 59670034214SMatthew G. Knepley ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr); 59770034214SMatthew G. Knepley ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr); 59870034214SMatthew G. Knepley ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr); 59970034214SMatthew G. Knepley packPoints += numPoints; 60070034214SMatthew G. Knepley } 60170034214SMatthew G. Knepley 60270034214SMatthew G. Knepley ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr); 60370034214SMatthew G. Knepley ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 60470034214SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 60570034214SMatthew G. Knepley PetscFunctionReturn(0); 60670034214SMatthew G. Knepley } 607