Actual source code: chaco.c

  1: #include <../src/mat/impls/adj/mpi/mpiadj.h>

  3: #if defined(PETSC_HAVE_UNISTD_H)
  4:   #include <unistd.h>
  5: #endif

  7: #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT)
  8:   #include <chaco.h>
  9: #else
 10: /* Older versions of Chaco do not have an include file */
 11: 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);
 12: #endif

 14: extern int FREE_GRAPH;

 16: /*
 17: int       nvtxs;                number of vertices in full graph
 18: int      *start;                start of edge list for each vertex
 19: int      *adjacency;            edge list data
 20: int      *vwgts;                weights for all vertices
 21: float    *ewgts;                weights for all edges
 22: float    *x, *y, *z;            coordinates for inertial method
 23: char     *outassignname;        name of assignment output file
 24: char     *outfilename;          output file name
 25: short    *assignment;           set number of each vtx (length n)
 26: int       architecture;         0 => hypercube, d => d-dimensional mesh
 27: int       ndims_tot;            total number of cube dimensions to divide
 28: int       mesh_dims[3];         dimensions of mesh of processors
 29: double   *goal;                 desired set sizes for each set
 30: int       global_method;        global partitioning algorithm
 31: int       local_method;         local partitioning algorithm
 32: int       rqi_flag;             should I use RQI/Symmlq eigensolver?
 33: int       vmax;                 how many vertices to coarsen down to?
 34: int       ndims;                number of eigenvectors (2^d sets)
 35: double    eigtol;               tolerance on eigenvectors
 36: long      seed;                 for random graph mutations
 37: */

 39: typedef struct {
 40:   PetscBool         verbose;
 41:   PetscInt          eignum;
 42:   PetscReal         eigtol;
 43:   MPChacoGlobalType global_method; /* global method */
 44:   MPChacoLocalType  local_method;  /* local method */
 45:   MPChacoEigenType  eigen_method;  /* eigensolver */
 46:   PetscInt          nbvtxcoarsed;  /* number of vertices for the coarse graph */
 47: } MatPartitioning_Chaco;

 49: #define SIZE_LOG 10000 /* size of buffer for mesg_log */

 51: static PetscErrorCode MatPartitioningApply_Chaco(MatPartitioning part, IS *partitioning)
 52: {
 53:   int                    cerr;
 54:   PetscInt              *parttab, *locals, i, nb_locals, M, N;
 55:   PetscMPIInt            size, rank;
 56:   Mat                    mat = part->adj, matAdj, matSeq, *A;
 57:   Mat_MPIAdj            *adj;
 58:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;
 59:   PetscBool              flg;
 60:   IS                     isrow, iscol;
 61:   int                    nvtxs, *start, *adjacency, *vwgts, architecture, ndims_tot;
 62:   int                    mesh_dims[3], global_method, local_method, rqi_flag, vmax, ndims;
 63: #if defined(PETSC_HAVE_CHACO_INT_ASSIGNMENT)
 64:   int *assignment;
 65: #else
 66:   short *assignment;
 67: #endif
 68:   double eigtol;
 69:   long   seed;
 70:   char  *mesg_log;
 71: #if defined(PETSC_HAVE_UNISTD_H)
 72:   int fd_stdout, fd_pipe[2], count;
 73: #endif

 75:   PetscFunctionBegin;
 76:   PetscCheck(!part->use_edge_weights, PetscObjectComm((PetscObject)part), PETSC_ERR_SUP, "Chaco does not support edge weights");
 77:   FREE_GRAPH = 0; /* otherwise Chaco will attempt to free memory for adjacency graph */
 78:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
 79:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank));
 80:   PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATMPIADJ, &flg));
 81:   if (size > 1) {
 82:     if (flg) PetscCall(MatMPIAdjToSeq(mat, &matSeq));
 83:     else {
 84:       PetscCall(PetscInfo(part, "Converting distributed matrix to sequential: this could be a performance loss\n"));
 85:       PetscCall(MatGetSize(mat, &M, &N));
 86:       PetscCall(ISCreateStride(PETSC_COMM_SELF, M, 0, 1, &isrow));
 87:       PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
 88:       PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, MAT_INITIAL_MATRIX, &A));
 89:       PetscCall(ISDestroy(&isrow));
 90:       PetscCall(ISDestroy(&iscol));
 91:       matSeq = *A;
 92:       PetscCall(PetscFree(A));
 93:     }
 94:   } else {
 95:     PetscCall(PetscObjectReference((PetscObject)mat));
 96:     matSeq = mat;
 97:   }

 99:   if (!flg) { /* convert regular matrix to MPIADJ */
100:     PetscCall(MatConvert(matSeq, MATMPIADJ, MAT_INITIAL_MATRIX, &matAdj));
101:   } else {
102:     PetscCall(PetscObjectReference((PetscObject)matSeq));
103:     matAdj = matSeq;
104:   }

