Actual source code: jostle.c
1: #define PETSCMAT_DLL
3: #include ../src/mat/impls/adj/mpi/mpiadj.h
5: #ifdef PETSC_HAVE_UNISTD_H
6: #include <unistd.h>
7: #endif
9: #ifdef PETSC_HAVE_STDLIB_H
10: #include <stdlib.h>
11: #endif
13: #include "petscfix.h"
17: #include "jostle.h"
18: /* this function is not declared in 'jostle.h' */
23: typedef struct {
24: int output;
25: int coarse_seq;
26: int nbvtxcoarsed; /* number of vertices for the coarse graph */
27: char *mesg_log;
28: } MatPartitioning_Jostle;
30: #define SIZE_LOG 10000 /* size of buffer for msg_log */
34: static PetscErrorCode MatPartitioningApply_Jostle(MatPartitioning part, IS * partitioning)
35: {
37: int size, rank, i;
38: Mat mat = part->adj, matMPI;
39: Mat_MPIAdj *adj = (Mat_MPIAdj *) mat->data;
40: MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
41: PetscTruth flg;
42: #ifdef PETSC_HAVE_UNISTD_H
43: int fd_stdout, fd_pipe[2], count,err;
44: #endif
48: /* check that the number of partitions is equal to the number of processors */
49: MPI_Comm_rank(((PetscObject)mat)->comm, &rank);
50: MPI_Comm_size(((PetscObject)mat)->comm, &size);
51: if (part->n != size) SETERRQ(PETSC_ERR_SUP, "Supports exactly one domain per processor");
53: /* convert adjacency matrix to MPIAdj if needed*/
54: PetscTypeCompare((PetscObject) mat, MATMPIADJ, &flg);
55: if (!flg) {
56: MatConvert(mat, MATMPIADJ, MAT_INITIAL_MATRIX, &matMPI);
57: } else {
58: matMPI = mat;
59: }
61: adj = (Mat_MPIAdj *) matMPI->data; /* adj contains adjacency graph */
62: {
63: /* definition of Jostle library arguments */
64: int nnodes = matMPI->M; /* number of vertices in full graph */
65: int offset = 0; /* 0 for C array indexing */
66: int core = matMPI->m;
67: int halo = 0; /* obsolete with contiguous format */
68: int *index_jostle; /* contribution of each processor */
69: int nparts = part->n;
70: int *part_wt = NULL;
72: int *partition; /* set number of each vtx (length n) */
73: int *degree; /* degree for each core nodes */
74: int *edges = adj->j;
75: int *node_wt = NULL; /* nodes weights */
76: int *edge_wt = NULL; /* edges weights */
77: double *coords = NULL; /* not used (cf jostle documentation) */
79: int local_nedges = adj->nz;
80: int dimension = 0; /* not used */
81: int output_level = jostle_struct->output;
82: char env_str[256];
84: /* allocate index_jostle */
85: PetscMalloc(nparts * sizeof(int), &index_jostle);
87: /* compute number of core nodes for each one */
88: for (i = 0; i < nparts - 1; i++)
89: index_jostle[i] = adj->rowners[i + 1] - adj->rowners[i];
90: index_jostle[nparts - 1] = nnodes - adj->rowners[nparts - 1];
92: /* allocate the partition vector */
93: PetscMalloc(core * sizeof(int), &partition);
95: /* build the degree vector and the local_nedges value */
96: PetscMalloc(core * sizeof(int), °ree);
97: for (i = 0; i < core; i++)
98: degree[i] = adj->i[i + 1] - adj->i[i];
100: /* library call */
101: pjostle_init(&size, &rank);
102: pjostle_comm(&((PetscObject)matMPI)->comm);
103: jostle_env("format = contiguous");
104: jostle_env("timer = off");
106: sprintf(env_str, "threshold = %d", jostle_struct->nbvtxcoarsed);
107: jostle_env(env_str);
109: if (jostle_struct->coarse_seq)
110: jostle_env("matching = local");
112: /* redirect output */
113: #ifdef PETSC_HAVE_UNISTD_H
114: fd_stdout = dup(1);
115: pipe(fd_pipe);
116: close(1);
117: dup2(fd_pipe[1], 1);
118: #endif
120: pjostle(&nnodes, &offset, &core, &halo, index_jostle, degree, node_wt,
121: partition, &local_nedges, edges, edge_wt, &nparts,
122: part_wt, &output_level, &dimension, coords);
124: printf("Jostle Partitioner statistics\ncut : %d, balance : %f, runtime : %f, mem used : %d\n",
125: jostle_cut(), jostle_bal(), jostle_tim(), jostle_mem());
127: #ifdef PETSC_HAVE_UNISTD_H
128: PetscMalloc(SIZE_LOG * sizeof(char), &(jostle_struct->mesg_log));
129: err = fflush(stdout);
130: if (err) SETERRQ(PETSC_ERR_SYS,"fflush() failed on stdout");
131: count = read(fd_pipe[0], jostle_struct->mesg_log, (SIZE_LOG - 1) * sizeof(char));
132: if (count < 0)
133: count = 0;
134: jostle_struct->mesg_log[count] = 0;
135: close(1);
136: dup2(fd_stdout, 1);
137: close(fd_stdout);
138: close(fd_pipe[0]);
139: close(fd_pipe[1]);
140: #endif
142: /* We free the memory used by jostle */
143: PetscFree(index_jostle);
144: PetscFree(degree);
146: /* Creation of the index set */
147: ISCreateGeneral(((PetscObject)part)->comm, mat->m, partition, partitioning);
149: if (matMPI != mat) {
150: MatDestroy(matMPI);
151: }
153: PetscFree(partition);
154: }
156: return(0);
157: }
162: PetscErrorCode MatPartitioningView_Jostle(MatPartitioning part, PetscViewer viewer)
163: {
164: MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
165: PetscErrorCode ierr;
166: PetscTruth iascii;
169: PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_ASCII, &iascii);
170: if (iascii) {
171: if (jostle_struct->mesg_log) {
172: PetscViewerASCIIPrintf(viewer, "%s\n", jostle_struct->mesg_log);
173: }
174: } else {
175: SETERRQ1(PETSC_ERR_SUP, "Viewer type %s not supported for this Jostle partitioner",((PetscObject)viewer)->type_name);
176: }
177: return(0);
178: }
182: /*@
183: MatPartitioningJostleSetCoarseLevel - Set the coarse level
184:
185: Input Parameter:
186: . part - the partitioning context
187: . level - the coarse level in range [0.0,1.0]
189: Level: advanced
191: @*/
192: PetscErrorCode MatPartitioningJostleSetCoarseLevel(MatPartitioning part, PetscReal level)
193: {
194: MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
198: if (level < 0.0 || level > 1.0) {
199: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,
200: "Jostle: level of coarsening out of range [0.0-1.0]");
201: } else
202: jostle_struct->nbvtxcoarsed = (int)(part->adj->N * level);
204: if (jostle_struct->nbvtxcoarsed < 20)
205: jostle_struct->nbvtxcoarsed = 20;
207: return(0);
208: }
212: /*@
213: MatPartitioningJostleSetCoarseSequential - Use the sequential code to
214: do the partitioning of the coarse grid.
216: Input Parameter:
217: . part - the partitioning context
219: Level: advanced
221: @*/
222: PetscErrorCode MatPartitioningJostleSetCoarseSequential(MatPartitioning part)
223: {
224: MatPartitioning_Jostle *jostle_struct =
225: (MatPartitioning_Jostle *) part->data;
227: jostle_struct->coarse_seq = 1;
228: return(0);
229: }
233: PetscErrorCode MatPartitioningSetFromOptions_Jostle(MatPartitioning part)
234: {
236: PetscTruth flag;
237: PetscReal level;
240: PetscOptionsHead("Set Jostle partitioning options");
242: PetscOptionsReal("-mat_partitioning_jostle_coarse_level",
243: "Coarse level", "MatPartitioningJostleSetCoarseLevel", 0,
244: &level, &flag);
245: if (flag)
246: MatPartitioningJostleSetCoarseLevel(part, level);
248: PetscOptionsName("-mat_partitioning_jostle_coarse_sequential",
249: "Use sequential coarse partitioner",
250: "MatPartitioningJostleSetCoarseSequential", &flag);
251: if (flag) {
252: MatPartitioningJostleSetCoarseSequential(part);
253: }
255: PetscOptionsTail();
256: return(0);
257: }
262: PetscErrorCode MatPartitioningDestroy_Jostle(MatPartitioning part)
263: {
264: MatPartitioning_Jostle *jostle_struct = (MatPartitioning_Jostle *) part->data;
265: PetscErrorCode ierr;
268: PetscFree(jostle_struct->mesg_log);
269: PetscFree(jostle_struct);
270: return(0);
271: }
273: /*MC
274: MAT_PARTITIONING_JOSTLE - Creates a partitioning context via the external package Jostle.
276: Collective on MPI_Comm
278: Input Parameter:
279: . part - the partitioning context
281: Options Database Keys:
282: + -mat_partitioning_jostle_coarse_level <0>: Coarse level (MatPartitioningJostleSetCoarseLevel)
283: - -mat_partitioning_jostle_coarse_sequential: Use sequential coarse partitioner (MatPartitioningJostleSetCoarseSequential)
285: Level: beginner
287: Notes: See http://www.gre.ac.uk/~c.walshaw/jostle/
289: .keywords: Partitioning, create, context
291: .seealso: MatPartitioningSetType(), MatPartitioningType
293: M*/
298: PetscErrorCode MatPartitioningCreate_Jostle(MatPartitioning part)
299: {
301: MatPartitioning_Jostle *jostle_struct;
304: PetscNewLog(part,MatPartitioning_Jostle, &jostle_struct);
305: part->data = (void*) jostle_struct;
307: jostle_struct->nbvtxcoarsed = 20;
308: jostle_struct->output = 0;
309: jostle_struct->coarse_seq = 0;
310: jostle_struct->mesg_log = NULL;
312: part->ops->apply = MatPartitioningApply_Jostle;
313: part->ops->view = MatPartitioningView_Jostle;
314: part->ops->destroy = MatPartitioningDestroy_Jostle;
315: part->ops->setfromoptions = MatPartitioningSetFromOptions_Jostle;
317: return(0);
318: }