Actual source code: partition.c
1: #define PETSCMAT_DLL
3: #include private/matimpl.h
5: /* Logging support */
6: PetscCookie MAT_PARTITIONING_COOKIE;
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(((PetscObject)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(((PetscObject)part)->comm,&rank);
26: MatGetLocalSize(part->adj,&m,PETSC_NULL);
27: ISCreateStride(((PetscObject)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(((PetscObject)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(((PetscObject)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: PetscFList MatPartitioningList = 0;
97: PetscTruth MatPartitioningRegisterAllCalled = PETSC_FALSE;
102: PetscErrorCode MatPartitioningRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(MatPartitioning))
103: {
105: char fullname[PETSC_MAX_PATH_LEN];
108: PetscFListConcat(path,name,fullname);
109: PetscFListAdd(&MatPartitioningList,sname,fullname,(void (*)(void))function);
110: return(0);
111: }
115: /*@C
116: MatPartitioningRegisterDestroy - Frees the list of partitioning routines.
118: Not Collective
120: Level: developer
122: .keywords: matrix, register, destroy
124: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningRegisterAll()
125: @*/
126: PetscErrorCode MatPartitioningRegisterDestroy(void)
127: {
131: MatPartitioningRegisterAllCalled = PETSC_FALSE;
132: PetscFListDestroy(&MatPartitioningList);
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: PetscErrorCode MatPartitioningGetType(MatPartitioning partitioning,const MatPartitioningType *type)
157: {
161: *type = ((PetscObject)partitioning)->type_name;
162: return(0);
163: }
167: /*@C
168: MatPartitioningSetNParts - Set how many partitions need to be created;
169: by default this is one per processor. Certain partitioning schemes may
170: in fact only support that option.
172: Not collective
174: Input Parameter:
175: . partitioning - the partitioning context
176: . n - the number of partitions
178: Level: intermediate
180: Not Collective
182: .keywords: Partitioning, set
184: .seealso: MatPartitioningCreate(), MatPartitioningApply()
185: @*/
186: PetscErrorCode MatPartitioningSetNParts(MatPartitioning part,PetscInt n)
187: {
189: part->n = n;
190: return(0);
191: }
195: /*@
196: MatPartitioningApply - Gets a partitioning for a matrix.
198: Collective on Mat
200: Input Parameters:
201: . matp - the matrix partitioning object
203: Output Parameters:
204: . partitioning - the partitioning. For each local node this tells the processor
205: number that that node is assigned to.
207: Options Database Keys:
208: To specify the partitioning through the options database, use one of
209: the following
210: $ -mat_partitioning_type parmetis, -mat_partitioning current
211: To see the partitioning result
212: $ -mat_partitioning_view
214: Level: beginner
216: The user can define additional partitionings; see MatPartitioningRegisterDynamic().
218: .keywords: matrix, get, partitioning
220: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningCreate(),
221: MatPartitioningDestroy(), MatPartitioningSetAdjacency(), ISPartitioningToNumbering(),
222: ISPartitioningCount()
223: @*/
224: PetscErrorCode MatPartitioningApply(MatPartitioning matp,IS *partitioning)
225: {
227: PetscTruth flag = PETSC_FALSE;
232: if (!matp->adj->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
233: if (matp->adj->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
234: if (!matp->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set type with MatPartitioningSetFromOptions() or MatPartitioningSetType()");
235: PetscLogEventBegin(MAT_Partitioning,matp,0,0,0);
236: (*matp->ops->apply)(matp,partitioning);
237: PetscLogEventEnd(MAT_Partitioning,matp,0,0,0);
239: PetscOptionsGetTruth(PETSC_NULL,"-mat_partitioning_view",&flag,PETSC_NULL);
240: if (flag) {
241: PetscViewer viewer;
242: PetscViewerASCIIGetStdout(((PetscObject)matp)->comm,&viewer);
243: MatPartitioningView(matp,viewer);
244: ISView(*partitioning,viewer);
245: }
246: return(0);
247: }
248:
251: /*@
252: MatPartitioningSetAdjacency - Sets the adjacency graph (matrix) of the thing to be
253: partitioned.
255: Collective on MatPartitioning and Mat
257: Input Parameters:
258: + part - the partitioning context
259: - adj - the adjacency matrix
261: Level: beginner
263: .keywords: Partitioning, adjacency
265: .seealso: MatPartitioningCreate()
266: @*/
267: PetscErrorCode MatPartitioningSetAdjacency(MatPartitioning part,Mat adj)
268: {
272: part->adj = adj;
273: return(0);
274: }
278: /*@
279: MatPartitioningDestroy - Destroys the partitioning context.
281: Collective on Partitioning
283: Input Parameters:
284: . part - the partitioning context
286: Level: beginner
288: .keywords: Partitioning, destroy, context
290: .seealso: MatPartitioningCreate()
291: @*/
292: PetscErrorCode MatPartitioningDestroy(MatPartitioning part)
293: {
298: if (--((PetscObject)part)->refct > 0) return(0);
300: if (part->ops->destroy) {
301: (*part->ops->destroy)(part);
302: }
303: PetscFree(part->vertex_weights);
304: PetscFree(part->part_weights);
305: PetscHeaderDestroy(part);
306: return(0);
307: }
311: /*@C
312: MatPartitioningSetVertexWeights - Sets the weights for vertices for a partitioning.
314: Collective on Partitioning
316: Input Parameters:
317: + part - the partitioning context
318: - weights - the weights
320: Level: beginner
322: Notes:
323: The array weights is freed by PETSc so the user should not free the array. In C/C++
324: the array must be obtained with a call to PetscMalloc(), not malloc().
326: .keywords: Partitioning, destroy, context
328: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetPartitionWeights()
329: @*/
330: PetscErrorCode MatPartitioningSetVertexWeights(MatPartitioning part,const PetscInt weights[])
331: {
337: PetscFree(part->vertex_weights);
338: part->vertex_weights = (PetscInt*)weights;
339: return(0);
340: }
344: /*@C
345: MatPartitioningSetPartitionWeights - Sets the weights for each partition.
347: Collective on Partitioning
349: Input Parameters:
350: + part - the partitioning context
351: - weights - the weights
353: Level: beginner
355: Notes:
356: The array weights is freed by PETSc so the user should not free the array. In C/C++
357: the array must be obtained with a call to PetscMalloc(), not malloc().
359: .keywords: Partitioning, destroy, context
361: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetVertexWeights()
362: @*/
363: PetscErrorCode MatPartitioningSetPartitionWeights(MatPartitioning part,const PetscReal weights[])
364: {
370: PetscFree(part->part_weights);
371: part->part_weights = (PetscReal*)weights;
372: return(0);
373: }
377: /*@
378: MatPartitioningCreate - Creates a partitioning context.
380: Collective on MPI_Comm
382: Input Parameter:
383: . comm - MPI communicator
385: Output Parameter:
386: . newp - location to put the context
388: Level: beginner
390: .keywords: Partitioning, create, context
392: .seealso: MatPartitioningSetType(), MatPartitioningApply(), MatPartitioningDestroy(),
393: MatPartitioningSetAdjacency()
395: @*/
396: PetscErrorCode MatPartitioningCreate(MPI_Comm comm,MatPartitioning *newp)
397: {
398: MatPartitioning part;
399: PetscErrorCode ierr;
400: PetscMPIInt size;
403: *newp = 0;
405: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
406: MatInitializePackage(PETSC_NULL);
407: #endif
408: PetscHeaderCreate(part,_p_MatPartitioning,struct _MatPartitioningOps,MAT_PARTITIONING_COOKIE,-1,"MatPartitioning",comm,MatPartitioningDestroy,
409: MatPartitioningView);
410: part->vertex_weights = PETSC_NULL;
411: part->part_weights = PETSC_NULL;
412: MPI_Comm_size(comm,&size);
413: part->n = (PetscInt)size;
415: *newp = part;
416: return(0);
417: }
421: /*@C
422: MatPartitioningView - Prints the partitioning data structure.
424: Collective on MatPartitioning
426: Input Parameters:
427: . part - the partitioning context
428: . viewer - optional visualization context
430: Level: intermediate
432: Note:
433: The available visualization contexts include
434: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
435: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
436: output where only the first processor opens
437: the file. All other processors send their
438: data to the first processor to print.
440: The user can open alternative visualization contexts with
441: . PetscViewerASCIIOpen() - output to a specified file
443: .keywords: Partitioning, view
445: .seealso: PetscViewerASCIIOpen()
446: @*/
447: PetscErrorCode MatPartitioningView(MatPartitioning part,PetscViewer viewer)
448: {
449: PetscErrorCode ierr;
450: PetscTruth iascii;
451: const MatPartitioningType name;
455: if (!viewer) {
456: PetscViewerASCIIGetStdout(((PetscObject)part)->comm,&viewer);
457: }
461: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
462: if (iascii) {
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(PETSC_ERR_SUP,"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(), MatPartitioningType
503: @*/
504: PetscErrorCode MatPartitioningSetType(MatPartitioning part,const MatPartitioningType type)
505: {
506: PetscErrorCode 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: PetscFListFind(MatPartitioningList,((PetscObject)part)->comm,type,(void (**)(void)) &r);
524: if (!r) {SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown partitioning type %s",type);}
526: part->ops->destroy = (PetscErrorCode (*)(MatPartitioning)) 0;
527: part->ops->view = (PetscErrorCode (*)(MatPartitioning,PetscViewer)) 0;
528: (*r)(part);
530: PetscStrfree(((PetscObject)part)->type_name);
531: PetscStrallocpy(type,&((PetscObject)part)->type_name);
532: return(0);
533: }
537: /*@
538: MatPartitioningSetFromOptions - Sets various partitioning options from the
539: options database.
541: Collective on MatPartitioning
543: Input Parameter:
544: . part - the partitioning context.
546: Options Database Command:
547: $ -mat_partitioning_type <type>
548: $ Use -help for a list of available methods
549: $ (for instance, parmetis)
551: Level: beginner
553: .keywords: partitioning, set, method, type
554: @*/
555: PetscErrorCode MatPartitioningSetFromOptions(MatPartitioning part)
556: {
558: PetscTruth flag;
559: char type[256];
560: const char *def;
563: PetscOptionsBegin(((PetscObject)part)->comm,((PetscObject)part)->prefix,"Partitioning options","MatOrderings");
564: if (!((PetscObject)part)->type_name) {
565: #if defined(PETSC_HAVE_PARMETIS)
566: def = MAT_PARTITIONING_PARMETIS;
567: #else
568: def = MAT_PARTITIONING_CURRENT;
569: #endif
570: } else {
571: def = ((PetscObject)part)->type_name;
572: }
573: PetscOptionsList("-mat_partitioning_type","Type of partitioner","MatPartitioningSetType",MatPartitioningList,def,type,256,&flag);
574: if (flag) {
575: MatPartitioningSetType(part,type);
576: }
577: /*
578: Set the type if it was never set.
579: */
580: if (!((PetscObject)part)->type_name) {
581: MatPartitioningSetType(part,def);
582: }
584: if (part->ops->setfromoptions) {
585: (*part->ops->setfromoptions)(part);
586: }
587: PetscOptionsEnd();
588: return(0);
589: }