Actual source code: partition.c
1: /*$Id: partition.c,v 1.60 2001/06/21 21:17:23 bsmith Exp $*/
2:
3: #include src/mat/matimpl.h
5: /* Logging support */
6: int MAT_PARTITIONING_COOKIE = 0;
8: /*
9: Simplest partitioning, keeps the current partitioning.
10: */
13: static int MatPartitioningApply_Current(MatPartitioning part,IS *partitioning)
14: {
15: int ierr,m,rank,size;
18: MPI_Comm_size(part->comm,&size);
19: if (part->n != size) {
20: SETERRQ(PETSC_ERR_SUP,"Currently only supports one domain per processor");
21: }
22: MPI_Comm_rank(part->comm,&rank);
24: MatGetLocalSize(part->adj,&m,PETSC_NULL);
25: ISCreateStride(part->comm,m,rank,0,partitioning);
26: return(0);
27: }
31: static int MatPartitioningApply_Square(MatPartitioning part,IS *partitioning)
32: {
33: int cell,ierr,n,N,p,rstart,rend,*color,size;
36: MPI_Comm_size(part->comm,&size);
37: if (part->n != size) {
38: SETERRQ(PETSC_ERR_SUP,"Currently only supports one domain per processor");
39: }
40: p = (int)sqrt((double)part->n);
41: if (p*p != part->n) {
42: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires \"perfect square\" number of domains");
43: }
44: MatGetSize(part->adj,&N,PETSC_NULL);
45: n = (int)sqrt((double)N);
46: if (n*n != N) { /* This condition is NECESSARY, but NOT SUFFICIENT in order to the domain be square */
47: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires square domain");
48: }
49: if (n%p != 0) {
50: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires p to divide n");
51: }
52: MatGetOwnershipRange(part->adj,&rstart,&rend);
53: PetscMalloc((rend-rstart)*sizeof(int),&color);
54: /* for (int cell=rstart; cell<rend; cell++) { color[cell-rstart] = ((cell%n) < (n/2)) + 2 * ((cell/n) < (n/2)); } */
55: for (cell=rstart; cell<rend; cell++) {
56: color[cell-rstart] = ((cell%n) / (n/p)) + p * ((cell/n) / (n/p));
57: }
58: ISCreateGeneral(part->comm,rend-rstart,color,partitioning);
59: PetscFree(color);
61: return(0);
62: }
64: EXTERN_C_BEGIN
67: int MatPartitioningCreate_Current(MatPartitioning part)
68: {
70: part->ops->apply = MatPartitioningApply_Current;
71: part->ops->view = 0;
72: part->ops->destroy = 0;
73: return(0);
74: }
75: EXTERN_C_END
77: EXTERN_C_BEGIN
80: int MatPartitioningCreate_Square(MatPartitioning part)
81: {
83: part->ops->apply = MatPartitioningApply_Square;
84: part->ops->view = 0;
85: part->ops->destroy = 0;
86: return(0);
87: }
88: EXTERN_C_END
90: /* ===========================================================================================*/
92: #include petscsys.h
94: PetscFList MatPartitioningList = 0;
95: PetscTruth MatPartitioningRegisterAllCalled = PETSC_FALSE;
100: int MatPartitioningRegister(const char sname[],const char path[],const char name[],int (*function)(MatPartitioning))
101: {
102: int ierr;
103: char fullname[256];
106: PetscFListConcat(path,name,fullname);
107: PetscFListAdd(&MatPartitioningList,sname,fullname,(void (*)(void))function);
108: return(0);
109: }
113: /*@C
114: MatPartitioningRegisterDestroy - Frees the list of partitioning routines.
116: Not Collective
118: Level: developer
120: .keywords: matrix, register, destroy
122: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningRegisterAll()
123: @*/
124: int MatPartitioningRegisterDestroy(void)
125: {
129: if (MatPartitioningList) {
130: PetscFListDestroy(&MatPartitioningList);
131: MatPartitioningList = 0;
132: }
133: return(0);
134: }
138: /*@C
139: MatPartitioningGetType - Gets the Partitioning method type and name (as a string)
140: from the partitioning context.
142: Not collective
144: Input Parameter:
145: . partitioning - the partitioning context
147: Output Parameter:
148: . type - partitioner type
150: Level: intermediate
152: Not Collective
154: .keywords: Partitioning, get, method, name, type
155: @*/
156: int MatPartitioningGetType(MatPartitioning partitioning,MatPartitioningType *type)
157: {
159: *type = partitioning->type_name;
160: return(0);
161: }
165: /*@C
166: MatPartitioningSetNParts - Set how many partitions need to be created;
167: by default this is one per processor. Certain partitioning schemes may
168: in fact only support that option.
170: Not collective
172: Input Parameter:
173: . partitioning - the partitioning context
174: . n - the number of partitions
176: Level: intermediate
178: Not Collective
180: .keywords: Partitioning, set
182: .seealso: MatPartitioningCreate(), MatPartitioningApply()
183: @*/
184: int MatPartitioningSetNParts(MatPartitioning part,int n)
185: {
187: part->n = n;
188: return(0);
189: }
193: /*@C
194: MatPartitioningApply - Gets a partitioning for a matrix.
196: Collective on Mat
198: Input Parameters:
199: . matp - the matrix partitioning object
201: Output Parameters:
202: . partitioning - the partitioning. For each local node this tells the processor
203: number that that node is assigned to.
205: Options Database Keys:
206: To specify the partitioning through the options database, use one of
207: the following
208: $ -mat_partitioning_type parmetis, -mat_partitioning current
209: To see the partitioning result
210: $ -mat_partitioning_view
212: Level: beginner
214: The user can define additional partitionings; see MatPartitioningRegisterDynamic().
216: .keywords: matrix, get, partitioning
218: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningCreate(),
219: MatPartitioningDestroy(), MatPartitioningSetAdjacency(), ISPartitioningToNumbering(),
220: ISPartitioningCount()
221: @*/
222: int MatPartitioningApply(MatPartitioning matp,IS *partitioning)
223: {
224: int ierr;
225: PetscTruth flag;
230: if (!matp->adj->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
231: if (matp->adj->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
232: if (!matp->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set type with MatPartitioningSetFromOptions() or MatPartitioningSetType()");
233: PetscLogEventBegin(MAT_Partitioning,matp,0,0,0);
234: (*matp->ops->apply)(matp,partitioning);
235: PetscLogEventEnd(MAT_Partitioning,matp,0,0,0);
237: PetscOptionsHasName(PETSC_NULL,"-mat_partitioning_view",&flag);
238: if (flag) {
239: MatPartitioningView(matp,PETSC_VIEWER_STDOUT_(matp->comm));
240: ISView(*partitioning,PETSC_VIEWER_STDOUT_(matp->comm));
241: }
242: return(0);
243: }
244:
247: /*@C
248: MatPartitioningSetAdjacency - Sets the adjacency graph (matrix) of the thing to be
249: partitioned.
251: Collective on MatPartitioning and Mat
253: Input Parameters:
254: + part - the partitioning context
255: - adj - the adjacency matrix
257: Level: beginner
259: .keywords: Partitioning, adjacency
261: .seealso: MatPartitioningCreate()
262: @*/
263: int MatPartitioningSetAdjacency(MatPartitioning part,Mat adj)
264: {
268: part->adj = adj;
269: return(0);
270: }
274: /*@C
275: MatPartitioningDestroy - Destroys the partitioning context.
277: Collective on Partitioning
279: Input Parameters:
280: . part - the partitioning context
282: Level: beginner
284: .keywords: Partitioning, destroy, context
286: .seealso: MatPartitioningCreate()
287: @*/
288: int MatPartitioningDestroy(MatPartitioning part)
289: {
294: if (--part->refct > 0) return(0);
296: if (part->ops->destroy) {
297: (*part->ops->destroy)(part);
298: }
299: if (part->vertex_weights){
300: PetscFree(part->vertex_weights);
301: }
302: if (part->part_weights){
303: PetscFree(part->part_weights);
304: }
305: PetscLogObjectDestroy(part);
306: PetscHeaderDestroy(part);
307: return(0);
308: }
312: /*@C
313: MatPartitioningSetVertexWeights - Sets the weights for vertices for a partitioning.
315: Collective on Partitioning
317: Input Parameters:
318: + part - the partitioning context
319: - weights - the weights
321: Level: beginner
323: Notes:
324: The array weights is freed by PETSc so the user should not free the array. In C/C++
325: the array must be obtained with a call to PetscMalloc(), not malloc().
327: .keywords: Partitioning, destroy, context
329: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetPartitionWeights()
330: @*/
331: int MatPartitioningSetVertexWeights(MatPartitioning part,const int weights[])
332: {
338: if (part->vertex_weights){
339: PetscFree(part->vertex_weights);
340: }
341: part->vertex_weights = (int *)weights;
342: return(0);
343: }
347: /*@C
348: MatPartitioningSetPartitionWeights - Sets the weights for each partition.
350: Collective on Partitioning
352: Input Parameters:
353: + part - the partitioning context
354: - weights - the weights
356: Level: beginner
358: Notes:
359: The array weights is freed by PETSc so the user should not free the array. In C/C++
360: the array must be obtained with a call to PetscMalloc(), not malloc().
362: .keywords: Partitioning, destroy, context
364: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetVertexWeights()
365: @*/
366: int MatPartitioningSetPartitionWeights(MatPartitioning part,const PetscReal weights[])
367: {
373: if (part->part_weights){
374: PetscFree(part->part_weights);
375: }
376: part->part_weights = (PetscReal*)weights;
377: return(0);
378: }
382: /*@C
383: MatPartitioningCreate - Creates a partitioning context.
385: Collective on MPI_Comm
387: Input Parameter:
388: . comm - MPI communicator
390: Output Parameter:
391: . newp - location to put the context
393: Level: beginner
395: .keywords: Partitioning, create, context
397: .seealso: MatPartitioningSetType(), MatPartitioningApply(), MatPartitioningDestroy(),
398: MatPartitioningSetAdjacency()
400: @*/
401: int MatPartitioningCreate(MPI_Comm comm,MatPartitioning *newp)
402: {
403: MatPartitioning part;
404: int ierr;
407: *newp = 0;
409: PetscHeaderCreate(part,_p_MatPartitioning,struct _MatPartitioningOps,MAT_PARTITIONING_COOKIE,-1,"MatPartitioning",comm,MatPartitioningDestroy,
410: MatPartitioningView);
411: PetscLogObjectCreate(part);
412: part->type = -1;
413: part->vertex_weights = PETSC_NULL;
414: part->part_weights = PETSC_NULL;
415: MPI_Comm_size(comm,&part->n);
417: *newp = part;
418: return(0);
419: }
423: /*@C
424: MatPartitioningView - Prints the partitioning data structure.
426: Collective on MatPartitioning
428: Input Parameters:
429: . part - the partitioning context
430: . viewer - optional visualization context
432: Level: intermediate
434: Note:
435: The available visualization contexts include
436: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
437: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
438: output where only the first processor opens
439: the file. All other processors send their
440: data to the first processor to print.
442: The user can open alternative visualization contexts with
443: . PetscViewerASCIIOpen() - output to a specified file
445: .keywords: Partitioning, view
447: .seealso: PetscViewerASCIIOpen()
448: @*/
449: int MatPartitioningView(MatPartitioning part,PetscViewer viewer)
450: {
451: int ierr;
452: PetscTruth isascii;
453: MatPartitioningType name;
457: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(part->comm);
461: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
462: if (isascii) {
463: MatPartitioningGetType(part,&name);
464: PetscViewerASCIIPrintf(viewer,"MatPartitioning Object: %s\n",name);
465: if (part->vertex_weights) {
466: PetscViewerASCIIPrintf(viewer," Using vertex weights\n");
467: }
468: } else {
469: SETERRQ1(1,"Viewer type %s not supported for this MatParitioning",((PetscObject)viewer)->type_name);
470: }
472: if (part->ops->view) {
473: PetscViewerASCIIPushTab(viewer);
474: (*part->ops->view)(part,viewer);
475: PetscViewerASCIIPopTab(viewer);
476: }
478: return(0);
479: }
483: /*@C
484: MatPartitioningSetType - Sets the type of partitioner to use
486: Collective on MatPartitioning
488: Input Parameter:
489: . part - the partitioning context.
490: . type - a known method
492: Options Database Command:
493: $ -mat_partitioning_type <type>
494: $ Use -help for a list of available methods
495: $ (for instance, parmetis)
497: Level: intermediate
499: .keywords: partitioning, set, method, type
501: .seealso: MatPartitioningCreate(), MatPartitioningApply()
503: @*/
504: int MatPartitioningSetType(MatPartitioning part,const MatPartitioningType type)
505: {
506: int ierr,(*r)(MatPartitioning);
507: PetscTruth match;
513: PetscTypeCompare((PetscObject)part,type,&match);
514: if (match) return(0);
516: if (part->setupcalled) {
517: (*part->ops->destroy)(part);
518: part->data = 0;
519: part->setupcalled = 0;
520: }
522: /* Get the function pointers for the method requested */
523: if (!MatPartitioningRegisterAllCalled){ MatPartitioningRegisterAll(0);}
524: PetscFListFind(part->comm,MatPartitioningList,type,(void (**)(void)) &r);
526: if (!r) {SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Unknown partitioning type %s",type);}
528: part->ops->destroy = (int (*)(MatPartitioning)) 0;
529: part->ops->view = (int (*)(MatPartitioning,PetscViewer)) 0;
530: (*r)(part);
532: PetscStrfree(part->type_name);
533: PetscStrallocpy(type,&part->type_name);
534: return(0);
535: }
539: /*@
540: MatPartitioningSetFromOptions - Sets various partitioning options from the
541: options database.
543: Collective on MatPartitioning
545: Input Parameter:
546: . part - the partitioning context.
548: Options Database Command:
549: $ -mat_partitioning_type <type>
550: $ Use -help for a list of available methods
551: $ (for instance, parmetis)
553: Level: beginner
555: .keywords: partitioning, set, method, type
556: @*/
557: int MatPartitioningSetFromOptions(MatPartitioning part)
558: {
559: int ierr;
560: PetscTruth flag;
561: char type[256];
562: const char *def;
565: if (!MatPartitioningRegisterAllCalled){ MatPartitioningRegisterAll(0);}
566: PetscOptionsBegin(part->comm,part->prefix,"Partitioning options","MatOrderings");
567: if (!part->type_name) {
568: #if defined(PETSC_HAVE_PARMETIS)
569: def = MAT_PARTITIONING_PARMETIS;
570: #else
571: def = MAT_PARTITIONING_CURRENT;
572: #endif
573: } else {
574: def = part->type_name;
575: }
576: PetscOptionsList("-mat_partitioning_type","Type of partitioner","MatPartitioningSetType",MatPartitioningList,def,type,256,&flag);
577: if (flag) {
578: MatPartitioningSetType(part,type);
579: }
580: /*
581: Set the type if it was never set.
582: */
583: if (!part->type_name) {
584: MatPartitioningSetType(part,def);
585: }
587: if (part->ops->setfromoptions) {
588: (*part->ops->setfromoptions)(part);
589: }
590: PetscOptionsEnd();
591: return(0);
592: }