Actual source code: chaco.c


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

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

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

 15: extern int FREE_GRAPH;

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

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

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

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

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

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

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

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

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

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

138:   /* library call */
139:   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);

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

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

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

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

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

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

191: /*@
192:    MatPartitioningChacoSetGlobal - Set the global method for Chaco partitioner.

194:    Collective

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

201:    Options Database Key:
202: .  -mat_partitioning_chaco_global <method> - the global method

204:    Level: advanced

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

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

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

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

240: /*@
241:    MatPartitioningChacoGetGlobal - Get the global method used by the Chaco partitioner.

243:    Not Collective

245:    Input Parameter:
246: .  part - the partitioning context

248:    Output Parameter:
249: .  method - the method

251:    Level: advanced

253: .seealso:  `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetGlobal()`
254: @*/
255: PetscErrorCode MatPartitioningChacoGetGlobal(MatPartitioning part, MPChacoGlobalType *method)
256: {
257:   PetscFunctionBegin;
260:   PetscTryMethod(part, "MatPartitioningChacoGetGlobal_C", (MatPartitioning, MPChacoGlobalType *), (part, method));
261:   PetscFunctionReturn(PETSC_SUCCESS);
262: }

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

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

273: /*@
274:    MatPartitioningChacoSetLocal - Set the local method for the Chaco partitioner.

276:    Collective

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

282:    Options Database Key:
283: .  -mat_partitioning_chaco_local <method> - the local method

285:    Level: advanced

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

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

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

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

318: /*@
319:    MatPartitioningChacoGetLocal - Get local method used by the Chaco partitioner.

321:    Not Collective

323:    Input Parameter:
324: .  part - the partitioning context

326:    Output Parameter:
327: .  method - the method

329:    Level: advanced

331: .seealso: `MatPartitioningType`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetLocal()`
332: @*/
333: PetscErrorCode MatPartitioningChacoGetLocal(MatPartitioning part, MPChacoLocalType *method)
334: {
335:   PetscFunctionBegin;
338:   PetscUseMethod(part, "MatPartitioningChacoGetLocal_C", (MatPartitioning, MPChacoLocalType *), (part, method));
339:   PetscFunctionReturn(PETSC_SUCCESS);
340: }

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

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

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

355:    Collective

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

361:    Options Database Key:
362: .  -mat_partitioning_chaco_coarse <l> - Coarse level

364:    Level: advanced

366: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`
367: @*/
368: PetscErrorCode MatPartitioningChacoSetCoarseLevel(MatPartitioning part, PetscReal level)
369: {
370:   PetscFunctionBegin;
373:   PetscTryMethod(part, "MatPartitioningChacoSetCoarseLevel_C", (MatPartitioning, PetscReal), (part, level));
374:   PetscFunctionReturn(PETSC_SUCCESS);
375: }

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

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

388: /*@
389:    MatPartitioningChacoSetEigenSolver - Set the eigensolver method for Chaco partitioner.

391:    Collective

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

397:    Options Database Key:
398: .  -mat_partitioning_chaco_eigen_solver <method> - the eigensolver

400:    Level: advanced

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

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

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

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

433: /*@
434:    MatPartitioningChacoGetEigenSolver - Get the eigensolver used by the Chaco partitioner.

436:    Not Collective

438:    Input Parameter:
439: .  part - the partitioning context

441:    Output Parameter:
442: .  method - the method

444:    Level: advanced

446: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenSolver()`
447: @*/
448: PetscErrorCode MatPartitioningChacoGetEigenSolver(MatPartitioning part, MPChacoEigenType *method)
449: {
450:   PetscFunctionBegin;
453:   PetscUseMethod(part, "MatPartitioningChacoGetEigenSolver_C", (MatPartitioning, MPChacoEigenType *), (part, method));
454:   PetscFunctionReturn(PETSC_SUCCESS);
455: }

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

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