106:   adj = (Mat_MPIAdj *)matAdj->data; /* finally adj contains adjacency graph */

108:   /* arguments for Chaco library */
109:   nvtxs         = mat->rmap->N;         /* number of vertices in full graph */
110:   start         = adj->i;               /* start of edge list for each vertex */
111:   vwgts         = part->vertex_weights; /* weights for all vertices */
112:   architecture  = 1;                    /* 0 => hypercube, d => d-dimensional mesh */
113:   ndims_tot     = 0;                    /* total number of cube dimensions to divide */
114:   mesh_dims[0]  = part->n;              /* dimensions of mesh of processors */
115:   global_method = chaco->global_method; /* global partitioning algorithm */
116:   local_method  = chaco->local_method;  /* local partitioning algorithm */
117:   rqi_flag      = chaco->eigen_method;  /* should I use RQI/Symmlq eigensolver? */
118:   vmax          = chaco->nbvtxcoarsed;  /* how many vertices to coarsen down to? */
119:   ndims         = chaco->eignum;        /* number of eigenvectors (2^d sets) */
120:   eigtol        = chaco->eigtol;        /* tolerance on eigenvectors */
121:   seed          = 123636512;            /* for random graph mutations */

123:   PetscCall(PetscMalloc1(mat->rmap->N, &assignment));
124:   PetscCall(PetscMalloc1(start[nvtxs], &adjacency));
125:   for (i = 0; i < start[nvtxs]; i++) adjacency[i] = (adj->j)[i] + 1; /* 1-based indexing */

127:   /* redirect output to buffer */
128: #if defined(PETSC_HAVE_UNISTD_H)
129:   fd_stdout = dup(1);
130:   PetscCheck(!pipe(fd_pipe), PETSC_COMM_SELF, PETSC_ERR_SYS, "Could not open pipe");
131:   close(1);
132:   dup2(fd_pipe[1], 1);
133:   PetscCall(PetscMalloc1(SIZE_LOG, &mesg_log));
134: #endif

136:   /* library call */
137:   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);

139: #if defined(PETSC_HAVE_UNISTD_H)
140:   PetscCall(PetscFFlush(stdout));
141:   count = (int)read(fd_pipe[0], mesg_log, (int)((SIZE_LOG - 1) * sizeof(char)));
142:   if (count < 0) count = 0;
143:   mesg_log[count] = 0;
144:   close(1);
145:   dup2(fd_stdout, 1);
146:   close(fd_stdout);
147:   close(fd_pipe[0]);
148:   close(fd_pipe[1]);
149:   if (chaco->verbose) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "%s", mesg_log));
150:   PetscCall(PetscFree(mesg_log));
151: #endif
152:   PetscCheck(!cerr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Chaco failed");

154:   PetscCall(PetscMalloc1(mat->rmap->N, &parttab));
155:   for (i = 0; i < nvtxs; i++) parttab[i] = assignment[i];

157:   /* creation of the index set */
158:   nb_locals = mat->rmap->n;
159:   locals    = parttab + mat->rmap->rstart;
160:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), nb_locals, locals, PETSC_COPY_VALUES, partitioning));

162:   /* clean up */
163:   PetscCall(PetscFree(parttab));
164:   PetscCall(PetscFree(adjacency));
165:   PetscCall(PetscFree(assignment));
166:   PetscCall(MatDestroy(&matSeq));
167:   PetscCall(MatDestroy(&matAdj));
168:   PetscFunctionReturn(PETSC_SUCCESS);
169: }

