Actual source code: partition.c
2: #include <private/matimpl.h> /*I "petscmat.h" I*/
4: /* Logging support */
5: PetscClassId MAT_PARTITIONING_CLASSID;
7: /*
8: Simplest partitioning, keeps the current partitioning.
9: */
12: static PetscErrorCode MatPartitioningApply_Current(MatPartitioning part,IS *partitioning)
13: {
15: PetscInt m;
16: PetscMPIInt rank,size;
19: MPI_Comm_size(((PetscObject)part)->comm,&size);
20: if (part->n != size) {
21: SETERRQ(((PetscObject)part)->comm,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");
22: }
23: MPI_Comm_rank(((PetscObject)part)->comm,&rank);
25: MatGetLocalSize(part->adj,&m,PETSC_NULL);
26: ISCreateStride(((PetscObject)part)->comm,m,rank,0,partitioning);
27: return(0);
28: }
32: static PetscErrorCode MatPartitioningApply_Square(MatPartitioning part,IS *partitioning)
33: {
35: PetscInt cell,n,N,p,rstart,rend,*color;
36: PetscMPIInt size;
39: MPI_Comm_size(((PetscObject)part)->comm,&size);
40: if (part->n != size) SETERRQ(((PetscObject)part)->comm,PETSC_ERR_SUP,"Currently only supports one domain per processor");
41: p = (PetscInt)sqrt((double)part->n);
42: if (p*p != part->n) SETERRQ(((PetscObject)part)->comm,PETSC_ERR_SUP,"Square partitioning requires \"perfect square\" number of domains");
44: MatGetSize(part->adj,&N,PETSC_NULL);
45: n = (PetscInt)sqrt((double)N);
46: if (n*n != N) SETERRQ(((PetscObject)part)->comm,PETSC_ERR_SUP,"Square partitioning requires square domain");
47: if (n%p != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Square partitioning requires p to divide n");
48: MatGetOwnershipRange(part->adj,&rstart,&rend);
49: PetscMalloc((rend-rstart)*sizeof(PetscInt),&color);
50: /* for (int cell=rstart; cell<rend; cell++) { color[cell-rstart] = ((cell%n) < (n/2)) + 2 * ((cell/n) < (n/2)); } */
51: for (cell=rstart; cell<rend; cell++) {
52: color[cell-rstart] = ((cell%n) / (n/p)) + p * ((cell/n) / (n/p));
53: }
54: ISCreateGeneral(((PetscObject)part)->comm,rend-rstart,color,PETSC_OWN_POINTER,partitioning);
55: return(0);
56: }
61: PetscErrorCode MatPartitioningCreate_Current(MatPartitioning part)
62: {
64: part->ops->apply = MatPartitioningApply_Current;
65: part->ops->view = 0;
66: part->ops->destroy = 0;
67: return(0);
68: }
74: PetscErrorCode MatPartitioningCreate_Square(MatPartitioning part)
75: {
77: part->ops->apply = MatPartitioningApply_Square;
78: part->ops->view = 0;
79: part->ops->destroy = 0;
80: return(0);
81: }
84: /* ===========================================================================================*/
86: PetscFList MatPartitioningList = 0;
87: PetscBool MatPartitioningRegisterAllCalled = PETSC_FALSE;
92: PetscErrorCode MatPartitioningRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(MatPartitioning))
93: {
95: char fullname[PETSC_MAX_PATH_LEN];
98: PetscFListConcat(path,name,fullname);
99: PetscFListAdd(&MatPartitioningList,sname,fullname,(void (*)(void))function);
100: return(0);
101: }
105: /*@C
106: MatPartitioningRegisterDestroy - Frees the list of partitioning routines.
108: Not Collective
110: Level: developer
112: .keywords: matrix, register, destroy
114: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningRegisterAll()
115: @*/
116: PetscErrorCode MatPartitioningRegisterDestroy(void)
117: {
121: MatPartitioningRegisterAllCalled = PETSC_FALSE;
122: PetscFListDestroy(&MatPartitioningList);
123: return(0);
124: }
128: /*@C
129: MatPartitioningGetType - Gets the Partitioning method type and name (as a string)
130: from the partitioning context.
132: Not collective
134: Input Parameter:
135: . partitioning - the partitioning context
137: Output Parameter:
138: . type - partitioner type
140: Level: intermediate
142: Not Collective
144: .keywords: Partitioning, get, method, name, type
145: @*/
146: PetscErrorCode MatPartitioningGetType(MatPartitioning partitioning,const MatPartitioningType *type)
147: {
151: *type = ((PetscObject)partitioning)->type_name;
152: return(0);
153: }
157: /*@C
158: MatPartitioningSetNParts - Set how many partitions need to be created;
159: by default this is one per processor. Certain partitioning schemes may
160: in fact only support that option.
162: Not collective
164: Input Parameter:
165: . partitioning - the partitioning context
166: . n - the number of partitions
168: Level: intermediate
170: Not Collective
172: .keywords: Partitioning, set
174: .seealso: MatPartitioningCreate(), MatPartitioningApply()
175: @*/
176: PetscErrorCode MatPartitioningSetNParts(MatPartitioning part,PetscInt n)
177: {
179: part->n = n;
180: return(0);
181: }
185: /*@
186: MatPartitioningApply - Gets a partitioning for a matrix.
188: Collective on Mat
190: Input Parameters:
191: . matp - the matrix partitioning object
193: Output Parameters:
194: . partitioning - the partitioning. For each local node this tells the processor
195: number that that node is assigned to.
197: Options Database Keys:
198: To specify the partitioning through the options database, use one of
199: the following
200: $ -mat_partitioning_type parmetis, -mat_partitioning current
201: To see the partitioning result
202: $ -mat_partitioning_view
204: Level: beginner
206: The user can define additional partitionings; see MatPartitioningRegisterDynamic().
208: .keywords: matrix, get, partitioning
210: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningCreate(),
211: MatPartitioningDestroy(), MatPartitioningSetAdjacency(), ISPartitioningToNumbering(),
212: ISPartitioningCount()
213: @*/
214: PetscErrorCode MatPartitioningApply(MatPartitioning matp,IS *partitioning)
215: {
217: PetscBool flag = PETSC_FALSE;
222: if (!matp->adj->assembled) SETERRQ(((PetscObject)matp)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
223: if (matp->adj->factortype) SETERRQ(((PetscObject)matp)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
224: if (!matp->ops->apply) SETERRQ(((PetscObject)matp)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must set type with MatPartitioningSetFromOptions() or MatPartitioningSetType()");
225: PetscLogEventBegin(MAT_Partitioning,matp,0,0,0);
226: (*matp->ops->apply)(matp,partitioning);
227: PetscLogEventEnd(MAT_Partitioning,matp,0,0,0);
229: PetscOptionsGetBool(PETSC_NULL,"-mat_partitioning_view",&flag,PETSC_NULL);
230: if (flag) {
231: PetscViewer viewer;
232: PetscViewerASCIIGetStdout(((PetscObject)matp)->comm,&viewer);
233: MatPartitioningView(matp,viewer);
234: ISView(*partitioning,viewer);
235: }
236: return(0);
237: }
238:
241: /*@
242: MatPartitioningSetAdjacency - Sets the adjacency graph (matrix) of the thing to be
243: partitioned.
245: Collective on MatPartitioning and Mat
247: Input Parameters:
248: + part - the partitioning context
249: - adj - the adjacency matrix
251: Level: beginner
253: .keywords: Partitioning, adjacency
255: .seealso: MatPartitioningCreate()
256: @*/
257: PetscErrorCode MatPartitioningSetAdjacency(MatPartitioning part,Mat adj)
258: {
262: part->adj = adj;
263: return(0);
264: }
268: /*@
269: MatPartitioningDestroy - Destroys the partitioning context.
271: Collective on Partitioning
273: Input Parameters:
274: . part - the partitioning context
276: Level: beginner
278: .keywords: Partitioning, destroy, context
280: .seealso: MatPartitioningCreate()
281: @*/
282: PetscErrorCode MatPartitioningDestroy(MatPartitioning *part)
283: {
287: if (!*part) return(0);
289: if (--((PetscObject)(*part))->refct > 0) {*part = 0; return(0);}
291: if ((*part)->ops->destroy) {
292: (*(*part)->ops->destroy)((*part));
293: }
294: PetscFree((*part)->vertex_weights);
295: PetscFree((*part)->part_weights);
296: PetscHeaderDestroy(part);
297: return(0);
298: }
302: /*@C
303: MatPartitioningSetVertexWeights - Sets the weights for vertices for a partitioning.
305: Logically Collective on Partitioning
307: Input Parameters:
308: + part - the partitioning context
309: - weights - the weights, on each process this array must have the same size as the number of local rows
311: Level: beginner
313: Notes:
314: The array weights is freed by PETSc so the user should not free the array. In C/C++
315: the array must be obtained with a call to PetscMalloc(), not malloc().
317: .keywords: Partitioning, destroy, context
319: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetPartitionWeights()
320: @*/
321: PetscErrorCode MatPartitioningSetVertexWeights(MatPartitioning part,const PetscInt weights[])
322: {
328: PetscFree(part->vertex_weights);
329: part->vertex_weights = (PetscInt*)weights;
330: return(0);
331: }
335: /*@C
336: MatPartitioningSetPartitionWeights - Sets the weights for each partition.
338: Logically Collective on Partitioning
340: Input Parameters:
341: + part - the partitioning context
342: - weights - An array of size nparts that is used to specify the fraction of
343: vertex weight that should be distributed to each sub-domain for
344: the balance constraint. If all of the sub-domains are to be of
345: the same size, then each of the nparts elements should be set
346: to a value of 1/nparts. Note that the sum of all of the weights
347: should be one.
349: Level: beginner
351: Notes:
352: The array weights is freed by PETSc so the user should not free the array. In C/C++
353: the array must be obtained with a call to PetscMalloc(), not malloc().
355: .keywords: Partitioning, destroy, context
357: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetVertexWeights()
358: @*/
359: PetscErrorCode MatPartitioningSetPartitionWeights(MatPartitioning part,const PetscReal weights[])
360: {
366: PetscFree(part->part_weights);
367: part->part_weights = (PetscReal*)weights;
368: return(0);
369: }
373: /*@
374: MatPartitioningCreate - Creates a partitioning context.
376: Collective on MPI_Comm
378: Input Parameter:
379: . comm - MPI communicator
381: Output Parameter:
382: . newp - location to put the context
384: Level: beginner
386: .keywords: Partitioning, create, context
388: .seealso: MatPartitioningSetType(), MatPartitioningApply(), MatPartitioningDestroy(),
389: MatPartitioningSetAdjacency()
391: @*/
392: PetscErrorCode MatPartitioningCreate(MPI_Comm comm,MatPartitioning *newp)
393: {
394: MatPartitioning part;
395: PetscErrorCode ierr;
396: PetscMPIInt size;
399: *newp = 0;
401: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
402: MatInitializePackage(PETSC_NULL);
403: #endif
404: PetscHeaderCreate(part,_p_MatPartitioning,struct _MatPartitioningOps,MAT_PARTITIONING_CLASSID,-1,"MatPartitioning","Matrix/graph partitioning","MatOrderings",comm,MatPartitioningDestroy,
405: MatPartitioningView);
406: part->vertex_weights = PETSC_NULL;
407: part->part_weights = PETSC_NULL;
408: MPI_Comm_size(comm,&size);
409: part->n = (PetscInt)size;
411: *newp = part;
412: return(0);
413: }
417: /*@C
418: MatPartitioningView - Prints the partitioning data structure.
420: Collective on MatPartitioning
422: Input Parameters:
423: . part - the partitioning context
424: . viewer - optional visualization context
426: Level: intermediate
428: Note:
429: The available visualization contexts include
430: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
431: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
432: output where only the first processor opens
433: the file. All other processors send their
434: data to the first processor to print.
436: The user can open alternative visualization contexts with
437: . PetscViewerASCIIOpen() - output to a specified file
439: .keywords: Partitioning, view
441: .seealso: PetscViewerASCIIOpen()
442: @*/
443: PetscErrorCode MatPartitioningView(MatPartitioning part,PetscViewer viewer)
444: {
445: PetscErrorCode ierr;
446: PetscBool iascii;
450: if (!viewer) {
451: PetscViewerASCIIGetStdout(((PetscObject)part)->comm,&viewer);
452: }
456: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
457: if (iascii) {
458: PetscObjectPrintClassNamePrefixType((PetscObject)part,viewer,"MatPartitioning Object");
459: if (part->vertex_weights) {
460: PetscViewerASCIIPrintf(viewer," Using vertex weights\n");
461: }
462: } else {
463: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for this MatParitioning",((PetscObject)viewer)->type_name);
464: }
466: if (part->ops->view) {
467: PetscViewerASCIIPushTab(viewer);
468: (*part->ops->view)(part,viewer);
469: PetscViewerASCIIPopTab(viewer);
470: }
472: return(0);
473: }
477: /*@C
478: MatPartitioningSetType - Sets the type of partitioner to use
480: Collective on MatPartitioning
482: Input Parameter:
483: . part - the partitioning context.
484: . type - a known method
486: Options Database Command:
487: $ -mat_partitioning_type <type>
488: $ Use -help for a list of available methods
489: $ (for instance, parmetis)
491: Level: intermediate
493: .keywords: partitioning, set, method, type
495: .seealso: MatPartitioningCreate(), MatPartitioningApply(), MatPartitioningType
497: @*/
498: PetscErrorCode MatPartitioningSetType(MatPartitioning part,const MatPartitioningType type)
499: {
500: PetscErrorCode ierr,(*r)(MatPartitioning);
501: PetscBool match;
507: PetscTypeCompare((PetscObject)part,type,&match);
508: if (match) return(0);
510: if (part->setupcalled) {
511: (*part->ops->destroy)(part);
512: part->data = 0;
513: part->setupcalled = 0;
514: }
516: PetscFListFind(MatPartitioningList,((PetscObject)part)->comm,type,PETSC_TRUE,(void (**)(void)) &r);
518: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown partitioning type %s",type);
520: part->ops->destroy = (PetscErrorCode (*)(MatPartitioning)) 0;
521: part->ops->view = (PetscErrorCode (*)(MatPartitioning,PetscViewer)) 0;
522: (*r)(part);
524: PetscFree(((PetscObject)part)->type_name);
525: PetscStrallocpy(type,&((PetscObject)part)->type_name);
526: return(0);
527: }
531: /*@
532: MatPartitioningSetFromOptions - Sets various partitioning options from the
533: options database.
535: Collective on MatPartitioning
537: Input Parameter:
538: . part - the partitioning context.
540: Options Database Command:
541: $ -mat_partitioning_type <type>
542: $ Use -help for a list of available methods
543: $ (for instance, parmetis)
545: Level: beginner
547: .keywords: partitioning, set, method, type
548: @*/
549: PetscErrorCode MatPartitioningSetFromOptions(MatPartitioning part)
550: {
552: PetscBool flag;
553: char type[256];
554: const char *def;
557: PetscObjectOptionsBegin((PetscObject)part);
558: if (!((PetscObject)part)->type_name) {
559: #if defined(PETSC_HAVE_PARMETIS)
560: def = MATPARTITIONINGPARMETIS;
561: #else
562: def = MATPARTITIONINGCURRENT;
563: #endif
564: } else {
565: def = ((PetscObject)part)->type_name;
566: }
567: PetscOptionsList("-mat_partitioning_type","Type of partitioner","MatPartitioningSetType",MatPartitioningList,def,type,256,&flag);
568: if (flag) {
569: MatPartitioningSetType(part,type);
570: }
571: /*
572: Set the type if it was never set.
573: */
574: if (!((PetscObject)part)->type_name) {
575: MatPartitioningSetType(part,def);
576: }
578: if (part->ops->setfromoptions) {
579: (*part->ops->setfromoptions)(part);
580: }
581: PetscOptionsEnd();
582: return(0);
583: }