466: /*@
467:    MatPartitioningChacoSetEigenTol - Sets the tolerance for the eigensolver used by Chaco

469:    Collective

471:    Input Parameters:
472: +  part - the partitioning context
473: -  tol  - the tolerance

475:    Options Database Key:
476: .  -mat_partitioning_chaco_eigen_tol <tol> - Tolerance for eigensolver

478:    Note:
479:    Must be positive. The default value is 0.001.

481:    Level: advanced

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

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

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

507: /*@
508:    MatPartitioningChacoGetEigenTol - Gets the eigensolver tolerance used by Chaco

510:    Not Collective

512:    Input Parameter:
513: .  part - the partitioning context

515:    Output Parameter:
516: .  tol  - the tolerance

518:    Level: advanced

520: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenTol()`
521: @*/
522: PetscErrorCode MatPartitioningChacoGetEigenTol(MatPartitioning part, PetscReal *tol)
523: {
524:   PetscFunctionBegin;
527:   PetscUseMethod(part, "MatPartitioningChacoGetEigenTol_C", (MatPartitioning, PetscReal *), (part, tol));
528:   PetscFunctionReturn(PETSC_SUCCESS);
529: }

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

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

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

544:    Collective

546:    Input Parameters:
547: +  part - the partitioning context
548: -  num  - the number of eigenvectors

550:    Options Database Key:
551: .  -mat_partitioning_chaco_eigen_number <n> - Number of eigenvectors

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

557:    Level: advanced

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

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

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

583: /*@
584:    MatPartitioningChacoGetEigenNumber - Gets the number of eigenvectors used by Chaco.

586:    Not Collective

588:    Input Parameter:
589: .  part - the partitioning context

591:    Output Parameter:
592: .  num  - number of eigenvectors

594:    Level: advanced

596: .seealso: `MatPartitioningType`, `MatPartitioning`, `MATPARTITIONINGCHACO`, `MatPartitioningChacoSetEigenNumber()`
597: @*/
598: PetscErrorCode MatPartitioningChacoGetEigenNumber(MatPartitioning part, PetscInt *num)
599: {
600:   PetscFunctionBegin;
603:   PetscUseMethod(part, "MatPartitioningChacoGetEigenNumber_C", (MatPartitioning, PetscInt *), (part, num));
604:   PetscFunctionReturn(PETSC_SUCCESS);
605: }

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

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

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

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

645: PetscErrorCode MatPartitioningDestroy_Chaco(MatPartitioning part)
646: {
647:   MatPartitioning_Chaco *chaco = (MatPartitioning_Chaco *)part->data;

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

666: /*MC
667:    MATPARTITIONINGCHACO - Creates a partitioning context that uses the external package Chaco.

669:    Level: beginner

671:    Note:
672:    Does not use the `MatPartitioningSetUseEdgeWeights()` option

674:    References:
675: .   * -  http://www.cs.sandia.gov/CRF/chac.html

677: .seealso: `MatPartitioningSetType()`, `MatPartitioningType`
678: M*/

680: PETSC_EXTERN PetscErrorCode MatPartitioningCreate_Chaco(MatPartitioning part)
681: {
682:   MatPartitioning_Chaco *chaco;

684:   PetscFunctionBegin;
685:   PetscCall(PetscNew(&chaco));
686:   part->data = (void *)chaco;

688:   chaco->global_method = MP_CHACO_MULTILEVEL;
689:   chaco->local_method  = MP_CHACO_KERNIGHAN;
690:   chaco->eigen_method  = MP_CHACO_LANCZOS;
691:   chaco->nbvtxcoarsed  = 200;
692:   chaco->eignum        = 1;
693:   chaco->eigtol        = 0.001;
694:   chaco->verbose       = PETSC_FALSE;

696:   part->ops->apply          = MatPartitioningApply_Chaco;
697:   part->ops->view           = MatPartitioningView_Chaco;
698:   part->ops->destroy        = MatPartitioningDestroy_Chaco;
699:   part->ops->setfromoptions = MatPartitioningSetFromOptions_Chaco;

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