171: static PetscErrorCode MatPartitioningView_Chaco(MatPartitioning part, PetscViewer viewer)
172: {
173:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;
174:   PetscBool              isascii;

176:   PetscFunctionBegin;
177:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
178:   if (isascii) {
179:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Global method: %s\n", MPChacoGlobalTypes[chaco->global_method]));
180:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local method: %s\n", MPChacoLocalTypes[chaco->local_method]));
181:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of vertices for the coarse graph: %" PetscInt_FMT "\n", chaco->nbvtxcoarsed));
182:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Eigensolver: %s\n", MPChacoEigenTypes[chaco->eigen_method]));
183:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Tolerance for eigensolver: %g\n", chaco->eigtol));
184:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of eigenvectors: %" PetscInt_FMT "\n", chaco->eignum));
185:   }
186:   PetscFunctionReturn(PETSC_SUCCESS);
187: }

189: /*@
190:   MatPartitioningChacoSetGlobal - Set the global method for Chaco partitioner.

192:   Collective

194:   Input Parameters:
195: + part   - the partitioning context
196: - method - one of `MP_CHACO_MULTILEVEL`, `MP_CHACO_SPECTRAL`, `MP_CHACO_LINEAR`,
197:             `MP_CHACO_RANDOM` or `MP_CHACO_SCATTERED`

199:   Options Database Key:
200: . -mat_partitioning_chaco_global method - the global method

202:   Level: advanced

204:   Note:
205:   The default is the multi-level method. See Chaco documentation for
206:   additional details.

208: .seealso: `MatPartitioning`, `MatPartioningSetType()`, `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetLocal()`, `MatPartitioningChacoGetGlobal()`
209: @*/
210: PetscErrorCode MatPartitioningChacoSetGlobal(MatPartitioning part, MPChacoGlobalType method)
211: {
212:   PetscFunctionBegin;
215:   PetscTryMethod(part, "MatPartitioningChacoSetGlobal_C", (MatPartitioning, MPChacoGlobalType), (part, method));
216:   PetscFunctionReturn(PETSC_SUCCESS);
217: }

