Actual source code: partition.c
1: #define PETSCMAT_DLL
3: #include include/private/matimpl.h
5: /* Logging support */
6: PetscCookie MAT_PARTITIONING_COOKIE = 0;
8: /*
9: Simplest partitioning, keeps the current partitioning.
10: */
13: static PetscErrorCode MatPartitioningApply_Current(MatPartitioning part,IS *partitioning)
14: {
16: PetscInt m;
17: PetscMPIInt rank,size;
20: MPI_Comm_size(part->comm,&size);
21: if (part->n != size) {
22: SETERRQ(PETSC_ERR_SUP,"This is the DEFAULT NO-OP partitioner, it currently only supports one domain per processor\nuse -matpartitioning_type parmetis or chaco or scotch for more than one subdomain per processor");
23: }
24: MPI_Comm_rank(part->comm,&rank);
26: MatGetLocalSize(part->adj,&m,PETSC_NULL);
27: ISCreateStride(part->comm,m,rank,0,partitioning);
28: return(0);
29: }
33: static PetscErrorCode MatPartitioningApply_Square(MatPartitioning part,IS *partitioning)
34: {
36: PetscInt cell,n,N,p,rstart,rend,*color;
37: PetscMPIInt size;
40: MPI_Comm_size(part->comm,&size);
41: if (part->n != size) {
42: SETERRQ(PETSC_ERR_SUP,"Currently only supports one domain per processor");
43: }
44: p = (PetscInt)sqrt((double)part->n);
45: if (p*p != part->n) {
46: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires \"perfect square\" number of domains");
47: }
48: MatGetSize(part->adj,&N,PETSC_NULL);
49: n = (PetscInt)sqrt((double)N);
50: if (n*n != N) { /* This condition is NECESSARY, but NOT SUFFICIENT in order to the domain be square */
51: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires square domain");
52: }
53: if (n%p != 0) {
54: SETERRQ(PETSC_ERR_SUP,"Square partitioning requires p to divide n");
55: }
56: MatGetOwnershipRange(part->adj,&rstart,&rend);
57: PetscMalloc((rend-rstart)*sizeof(PetscInt),&color);
58: /* for (int cell=rstart; cell<rend; cell++) { color[cell-rstart] = ((cell%n) < (n/2)) + 2 * ((cell/n) < (n/2)); } */
59: for (cell=rstart; cell<rend; cell++) {
60: color[cell-rstart] = ((cell%n) / (n/p)) + p * ((cell/n) / (n/p));
61: }
62: ISCreateGeneral(part->comm,rend-rstart,color,partitioning);
63: PetscFree(color);
65: return(0);
66: }
71: PetscErrorCode MatPartitioningCreate_Current(MatPartitioning part)
72: {
74: part->ops->apply = MatPartitioningApply_Current;
75: part->ops->view = 0;
76: part->ops->destroy = 0;
77: return(0);
78: }
84: PetscErrorCode MatPartitioningCreate_Square(MatPartitioning part)
85: {
87: part->ops->apply = MatPartitioningApply_Square;
88: part->ops->view = 0;
89: part->ops->destroy = 0;
90: return(0);
91: }
94: /* ===========================================================================================*/
96: #include petscsys.h
98: PetscFList MatPartitioningList = 0;
99: PetscTruth MatPartitioningRegisterAllCalled = PETSC_FALSE;
104: PetscErrorCode MatPartitioningRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(MatPartitioning))
105: {
107: char fullname[PETSC_MAX_PATH_LEN];
110: PetscFListConcat(path,name,fullname);
111: PetscFListAdd(&MatPartitioningList,sname,fullname,(void (*)(void))function);
112: return(0);
113: }
117: /*@C
118: MatPartitioningRegisterDestroy - Frees the list of partitioning routines.
120: Not Collective
122: Level: developer
124: .keywords: matrix, register, destroy
126: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningRegisterAll()
127: @*/
128: PetscErrorCode MatPartitioningRegisterDestroy(void)
129: {
133: PetscFListDestroy(&MatPartitioningList);
134: return(0);
135: }
139: /*@C
140: MatPartitioningGetType - Gets the Partitioning method type and name (as a string)
141: from the partitioning context.
143: Not collective
145: Input Parameter:
146: . partitioning - the partitioning context
148: Output Parameter:
149: . type - partitioner type
151: Level: intermediate
153: Not Collective
155: .keywords: Partitioning, get, method, name, type
156: @*/
157: PetscErrorCode MatPartitioningGetType(MatPartitioning partitioning,MatPartitioningType *type)
158: {
160: *type = partitioning->type_name;
161: return(0);
162: }
166: /*@C
167: MatPartitioningSetNParts - Set how many partitions need to be created;
168: by default this is one per processor. Certain partitioning schemes may
169: in fact only support that option.
171: Not collective
173: Input Parameter:
174: . partitioning - the partitioning context
175: . n - the number of partitions
177: Level: intermediate
179: Not Collective
181: .keywords: Partitioning, set
183: .seealso: MatPartitioningCreate(), MatPartitioningApply()
184: @*/
185: PetscErrorCode MatPartitioningSetNParts(MatPartitioning part,PetscInt n)
186: {
188: part->n = n;
189: return(0);
190: }
194: /*@
195: MatPartitioningApply - Gets a partitioning for a matrix.
197: Collective on Mat
199: Input Parameters:
200: . matp - the matrix partitioning object
202: Output Parameters:
203: . partitioning - the partitioning. For each local node this tells the processor
204: number that that node is assigned to.
206: Options Database Keys:
207: To specify the partitioning through the options database, use one of
208: the following
209: $ -mat_partitioning_type parmetis, -mat_partitioning current
210: To see the partitioning result
211: $ -mat_partitioning_view
213: Level: beginner
215: The user can define additional partitionings; see MatPartitioningRegisterDynamic().
217: .keywords: matrix, get, partitioning
219: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningCreate(),
220: MatPartitioningDestroy(), MatPartitioningSetAdjacency(), ISPartitioningToNumbering(),
221: ISPartitioningCount()
222: @*/
223: PetscErrorCode MatPartitioningApply(MatPartitioning matp,IS *partitioning)
224: {
226: PetscTruth flag;
231: if (!matp->adj->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
232: if (matp->adj->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
233: if (!matp->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set type with MatPartitioningSetFromOptions() or MatPartitioningSetType()");
235: (*matp->ops->apply)(matp,partitioning);
238: PetscOptionsHasName(PETSC_NULL,"-mat_partitioning_view",&flag);
239: if (flag) {
240: PetscViewer viewer;
241: PetscViewerASCIIGetStdout(matp->comm,&viewer);
242: MatPartitioningView(matp,viewer);
243: ISView(*partitioning,viewer);
244: }
245: return(0);
246: }
247:
250: /*@
251: MatPartitioningSetAdjacency - Sets the adjacency graph (matrix) of the thing to be
252: partitioned.
254: Collective on MatPartitioning and Mat
256: Input Parameters:
257: + part - the partitioning context
258: - adj - the adjacency matrix
260: Level: beginner
262: .keywords: Partitioning, adjacency
264: .seealso: MatPartitioningCreate()
265: @*/
266: PetscErrorCode MatPartitioningSetAdjacency(MatPartitioning part,Mat adj)
267: {
271: part->adj = adj;
272: return(0);
273: }
277: /*@
278: MatPartitioningDestroy - Destroys the partitioning context.
280: Collective on Partitioning
282: Input Parameters:
283: . part - the partitioning context
285: Level: beginner
287: .keywords: Partitioning, destroy, context
289: .seealso: MatPartitioningCreate()
290: @*/
291: PetscErrorCode MatPartitioningDestroy(MatPartitioning part)
292: {
297: if (--part->refct > 0) return(0);
299: if (part->ops->destroy) {
300: (*part->ops->destroy)(part);
301: }
302: PetscFree(part->vertex_weights);
303: PetscFree(part->part_weights);
304: PetscHeaderDestroy(part);
305: return(0);
306: }
310: /*@C
311: MatPartitioningSetVertexWeights - Sets the weights for vertices for a partitioning.
313: Collective on Partitioning
315: Input Parameters:
316: + part - the partitioning context
317: - weights - the weights
319: Level: beginner
321: Notes:
322: The array weights is freed by PETSc so the user should not free the array. In C/C++
323: the array must be obtained with a call to PetscMalloc(), not malloc().
325: .keywords: Partitioning, destroy, context
327: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetPartitionWeights()
328: @*/
329: PetscErrorCode MatPartitioningSetVertexWeights(MatPartitioning part,const PetscInt weights[])
330: {
336: PetscFree(part->vertex_weights);
337: part->vertex_weights = (PetscInt*)weights;
338: return(0);
339: }
343: /*@C
344: MatPartitioningSetPartitionWeights - Sets the weights for each partition.
346: Collective on Partitioning
348: Input Parameters:
349: + part - the partitioning context
350: - weights - the weights
352: Level: beginner
354: Notes:
355: The array weights is freed by PETSc so the user should not free the array. In C/C++
356: the array must be obtained with a call to PetscMalloc(), not malloc().
358: .keywords: Partitioning, destroy, context
360: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetVertexWeights()
361: @*/
362: PetscErrorCode MatPartitioningSetPartitionWeights(MatPartitioning part,const PetscReal weights[])
363: {
369: PetscFree(part->part_weights);
370: part->part_weights = (PetscReal*)weights;
371: return(0);
372: }
376: /*@
377: MatPartitioningCreate - Creates a partitioning context.
379: Collective on MPI_Comm
381: Input Parameter:
382: . comm - MPI communicator
384: Output Parameter:
385: . newp - location to put the context
387: Level: beginner
389: .keywords: Partitioning, create, context
391: .seealso: MatPartitioningSetType(), MatPartitioningApply(), MatPartitioningDestroy(),
392: MatPartitioningSetAdjacency()
394: @*/
395: PetscErrorCode MatPartitioningCreate(MPI_Comm comm,MatPartitioning *newp)
396: {
397: MatPartitioning part;
398: PetscErrorCode ierr;
399: PetscMPIInt size;
402: *newp = 0;
404: PetscHeaderCreate(part,_p_MatPartitioning,struct _MatPartitioningOps,MAT_PARTITIONING_COOKIE,-1,"MatPartitioning",comm,MatPartitioningDestroy,
405: MatPartitioningView);
406: part->type = -1;
407: part->vertex_weights = PETSC_NULL;
408: part->part_weights = PETSC_NULL;
409: MPI_Comm_size(comm,&size);
410: part->n = (PetscInt)size;
412: *newp = part;
413: return(0);
414: }
418: /*@C
419: MatPartitioningView - Prints the partitioning data structure.
421: Collective on MatPartitioning
423: Input Parameters:
424: . part - the partitioning context
425: . viewer - optional visualization context
427: Level: intermediate
429: Note:
430: The available visualization contexts include
431: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
432: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
433: output where only the first processor opens
434: the file. All other processors send their
435: data to the first processor to print.
437: The user can open alternative visualization contexts with
438: . PetscViewerASCIIOpen() - output to a specified file
440: .keywords: Partitioning, view
442: .seealso: PetscViewerASCIIOpen()
443: @*/
444: PetscErrorCode MatPartitioningView(MatPartitioning part,PetscViewer viewer)
445: {
446: PetscErrorCode ierr;
447: PetscTruth iascii;
448: MatPartitioningType name;
452: if (!viewer) {
453: PetscViewerASCIIGetStdout(part->comm,&viewer);
454: }
458: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
459: if (iascii) {
460: MatPartitioningGetType(part,&name);
461: PetscViewerASCIIPrintf(viewer,"MatPartitioning Object: %s\n",name);
462: if (part->vertex_weights) {
463: PetscViewerASCIIPrintf(viewer," Using vertex weights\n");
464: }
465: } else {
466: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this MatParitioning",((PetscObject)viewer)->type_name);
467: }
469: if (part->ops->view) {
470: PetscViewerASCIIPushTab(viewer);
471: (*part->ops->view)(part,viewer);
472: PetscViewerASCIIPopTab(viewer);
473: }
475: return(0);
476: }
480: /*@C
481: MatPartitioningSetType - Sets the type of partitioner to use
483: Collective on MatPartitioning
485: Input Parameter:
486: . part - the partitioning context.
487: . type - a known method
489: Options Database Command:
490: $ -mat_partitioning_type <type>
491: $ Use -help for a list of available methods
492: $ (for instance, parmetis)
494: Level: intermediate
496: .keywords: partitioning, set, method, type
498: .seealso: MatPartitioningCreate(), MatPartitioningApply(), MatPartitioningType
500: @*/
501: PetscErrorCode MatPartitioningSetType(MatPartitioning part,MatPartitioningType type)
502: {
503: PetscErrorCode ierr,(*r)(MatPartitioning);
504: PetscTruth match;
510: PetscTypeCompare((PetscObject)part,type,&match);
511: if (match) return(0);
513: if (part->setupcalled) {
514: (*part->ops->destroy)(part);
515: part->data = 0;
516: part->setupcalled = 0;
517: }
519: PetscFListFind(MatPartitioningList,part->comm,type,(void (**)(void)) &r);
521: if (!r) {SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown partitioning type %s",type);}
523: part->ops->destroy = (PetscErrorCode (*)(MatPartitioning)) 0;
524: part->ops->view = (PetscErrorCode (*)(MatPartitioning,PetscViewer)) 0;
525: (*r)(part);
527: PetscStrfree(part->type_name);
528: PetscStrallocpy(type,&part->type_name);
529: return(0);
530: }
534: /*@
535: MatPartitioningSetFromOptions - Sets various partitioning options from the
536: options database.
538: Collective on MatPartitioning
540: Input Parameter:
541: . part - the partitioning context.
543: Options Database Command:
544: $ -mat_partitioning_type <type>
545: $ Use -help for a list of available methods
546: $ (for instance, parmetis)
548: Level: beginner
550: .keywords: partitioning, set, method, type
551: @*/
552: PetscErrorCode MatPartitioningSetFromOptions(MatPartitioning part)
553: {
555: PetscTruth flag;
556: char type[256];
557: const char *def;
560: if (!MatPartitioningRegisterAllCalled){ MatPartitioningRegisterAll(0);}
561: PetscOptionsBegin(part->comm,part->prefix,"Partitioning options","MatOrderings");
562: if (!part->type_name) {
563: #if defined(PETSC_HAVE_PARMETIS)
564: def = MAT_PARTITIONING_PARMETIS;
565: #else
566: def = MAT_PARTITIONING_CURRENT;
567: #endif
568: } else {
569: def = part->type_name;
570: }
571: PetscOptionsList("-mat_partitioning_type","Type of partitioner","MatPartitioningSetType",MatPartitioningList,def,type,256,&flag);
572: if (flag) {
573: MatPartitioningSetType(part,type);
574: }
575: /*
576: Set the type if it was never set.
577: */
578: if (!part->type_name) {
579: MatPartitioningSetType(part,def);
580: }
582: if (part->ops->setfromoptions) {
583: (*part->ops->setfromoptions)(part);
584: }
585: PetscOptionsEnd();
586: return(0);
587: }