#include <../src/mat/impls/adj/mpi/mpiadj.h> /*I "petscmat.h" I*/ #if defined(PETSC_HAVE_UNISTD_H) #include #endif #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) #include #else /* Older versions of Chaco do not have an include file */ PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts, float *ewgts, float *x, float *y, float *z, char *outassignname, char *outfilename, short *assignment, int architecture, int ndims_tot, int mesh_dims[3], double *goal, int global_method, int local_method, int rqi_flag, int vmax, int ndims, double eigtol, long seed); #endif extern int FREE_GRAPH; /* int nvtxs; number of vertices in full graph int *start; start of edge list for each vertex int *adjacency; edge list data int *vwgts; weights for all vertices float *ewgts; weights for all edges float *x, *y, *z; coordinates for inertial method char *outassignname; name of assignment output file char *outfilename; output file name short *assignment; set number of each vtx (length n) int architecture; 0 => hypercube, d => d-dimensional mesh int ndims_tot; total number of cube dimensions to divide int mesh_dims[3]; dimensions of mesh of processors double *goal; desired set sizes for each set int global_method; global partitioning algorithm int local_method; local partitioning algorithm int rqi_flag; should I use RQI/Symmlq eigensolver? int vmax; how many vertices to coarsen down to? int ndims; number of eigenvectors (2^d sets) double eigtol; tolerance on eigenvectors long seed; for random graph mutations */ typedef struct { PetscBool verbose; PetscInt eignum; PetscReal eigtol; MPChacoGlobalType global_method; /* global method */ MPChacoLocalType local_method; /* local method */ MPChacoEigenType eigen_method; /* eigensolver */ PetscInt nbvtxcoarsed; /* number of vertices for the coarse graph */ } MatPartitioning_Chaco; #define SIZE_LOG 10000 /* size of buffer for mesg_log */ static PetscErrorCode MatPartitioningApply_Chaco(MatPartitioning part, IS *partitioning) { int cerr; PetscInt *parttab, *locals, i, nb_locals, M, N; PetscMPIInt size, rank; Mat mat = part->adj, matAdj, matSeq, *A; Mat_MPIAdj *adj; MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscBool flg; IS isrow, iscol; int nvtxs, *start, *adjacency, *vwgts, architecture, ndims_tot; int mesh_dims[3], global_method, local_method, rqi_flag, vmax, ndims; #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT) int *assignment; #else short *assignment; #endif double eigtol; long seed; char *mesg_log; #if defined(PETSC_HAVE_UNISTD_H) int fd_stdout, fd_pipe[2], count; #endif PetscFunctionBegin; PetscCheck(!part->use_edge_weights, PetscObjectComm((PetscObject)part), PETSC_ERR_SUP, "Chaco does not support edge weights"); FREE_GRAPH = 0; /* otherwise Chaco will attempt to free memory for adjacency graph */ PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATMPIADJ, &flg)); if (size > 1) { if (flg) { PetscCall(MatMPIAdjToSeq(mat, &matSeq)); } else { PetscCall(PetscInfo(part, "Converting distributed matrix to sequential: this could be a performance loss\n")); PetscCall(MatGetSize(mat, &M, &N)); PetscCall(ISCreateStride(PETSC_COMM_SELF, M, 0, 1, &isrow)); PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, MAT_INITIAL_MATRIX, &A)); PetscCall(ISDestroy(&isrow)); PetscCall(ISDestroy(&iscol)); matSeq = *A; PetscCall(PetscFree(A)); } } else { PetscCall(PetscObjectReference((PetscObject)mat)); matSeq = mat; } if (!flg) { /* convert regular matrix to MPIADJ */ PetscCall(MatConvert(matSeq, MATMPIADJ, MAT_INITIAL_MATRIX, &matAdj)); } else { PetscCall(PetscObjectReference((PetscObject)matSeq)); matAdj = matSeq; } adj = (Mat_MPIAdj *)matAdj->data; /* finally adj contains adjacency graph */ /* arguments for Chaco library */ nvtxs = mat->rmap->N; /* number of vertices in full graph */ start = adj->i; /* start of edge list for each vertex */ vwgts = part->vertex_weights; /* weights for all vertices */ architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ ndims_tot = 0; /* total number of cube dimensions to divide */ mesh_dims[0] = part->n; /* dimensions of mesh of processors */ global_method = chaco->global_method; /* global partitioning algorithm */ local_method = chaco->local_method; /* local partitioning algorithm */ rqi_flag = chaco->eigen_method; /* should I use RQI/Symmlq eigensolver? */ vmax = chaco->nbvtxcoarsed; /* how many vertices to coarsen down to? */ ndims = chaco->eignum; /* number of eigenvectors (2^d sets) */ eigtol = chaco->eigtol; /* tolerance on eigenvectors */ seed = 123636512; /* for random graph mutations */ PetscCall(PetscMalloc1(mat->rmap->N, &assignment)); PetscCall(PetscMalloc1(start[nvtxs], &adjacency)); for (i = 0; i < start[nvtxs]; i++) adjacency[i] = (adj->j)[i] + 1; /* 1-based indexing */ /* redirect output to buffer */ #if defined(PETSC_HAVE_UNISTD_H) fd_stdout = dup(1); PetscCheck(!pipe(fd_pipe), PETSC_COMM_SELF, PETSC_ERR_SYS, "Could not open pipe"); close(1); dup2(fd_pipe[1], 1); PetscCall(PetscMalloc1(SIZE_LOG, &mesg_log)); #endif /* library call */ cerr = interface(nvtxs, start, adjacency, vwgts, NULL, NULL, NULL, NULL, NULL, NULL, assignment, architecture, ndims_tot, mesh_dims, NULL, global_method, local_method, rqi_flag, vmax, ndims, eigtol, seed); #if defined(PETSC_HAVE_UNISTD_H) PetscCall(PetscFFlush(stdout)); count = (int)read(fd_pipe[0], mesg_log, (int)((SIZE_LOG - 1) * sizeof(char))); if (count < 0) count = 0; mesg_log[count] = 0; close(1); dup2(fd_stdout, 1); close(fd_stdout); close(fd_pipe[0]); close(fd_pipe[1]); if (chaco->verbose) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "%s", mesg_log)); PetscCall(PetscFree(mesg_log)); #endif PetscCheck(!cerr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Chaco failed"); PetscCall(PetscMalloc1(mat->rmap->N, &parttab)); for (i = 0; i < nvtxs; i++) parttab[i] = assignment[i]; /* creation of the index set */ nb_locals = mat->rmap->n; locals = parttab + mat->rmap->rstart; PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), nb_locals, locals, PETSC_COPY_VALUES, partitioning)); /* clean up */ PetscCall(PetscFree(parttab)); PetscCall(PetscFree(adjacency)); PetscCall(PetscFree(assignment)); PetscCall(MatDestroy(&matSeq)); PetscCall(MatDestroy(&matAdj)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningView_Chaco(MatPartitioning part, PetscViewer viewer) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscBool isascii; PetscFunctionBegin; PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); if (isascii) { PetscCall(PetscViewerASCIIPrintf(viewer, " Global method: %s\n", MPChacoGlobalTypes[chaco->global_method])); PetscCall(PetscViewerASCIIPrintf(viewer, " Local method: %s\n", MPChacoLocalTypes[chaco->local_method])); PetscCall(PetscViewerASCIIPrintf(viewer, " Number of vertices for the coarse graph: %" PetscInt_FMT "\n", chaco->nbvtxcoarsed)); PetscCall(PetscViewerASCIIPrintf(viewer, " Eigensolver: %s\n", MPChacoEigenTypes[chaco->eigen_method])); PetscCall(PetscViewerASCIIPrintf(viewer, " Tolerance for eigensolver: %g\n", chaco->eigtol)); PetscCall(PetscViewerASCIIPrintf(viewer, " Number of eigenvectors: %" PetscInt_FMT "\n", chaco->eignum)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetGlobal - Set the global method for Chaco partitioner. Collective Input Parameters: + part - the partitioning context - method - one of `MP_CHACO_MULTILEVEL`, `MP_CHACO_SPECTRAL`, `MP_CHACO_LINEAR`, `MP_CHACO_RANDOM` or `MP_CHACO_SCATTERED` Options Database Key: . -mat_partitioning_chaco_global - the global method Level: advanced Note: The default is the multi-level method. See Chaco documentation for additional details. .seealso: `MatPartitioning`, `MatPartioningSetType()`, `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetLocal()`, `MatPartitioningChacoGetGlobal()` @*/ PetscErrorCode MatPartitioningChacoSetGlobal(MatPartitioning part, MPChacoGlobalType method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveEnum(part, method, 2); PetscTryMethod(part, "MatPartitioningChacoSetGlobal_C", (MatPartitioning, MPChacoGlobalType), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetGlobal_Chaco(MatPartitioning part, MPChacoGlobalType method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; switch (method) { case MP_CHACO_MULTILEVEL: case MP_CHACO_SPECTRAL: case MP_CHACO_LINEAR: case MP_CHACO_RANDOM: case MP_CHACO_SCATTERED: chaco->global_method = method; break; default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option"); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoGetGlobal - Get the global method used by the Chaco partitioner. Not Collective Input Parameter: . part - the partitioning context Output Parameter: . method - the method Level: advanced .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetGlobal()` @*/ PetscErrorCode MatPartitioningChacoGetGlobal(MatPartitioning part, MPChacoGlobalType *method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscAssertPointer(method, 2); PetscTryMethod(part, "MatPartitioningChacoGetGlobal_C", (MatPartitioning, MPChacoGlobalType *), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoGetGlobal_Chaco(MatPartitioning part, MPChacoGlobalType *method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; *method = chaco->global_method; PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetLocal - Set the local method for the Chaco partitioner. Collective Input Parameters: + part - the partitioning context - method - one of `MP_CHACO_KERNIGHAN` or `MP_CHACO_NONE` Options Database Key: . -mat_partitioning_chaco_local - the local method Level: advanced Note: The default is to apply the Kernighan-Lin heuristic. See Chaco documentation for additional details. .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetGlobal()`, `MatPartitioningChacoGetLocal()` @*/ PetscErrorCode MatPartitioningChacoSetLocal(MatPartitioning part, MPChacoLocalType method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveEnum(part, method, 2); PetscTryMethod(part, "MatPartitioningChacoSetLocal_C", (MatPartitioning, MPChacoLocalType), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetLocal_Chaco(MatPartitioning part, MPChacoLocalType method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; switch (method) { case MP_CHACO_KERNIGHAN: case MP_CHACO_NONE: chaco->local_method = method; break; default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option"); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoGetLocal - Get local method used by the Chaco partitioner. Not Collective Input Parameter: . part - the partitioning context Output Parameter: . method - the method Level: advanced .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetLocal()` @*/ PetscErrorCode MatPartitioningChacoGetLocal(MatPartitioning part, MPChacoLocalType *method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscAssertPointer(method, 2); PetscUseMethod(part, "MatPartitioningChacoGetLocal_C", (MatPartitioning, MPChacoLocalType *), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoGetLocal_Chaco(MatPartitioning part, MPChacoLocalType *method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; *method = chaco->local_method; PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetCoarseLevel - Set the coarse level parameter for the Chaco partitioner. Collective Input Parameters: + part - the partitioning context - level - the coarse level in range [0.0,1.0] Options Database Key: . -mat_partitioning_chaco_coarse - Coarse level Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO` @*/ PetscErrorCode MatPartitioningChacoSetCoarseLevel(MatPartitioning part, PetscReal level) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveReal(part, level, 2); PetscTryMethod(part, "MatPartitioningChacoSetCoarseLevel_C", (MatPartitioning, PetscReal), (part, level)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetCoarseLevel_Chaco(MatPartitioning part, PetscReal level) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; PetscCheck(level >= 0.0 && level < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Chaco: level of coarsening out of range [0.0-1.0]"); chaco->nbvtxcoarsed = (PetscInt)(part->adj->cmap->N * level); if (chaco->nbvtxcoarsed < 20) chaco->nbvtxcoarsed = 20; PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetEigenSolver - Set the eigensolver method for Chaco partitioner. Collective Input Parameters: + part - the partitioning context - method - one of `MP_CHACO_LANCZOS` or `MP_CHACO_RQI` Options Database Key: . -mat_partitioning_chaco_eigen_solver - the eigensolver Level: advanced Note: The default is to use a Lanczos method. See Chaco documentation for details. .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenTol()`, `MatPartitioningChacoSetEigenNumber()`, `MatPartitioningChacoGetEigenSolver()` @*/ PetscErrorCode MatPartitioningChacoSetEigenSolver(MatPartitioning part, MPChacoEigenType method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveEnum(part, method, 2); PetscTryMethod(part, "MatPartitioningChacoSetEigenSolver_C", (MatPartitioning, MPChacoEigenType), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetEigenSolver_Chaco(MatPartitioning part, MPChacoEigenType method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; switch (method) { case MP_CHACO_LANCZOS: case MP_CHACO_RQI: chaco->eigen_method = method; break; default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option"); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoGetEigenSolver - Get the eigensolver used by the Chaco partitioner. Not Collective Input Parameter: . part - the partitioning context Output Parameter: . method - the method Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()` @*/ PetscErrorCode MatPartitioningChacoGetEigenSolver(MatPartitioning part, MPChacoEigenType *method) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscAssertPointer(method, 2); PetscUseMethod(part, "MatPartitioningChacoGetEigenSolver_C", (MatPartitioning, MPChacoEigenType *), (part, method)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoGetEigenSolver_Chaco(MatPartitioning part, MPChacoEigenType *method) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; *method = chaco->eigen_method; PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetEigenTol - Sets the tolerance for the eigensolver used by Chaco Collective Input Parameters: + part - the partitioning context - tol - the tolerance Options Database Key: . -mat_partitioning_chaco_eigen_tol - Tolerance for eigensolver Note: Must be positive. The default value is 0.001. Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`, `MatPartitioningChacoGetEigenTol()` @*/ PetscErrorCode MatPartitioningChacoSetEigenTol(MatPartitioning part, PetscReal tol) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveReal(part, tol, 2); PetscTryMethod(part, "MatPartitioningChacoSetEigenTol_C", (MatPartitioning, PetscReal), (part, tol)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetEigenTol_Chaco(MatPartitioning part, PetscReal tol) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; if (tol == PETSC_DEFAULT) chaco->eigtol = 0.001; else { PetscCheck(tol > 0.0, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Tolerance must be positive"); chaco->eigtol = tol; } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoGetEigenTol - Gets the eigensolver tolerance used by Chaco Not Collective Input Parameter: . part - the partitioning context Output Parameter: . tol - the tolerance Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenTol()` @*/ PetscErrorCode MatPartitioningChacoGetEigenTol(MatPartitioning part, PetscReal *tol) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscAssertPointer(tol, 2); PetscUseMethod(part, "MatPartitioningChacoGetEigenTol_C", (MatPartitioning, PetscReal *), (part, tol)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoGetEigenTol_Chaco(MatPartitioning part, PetscReal *tol) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; *tol = chaco->eigtol; PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoSetEigenNumber - Sets the number of eigenvectors to compute by Chaco during partitioning during partitioning. Collective Input Parameters: + part - the partitioning context - num - the number of eigenvectors Options Database Key: . -mat_partitioning_chaco_eigen_number - Number of eigenvectors Note: Accepted values are 1, 2 or 3, indicating partitioning by bisection, quadrisection, or octosection. Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`, `MatPartitioningChacoGetEigenTol()` @*/ PetscErrorCode MatPartitioningChacoSetEigenNumber(MatPartitioning part, PetscInt num) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscValidLogicalCollectiveInt(part, num, 2); PetscTryMethod(part, "MatPartitioningChacoSetEigenNumber_C", (MatPartitioning, PetscInt), (part, num)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoSetEigenNumber_Chaco(MatPartitioning part, PetscInt num) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; if (num == PETSC_DEFAULT) chaco->eignum = 1; else { PetscCheck(num >= 1 && num <= 3, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Can only specify 1, 2 or 3 eigenvectors"); chaco->eignum = num; } PetscFunctionReturn(PETSC_SUCCESS); } /*@ MatPartitioningChacoGetEigenNumber - Gets the number of eigenvectors used by Chaco. Not Collective Input Parameter: . part - the partitioning context Output Parameter: . num - number of eigenvectors Level: advanced .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenNumber()` @*/ PetscErrorCode MatPartitioningChacoGetEigenNumber(MatPartitioning part, PetscInt *num) { PetscFunctionBegin; PetscValidHeaderSpecific(part, MAT_PARTITIONING_CLASSID, 1); PetscAssertPointer(num, 2); PetscUseMethod(part, "MatPartitioningChacoGetEigenNumber_C", (MatPartitioning, PetscInt *), (part, num)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningChacoGetEigenNumber_Chaco(MatPartitioning part, PetscInt *num) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; *num = chaco->eignum; PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningSetFromOptions_Chaco(MatPartitioning part, PetscOptionItems PetscOptionsObject) { PetscInt i; PetscReal r; PetscBool flag; MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; MPChacoGlobalType global; MPChacoLocalType local; MPChacoEigenType eigen; PetscFunctionBegin; PetscOptionsHeadBegin(PetscOptionsObject, "Chaco partitioning options"); PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_global", "Global method", "MatPartitioningChacoSetGlobal", MPChacoGlobalTypes, (PetscEnum)chaco->global_method, (PetscEnum *)&global, &flag)); if (flag) PetscCall(MatPartitioningChacoSetGlobal(part, global)); PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_local", "Local method", "MatPartitioningChacoSetLocal", MPChacoLocalTypes, (PetscEnum)chaco->local_method, (PetscEnum *)&local, &flag)); if (flag) PetscCall(MatPartitioningChacoSetLocal(part, local)); PetscCall(PetscOptionsReal("-mat_partitioning_chaco_coarse", "Coarse level", "MatPartitioningChacoSetCoarseLevel", 0.0, &r, &flag)); if (flag) PetscCall(MatPartitioningChacoSetCoarseLevel(part, r)); PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_eigen_solver", "Eigensolver method", "MatPartitioningChacoSetEigenSolver", MPChacoEigenTypes, (PetscEnum)chaco->eigen_method, (PetscEnum *)&eigen, &flag)); if (flag) PetscCall(MatPartitioningChacoSetEigenSolver(part, eigen)); PetscCall(PetscOptionsReal("-mat_partitioning_chaco_eigen_tol", "Eigensolver tolerance", "MatPartitioningChacoSetEigenTol", chaco->eigtol, &r, &flag)); if (flag) PetscCall(MatPartitioningChacoSetEigenTol(part, r)); PetscCall(PetscOptionsInt("-mat_partitioning_chaco_eigen_number", "Number of eigenvectors: 1, 2, or 3 (bi-, quadri-, or octosection)", "MatPartitioningChacoSetEigenNumber", chaco->eignum, &i, &flag)); if (flag) PetscCall(MatPartitioningChacoSetEigenNumber(part, i)); PetscCall(PetscOptionsBool("-mat_partitioning_chaco_verbose", "Show library output", "", chaco->verbose, &chaco->verbose, NULL)); PetscOptionsHeadEnd(); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode MatPartitioningDestroy_Chaco(MatPartitioning part) { MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data; PetscFunctionBegin; PetscCall(PetscFree(chaco)); /* clear composed functions */ PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetGlobal_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetGlobal_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetLocal_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetLocal_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetCoarseLevel_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenSolver_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenSolver_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenTol_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenTol_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenNumber_C", NULL)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenNumber_C", NULL)); PetscFunctionReturn(PETSC_SUCCESS); } /*MC MATPARTITIONINGCHACO - Creates a partitioning context that uses the external package Chaco {cite}`chaco95` Level: beginner Note: Does not use the `MatPartitioningSetUseEdgeWeights()` option .seealso: `MatPartitioning`, `MatPartitioningSetType()`, `MatPartitioningType` M*/ PETSC_EXTERN PetscErrorCode MatPartitioningCreate_Chaco(MatPartitioning part) { MatPartitioning_Chaco *chaco; PetscFunctionBegin; PetscCall(PetscNew(&chaco)); part->data = (void *)chaco; chaco->global_method = MP_CHACO_MULTILEVEL; chaco->local_method = MP_CHACO_KERNIGHAN; chaco->eigen_method = MP_CHACO_LANCZOS; chaco->nbvtxcoarsed = 200; chaco->eignum = 1; chaco->eigtol = 0.001; chaco->verbose = PETSC_FALSE; part->ops->apply = MatPartitioningApply_Chaco; part->ops->view = MatPartitioningView_Chaco; part->ops->destroy = MatPartitioningDestroy_Chaco; part->ops->setfromoptions = MatPartitioningSetFromOptions_Chaco; PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetGlobal_C", MatPartitioningChacoSetGlobal_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetGlobal_C", MatPartitioningChacoGetGlobal_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetLocal_C", MatPartitioningChacoSetLocal_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetLocal_C", MatPartitioningChacoGetLocal_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetCoarseLevel_C", MatPartitioningChacoSetCoarseLevel_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenSolver_C", MatPartitioningChacoSetEigenSolver_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenSolver_C", MatPartitioningChacoGetEigenSolver_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenTol_C", MatPartitioningChacoSetEigenTol_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenTol_C", MatPartitioningChacoGetEigenTol_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenNumber_C", MatPartitioningChacoSetEigenNumber_Chaco)); PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenNumber_C", MatPartitioningChacoGetEigenNumber_Chaco)); PetscFunctionReturn(PETSC_SUCCESS); }