219: static PetscErrorCode MatPartitioningChacoSetGlobal_Chaco(MatPartitioning part, MPChacoGlobalType method)
220: {
221:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

223:   PetscFunctionBegin;
224:   switch (method) {
225:   case MP_CHACO_MULTILEVEL:
226:   case MP_CHACO_SPECTRAL:
227:   case MP_CHACO_LINEAR:
228:   case MP_CHACO_RANDOM:
229:   case MP_CHACO_SCATTERED:
230:     chaco->global_method = method;
231:     break;
232:   default:
233:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option");
234:   }
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

238: /*@
239:   MatPartitioningChacoGetGlobal - Get the global method used by the Chaco partitioner.

241:   Not Collective

243:   Input Parameter:
244: . part - the partitioning context

246:   Output Parameter:
247: . method - the method

249:   Level: advanced

251: .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetGlobal()`
252: @*/
253: PetscErrorCode MatPartitioningChacoGetGlobal(MatPartitioning part, MPChacoGlobalType *method)
254: {
255:   PetscFunctionBegin;
257:   PetscAssertPointer(method, 2);
258:   PetscTryMethod(part, "MatPartitioningChacoGetGlobal_C", (MatPartitioning, MPChacoGlobalType *), (part, method));
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: static PetscErrorCode MatPartitioningChacoGetGlobal_Chaco(MatPartitioning part, MPChacoGlobalType *method)
263: {
264:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

266:   PetscFunctionBegin;
267:   *method = chaco->global_method;
268:   PetscFunctionReturn(PETSC_SUCCESS);
269: }

271: /*@
272:   MatPartitioningChacoSetLocal - Set the local method for the Chaco partitioner.

274:   Collective

276:   Input Parameters:
277: + part   - the partitioning context
278: - method - one of `MP_CHACO_KERNIGHAN` or `MP_CHACO_NONE`

280:   Options Database Key:
281: . -mat_partitioning_chaco_local method - the local method

283:   Level: advanced

285:   Note:
286:   The default is to apply the Kernighan-Lin heuristic. See Chaco documentation
287:   for additional details.

289: .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetGlobal()`, `MatPartitioningChacoGetLocal()`
290: @*/
291: PetscErrorCode MatPartitioningChacoSetLocal(MatPartitioning part, MPChacoLocalType method)
292: {
293:   PetscFunctionBegin;
296:   PetscTryMethod(part, "MatPartitioningChacoSetLocal_C", (MatPartitioning, MPChacoLocalType), (part, method));
297:   PetscFunctionReturn(PETSC_SUCCESS);
298: }

300: static PetscErrorCode MatPartitioningChacoSetLocal_Chaco(MatPartitioning part, MPChacoLocalType method)
301: {
302:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

304:   PetscFunctionBegin;
305:   switch (method) {
306:   case MP_CHACO_KERNIGHAN:
307:   case MP_CHACO_NONE:
308:     chaco->local_method = method;
309:     break;
310:   default:
311:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option");
312:   }
313:   PetscFunctionReturn(PETSC_SUCCESS);
314: }

316: /*@
317:   MatPartitioningChacoGetLocal - Get local method used by the Chaco partitioner.

319:   Not Collective

321:   Input Parameter:
322: . part - the partitioning context

324:   Output Parameter:
325: . method - the method

327:   Level: advanced

329: .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetLocal()`
330: @*/
331: PetscErrorCode MatPartitioningChacoGetLocal(MatPartitioning part, MPChacoLocalType *method)
332: {
333:   PetscFunctionBegin;
335:   PetscAssertPointer(method, 2);
336:   PetscUseMethod(part, "MatPartitioningChacoGetLocal_C", (MatPartitioning, MPChacoLocalType *), (part, method));
337:   PetscFunctionReturn(PETSC_SUCCESS);
338: }

340: static PetscErrorCode MatPartitioningChacoGetLocal_Chaco(MatPartitioning part, MPChacoLocalType *method)
341: {
342:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

344:   PetscFunctionBegin;
345:   *method = chaco->local_method;
346:   PetscFunctionReturn(PETSC_SUCCESS);
347: }

349: /*@
350:   MatPartitioningChacoSetCoarseLevel - Set the coarse level parameter for the
351:   Chaco partitioner.

353:   Collective

355:   Input Parameters:
356: + part  - the partitioning context
357: - level - the coarse level in range [0.0,1.0]

359:   Options Database Key:
360: . -mat_partitioning_chaco_coarse l - Coarse level

362:   Level: advanced

364: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`
365: @*/
366: PetscErrorCode MatPartitioningChacoSetCoarseLevel(MatPartitioning part, PetscReal level)
367: {
368:   PetscFunctionBegin;
371:   PetscTryMethod(part, "MatPartitioningChacoSetCoarseLevel_C", (MatPartitioning, PetscReal), (part, level));
372:   PetscFunctionReturn(PETSC_SUCCESS);
373: }

375: static PetscErrorCode MatPartitioningChacoSetCoarseLevel_Chaco(MatPartitioning part, PetscReal level)
376: {
377:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

379:   PetscFunctionBegin;
380:   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]");
381:   chaco->nbvtxcoarsed = (PetscInt)(part->adj->cmap->N * level);
382:   if (chaco->nbvtxcoarsed < 20) chaco->nbvtxcoarsed = 20;
383:   PetscFunctionReturn(PETSC_SUCCESS);
384: }

386: /*@
387:   MatPartitioningChacoSetEigenSolver - Set the eigensolver method for Chaco partitioner.

389:   Collective

391:   Input Parameters:
392: + part   - the partitioning context
393: - method - one of `MP_CHACO_LANCZOS` or `MP_CHACO_RQI`

395:   Options Database Key:
396: . -mat_partitioning_chaco_eigen_solver method - the eigensolver

398:   Level: advanced

400:   Note:
401:   The default is to use a Lanczos method. See Chaco documentation for details.

403: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenTol()`, `MatPartitioningChacoSetEigenNumber()`,
404:           `MatPartitioningChacoGetEigenSolver()`
405: @*/
406: PetscErrorCode MatPartitioningChacoSetEigenSolver(MatPartitioning part, MPChacoEigenType method)
407: {
408:   PetscFunctionBegin;
411:   PetscTryMethod(part, "MatPartitioningChacoSetEigenSolver_C", (MatPartitioning, MPChacoEigenType), (part, method));
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }

415: static PetscErrorCode MatPartitioningChacoSetEigenSolver_Chaco(MatPartitioning part, MPChacoEigenType method)
416: {
417:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

419:   PetscFunctionBegin;
420:   switch (method) {
421:   case MP_CHACO_LANCZOS:
422:   case MP_CHACO_RQI:
423:     chaco->eigen_method = method;
424:     break;
425:   default:
426:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Chaco: Unknown or unsupported option");
427:   }
428:   PetscFunctionReturn(PETSC_SUCCESS);
429: }

431: /*@
432:   MatPartitioningChacoGetEigenSolver - Get the eigensolver used by the Chaco partitioner.

434:   Not Collective

436:   Input Parameter:
437: . part - the partitioning context

439:   Output Parameter:
440: . method - the method

442:   Level: advanced

444: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`
445: @*/
446: PetscErrorCode MatPartitioningChacoGetEigenSolver(MatPartitioning part, MPChacoEigenType *method)
447: {
448:   PetscFunctionBegin;
450:   PetscAssertPointer(method, 2);
451:   PetscUseMethod(part, "MatPartitioningChacoGetEigenSolver_C", (MatPartitioning, MPChacoEigenType *), (part, method));
452:   PetscFunctionReturn(PETSC_SUCCESS);
453: }

455: static PetscErrorCode MatPartitioningChacoGetEigenSolver_Chaco(MatPartitioning part, MPChacoEigenType *method)
456: {
457:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

459:   PetscFunctionBegin;
460:   *method = chaco->eigen_method;
461:   PetscFunctionReturn(PETSC_SUCCESS);
462: }

464: /*@
465:   MatPartitioningChacoSetEigenTol - Sets the tolerance for the eigensolver used by Chaco

467:   Collective

469:   Input Parameters:
470: + part - the partitioning context
471: - tol  - the tolerance

473:   Options Database Key:
474: . -mat_partitioning_chaco_eigen_tol tol - Tolerance for eigensolver

476:   Note:
477:   Must be positive. The default value is 0.001.

479:   Level: advanced

481: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`, `MatPartitioningChacoGetEigenTol()`
482: @*/
483: PetscErrorCode MatPartitioningChacoSetEigenTol(MatPartitioning part, PetscReal tol)
484: {
485:   PetscFunctionBegin;
488:   PetscTryMethod(part, "MatPartitioningChacoSetEigenTol_C", (MatPartitioning, PetscReal), (part, tol));
489:   PetscFunctionReturn(PETSC_SUCCESS);
490: }

492: static PetscErrorCode MatPartitioningChacoSetEigenTol_Chaco(MatPartitioning part, PetscReal tol)
493: {
494:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

496:   PetscFunctionBegin;
497:   if (tol == PETSC_DEFAULT) chaco->eigtol = 0.001;
498:   else {
499:     PetscCheck(tol > 0.0, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Tolerance must be positive");
500:     chaco->eigtol = tol;
501:   }
502:   PetscFunctionReturn(PETSC_SUCCESS);
503: }

505: /*@
506:   MatPartitioningChacoGetEigenTol - Gets the eigensolver tolerance used by Chaco

508:   Not Collective

510:   Input Parameter:
511: . part - the partitioning context

513:   Output Parameter:
514: . tol - the tolerance

516:   Level: advanced

518: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenTol()`
519: @*/
520: PetscErrorCode MatPartitioningChacoGetEigenTol(MatPartitioning part, PetscReal *tol)
521: {
522:   PetscFunctionBegin;
524:   PetscAssertPointer(tol, 2);
525:   PetscUseMethod(part, "MatPartitioningChacoGetEigenTol_C", (MatPartitioning, PetscReal *), (part, tol));
526:   PetscFunctionReturn(PETSC_SUCCESS);
527: }

529: static PetscErrorCode MatPartitioningChacoGetEigenTol_Chaco(MatPartitioning part, PetscReal *tol)
530: {
531:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

533:   PetscFunctionBegin;
534:   *tol = chaco->eigtol;
535:   PetscFunctionReturn(PETSC_SUCCESS);
536: }

538: /*@
539:   MatPartitioningChacoSetEigenNumber - Sets the number of eigenvectors to compute by Chaco during partitioning
540:   during partitioning.

542:   Collective

544:   Input Parameters:
545: + part - the partitioning context
546: - num  - the number of eigenvectors

548:   Options Database Key:
549: . -mat_partitioning_chaco_eigen_number n - Number of eigenvectors

551:   Note:
552:   Accepted values are 1, 2 or 3, indicating partitioning by bisection,
553:   quadrisection, or octosection.

555:   Level: advanced

557: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`, `MatPartitioningChacoGetEigenTol()`
558: @*/
559: PetscErrorCode MatPartitioningChacoSetEigenNumber(MatPartitioning part, PetscInt num)
560: {
561:   PetscFunctionBegin;
564:   PetscTryMethod(part, "MatPartitioningChacoSetEigenNumber_C", (MatPartitioning, PetscInt), (part, num));
565:   PetscFunctionReturn(PETSC_SUCCESS);
566: }

568: static PetscErrorCode MatPartitioningChacoSetEigenNumber_Chaco(MatPartitioning part, PetscInt num)
569: {
570:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

572:   PetscFunctionBegin;
573:   if (num == PETSC_DEFAULT) chaco->eignum = 1;
574:   else {
575:     PetscCheck(num >= 1 && num <= 3, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Can only specify 1, 2 or 3 eigenvectors");
576:     chaco->eignum = num;
577:   }
578:   PetscFunctionReturn(PETSC_SUCCESS);
579: }

581: /*@
582:   MatPartitioningChacoGetEigenNumber - Gets the number of eigenvectors used by Chaco.

584:   Not Collective

586:   Input Parameter:
587: . part - the partitioning context

589:   Output Parameter:
590: . num - number of eigenvectors

592:   Level: advanced

594: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenNumber()`
595: @*/
596: PetscErrorCode MatPartitioningChacoGetEigenNumber(MatPartitioning part, PetscInt *num)
597: {
598:   PetscFunctionBegin;
600:   PetscAssertPointer(num, 2);
601:   PetscUseMethod(part, "MatPartitioningChacoGetEigenNumber_C", (MatPartitioning, PetscInt *), (part, num));
602:   PetscFunctionReturn(PETSC_SUCCESS);
603: }

605: static PetscErrorCode MatPartitioningChacoGetEigenNumber_Chaco(MatPartitioning part, PetscInt *num)
606: {
607:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

609:   PetscFunctionBegin;
610:   *num = chaco->eignum;
611:   PetscFunctionReturn(PETSC_SUCCESS);
612: }

614: static PetscErrorCode MatPartitioningSetFromOptions_Chaco(MatPartitioning part, PetscOptionItems PetscOptionsObject)
615: {
616:   PetscInt               i;
617:   PetscReal              r;
618:   PetscBool              flag;
619:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;
620:   MPChacoGlobalType      global;
621:   MPChacoLocalType       local;
622:   MPChacoEigenType       eigen;

624:   PetscFunctionBegin;
625:   PetscOptionsHeadBegin(PetscOptionsObject, "Chaco partitioning options");
626:   PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_global", "Global method", "MatPartitioningChacoSetGlobal", MPChacoGlobalTypes, (PetscEnum)chaco->global_method, (PetscEnum *)&global, &flag));
627:   if (flag) PetscCall(MatPartitioningChacoSetGlobal(part, global));
628:   PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_local", "Local method", "MatPartitioningChacoSetLocal", MPChacoLocalTypes, (PetscEnum)chaco->local_method, (PetscEnum *)&local, &flag));
629:   if (flag) PetscCall(MatPartitioningChacoSetLocal(part, local));
630:   PetscCall(PetscOptionsReal("-mat_partitioning_chaco_coarse", "Coarse level", "MatPartitioningChacoSetCoarseLevel", 0.0, &r, &flag));
631:   if (flag) PetscCall(MatPartitioningChacoSetCoarseLevel(part, r));
632:   PetscCall(PetscOptionsEnum("-mat_partitioning_chaco_eigen_solver", "Eigensolver method", "MatPartitioningChacoSetEigenSolver", MPChacoEigenTypes, (PetscEnum)chaco->eigen_method, (PetscEnum *)&eigen, &flag));
633:   if (flag) PetscCall(MatPartitioningChacoSetEigenSolver(part, eigen));
634:   PetscCall(PetscOptionsReal("-mat_partitioning_chaco_eigen_tol", "Eigensolver tolerance", "MatPartitioningChacoSetEigenTol", chaco->eigtol, &r, &flag));
635:   if (flag) PetscCall(MatPartitioningChacoSetEigenTol(part, r));
636:   PetscCall(PetscOptionsInt("-mat_partitioning_chaco_eigen_number", "Number of eigenvectors: 1, 2, or 3 (bi-, quadri-, or octosection)", "MatPartitioningChacoSetEigenNumber", chaco->eignum, &i, &flag));
637:   if (flag) PetscCall(MatPartitioningChacoSetEigenNumber(part, i));
638:   PetscCall(PetscOptionsBool("-mat_partitioning_chaco_verbose", "Show library output", "", chaco->verbose, &chaco->verbose, NULL));
639:   PetscOptionsHeadEnd();
640:   PetscFunctionReturn(PETSC_SUCCESS);
641: }

643: static PetscErrorCode MatPartitioningDestroy_Chaco(MatPartitioning part)
644: {
645:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

647:   PetscFunctionBegin;
648:   PetscCall(PetscFree(chaco));
649:   /* clear composed functions */
650:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetGlobal_C", NULL));
651:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetGlobal_C", NULL));
652:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetLocal_C", NULL));
653:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetLocal_C", NULL));
654:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetCoarseLevel_C", NULL));
655:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenSolver_C", NULL));
656:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenSolver_C", NULL));
657:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenTol_C", NULL));
658:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenTol_C", NULL));
659:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenNumber_C", NULL));
660:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenNumber_C", NULL));
661:   PetscFunctionReturn(PETSC_SUCCESS);
662: }

664: /*MC
665:    MATPARTITIONINGCHACO - Creates a partitioning context that uses the external package Chaco {cite}`chaco95`

667:    Level: beginner

669:    Note:
670:    Does not use the `MatPartitioningSetUseEdgeWeights()` option

672: .seealso: `MatPartitioning`, `MatPartitioningSetType()`, `MatPartitioningType`
673: M*/

675: PETSC_EXTERN PetscErrorCode MatPartitioningCreate_Chaco(MatPartitioning part)
676: {
677:   MatPartitioning_Chaco *chaco;

679:   PetscFunctionBegin;
680:   PetscCall(PetscNew(&chaco));
681:   part->data = (void *)chaco;

683:   chaco->global_method = MP_CHACO_MULTILEVEL;
684:   chaco->local_method  = MP_CHACO_KERNIGHAN;
685:   chaco->eigen_method  = MP_CHACO_LANCZOS;
686:   chaco->nbvtxcoarsed  = 200;
687:   chaco->eignum        = 1;
688:   chaco->eigtol        = 0.001;
689:   chaco->verbose       = PETSC_FALSE;

691:   part->ops->apply          = MatPartitioningApply_Chaco;
692:   part->ops->view           = MatPartitioningView_Chaco;
693:   part->ops->destroy        = MatPartitioningDestroy_Chaco;
694:   part->ops->setfromoptions = MatPartitioningSetFromOptions_Chaco;

696:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetGlobal_C", MatPartitioningChacoSetGlobal_Chaco));
697:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetGlobal_C", MatPartitioningChacoGetGlobal_Chaco));
698:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetLocal_C", MatPartitioningChacoSetLocal_Chaco));
699:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetLocal_C", MatPartitioningChacoGetLocal_Chaco));
700:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetCoarseLevel_C", MatPartitioningChacoSetCoarseLevel_Chaco));
701:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenSolver_C", MatPartitioningChacoSetEigenSolver_Chaco));
702:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenSolver_C", MatPartitioningChacoGetEigenSolver_Chaco));
703:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenTol_C", MatPartitioningChacoSetEigenTol_Chaco));
704:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenTol_C", MatPartitioningChacoGetEigenTol_Chaco));
705:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoSetEigenNumber_C", MatPartitioningChacoSetEigenNumber_Chaco));
706:   PetscCall(PetscObjectComposeFunction((PetscObject)part, "MatPartitioningChacoGetEigenNumber_C", MatPartitioningChacoGetEigenNumber_Chaco));
707:   PetscFunctionReturn(PETSC_SUCCESS);
708: }