Actual source code: partition.c
1: #define PETSCMAT_DLL
3: #include src/mat/matimpl.h
5: /* Logging support */
6: PetscCookie PETSCMAT_DLLEXPORT 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 PETSCMAT_DLLEXPORT 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 PETSCMAT_DLLEXPORT 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 PETSCMAT_DLLEXPORT 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 PETSCMAT_DLLEXPORT MatPartitioningRegisterDestroy(void)
129: {
133: if (MatPartitioningList) {
134: PetscFListDestroy(&MatPartitioningList);
135: MatPartitioningList = 0;
136: }
137: return(0);
138: }
142: /*@C
143: MatPartitioningGetType - Gets the Partitioning method type and name (as a string)
144: from the partitioning context.
146: Not collective
148: Input Parameter:
149: . partitioning - the partitioning context
151: Output Parameter:
152: . type - partitioner type
154: Level: intermediate
156: Not Collective
158: .keywords: Partitioning, get, method, name, type
159: @*/
160: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningGetType(MatPartitioning partitioning,MatPartitioningType *type)
161: {
163: *type = partitioning->type_name;
164: return(0);
165: }
169: /*@C
170: MatPartitioningSetNParts - Set how many partitions need to be created;
171: by default this is one per processor. Certain partitioning schemes may
172: in fact only support that option.
174: Not collective
176: Input Parameter:
177: . partitioning - the partitioning context
178: . n - the number of partitions
180: Level: intermediate
182: Not Collective
184: .keywords: Partitioning, set
186: .seealso: MatPartitioningCreate(), MatPartitioningApply()
187: @*/
188: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningSetNParts(MatPartitioning part,PetscInt n)
189: {
191: part->n = n;
192: return(0);
193: }
197: /*@C
198: MatPartitioningApply - Gets a partitioning for a matrix.
200: Collective on Mat
202: Input Parameters:
203: . matp - the matrix partitioning object
205: Output Parameters:
206: . partitioning - the partitioning. For each local node this tells the processor
207: number that that node is assigned to.
209: Options Database Keys:
210: To specify the partitioning through the options database, use one of
211: the following
212: $ -mat_partitioning_type parmetis, -mat_partitioning current
213: To see the partitioning result
214: $ -mat_partitioning_view
216: Level: beginner
218: The user can define additional partitionings; see MatPartitioningRegisterDynamic().
220: .keywords: matrix, get, partitioning
222: .seealso: MatPartitioningRegisterDynamic(), MatPartitioningCreate(),
223: MatPartitioningDestroy(), MatPartitioningSetAdjacency(), ISPartitioningToNumbering(),
224: ISPartitioningCount()
225: @*/
226: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningApply(MatPartitioning matp,IS *partitioning)
227: {
229: PetscTruth flag;
234: if (!matp->adj->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
235: if (matp->adj->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
236: if (!matp->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set type with MatPartitioningSetFromOptions() or MatPartitioningSetType()");
237: PetscLogEventBegin(MAT_Partitioning,matp,0,0,0);
238: (*matp->ops->apply)(matp,partitioning);
239: PetscLogEventEnd(MAT_Partitioning,matp,0,0,0);
241: PetscOptionsHasName(PETSC_NULL,"-mat_partitioning_view",&flag);
242: if (flag) {
243: MatPartitioningView(matp,PETSC_VIEWER_STDOUT_(matp->comm));
244: ISView(*partitioning,PETSC_VIEWER_STDOUT_(matp->comm));
245: }
246: return(0);
247: }
248:
251: /*@C
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 PETSCMAT_DLLEXPORT MatPartitioningSetAdjacency(MatPartitioning part,Mat adj)
268: {
272: part->adj = adj;
273: return(0);
274: }
278: /*@C
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 PETSCMAT_DLLEXPORT MatPartitioningDestroy(MatPartitioning part)
293: {
298: if (--part->refct > 0) return(0);
300: if (part->ops->destroy) {
301: (*part->ops->destroy)(part);
302: }
303: if (part->vertex_weights){
304: PetscFree(part->vertex_weights);
305: }
306: if (part->part_weights){
307: PetscFree(part->part_weights);
308: }
309: PetscHeaderDestroy(part);
310: return(0);
311: }
315: /*@C
316: MatPartitioningSetVertexWeights - Sets the weights for vertices for a partitioning.
318: Collective on Partitioning
320: Input Parameters:
321: + part - the partitioning context
322: - weights - the weights
324: Level: beginner
326: Notes:
327: The array weights is freed by PETSc so the user should not free the array. In C/C++
328: the array must be obtained with a call to PetscMalloc(), not malloc().
330: .keywords: Partitioning, destroy, context
332: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetPartitionWeights()
333: @*/
334: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningSetVertexWeights(MatPartitioning part,const PetscInt weights[])
335: {
341: if (part->vertex_weights){
342: PetscFree(part->vertex_weights);
343: }
344: part->vertex_weights = (PetscInt*)weights;
345: return(0);
346: }
350: /*@C
351: MatPartitioningSetPartitionWeights - Sets the weights for each partition.
353: Collective on Partitioning
355: Input Parameters:
356: + part - the partitioning context
357: - weights - the weights
359: Level: beginner
361: Notes:
362: The array weights is freed by PETSc so the user should not free the array. In C/C++
363: the array must be obtained with a call to PetscMalloc(), not malloc().
365: .keywords: Partitioning, destroy, context
367: .seealso: MatPartitioningCreate(), MatPartitioningSetType(), MatPartitioningSetVertexWeights()
368: @*/
369: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningSetPartitionWeights(MatPartitioning part,const PetscReal weights[])
370: {
376: if (part->part_weights){
377: PetscFree(part->part_weights);
378: }
379: part->part_weights = (PetscReal*)weights;
380: return(0);
381: }
385: /*@C
386: MatPartitioningCreate - Creates a partitioning context.
388: Collective on MPI_Comm
390: Input Parameter:
391: . comm - MPI communicator
393: Output Parameter:
394: . newp - location to put the context
396: Level: beginner
398: .keywords: Partitioning, create, context
400: .seealso: MatPartitioningSetType(), MatPartitioningApply(), MatPartitioningDestroy(),
401: MatPartitioningSetAdjacency()
403: @*/
404: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningCreate(MPI_Comm comm,MatPartitioning *newp)
405: {
406: MatPartitioning part;
407: PetscErrorCode ierr;
408: PetscMPIInt size;
411: *newp = 0;
413: PetscHeaderCreate(part,_p_MatPartitioning,struct _MatPartitioningOps,MAT_PARTITIONING_COOKIE,-1,"MatPartitioning",comm,MatPartitioningDestroy,
414: MatPartitioningView);
415: part->type = -1;
416: part->vertex_weights = PETSC_NULL;
417: part->part_weights = PETSC_NULL;
418: MPI_Comm_size(comm,&size);
419: part->n = (PetscInt)size;
421: *newp = part;
422: return(0);
423: }
427: /*@C
428: MatPartitioningView - Prints the partitioning data structure.
430: Collective on MatPartitioning
432: Input Parameters:
433: . part - the partitioning context
434: . viewer - optional visualization context
436: Level: intermediate
438: Note:
439: The available visualization contexts include
440: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
441: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
442: output where only the first processor opens
443: the file. All other processors send their
444: data to the first processor to print.
446: The user can open alternative visualization contexts with
447: . PetscViewerASCIIOpen() - output to a specified file
449: .keywords: Partitioning, view
451: .seealso: PetscViewerASCIIOpen()
452: @*/
453: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningView(MatPartitioning part,PetscViewer viewer)
454: {
456: PetscTruth iascii;
457: MatPartitioningType name;
461: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(part->comm);
465: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
466: if (iascii) {
467: MatPartitioningGetType(part,&name);
468: PetscViewerASCIIPrintf(viewer,"MatPartitioning Object: %s\n",name);
469: if (part->vertex_weights) {
470: PetscViewerASCIIPrintf(viewer," Using vertex weights\n");
471: }
472: } else {
473: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this MatParitioning",((PetscObject)viewer)->type_name);
474: }
476: if (part->ops->view) {
477: PetscViewerASCIIPushTab(viewer);
478: (*part->ops->view)(part,viewer);
479: PetscViewerASCIIPopTab(viewer);
480: }
482: return(0);
483: }
487: /*@C
488: MatPartitioningSetType - Sets the type of partitioner to use
490: Collective on MatPartitioning
492: Input Parameter:
493: . part - the partitioning context.
494: . type - a known method
496: Options Database Command:
497: $ -mat_partitioning_type <type>
498: $ Use -help for a list of available methods
499: $ (for instance, parmetis)
501: Level: intermediate
503: .keywords: partitioning, set, method, type
505: .seealso: MatPartitioningCreate(), MatPartitioningApply(), MatPartitioningType
507: @*/
508: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningSetType(MatPartitioning part,const MatPartitioningType type)
509: {
510: PetscErrorCode ierr,(*r)(MatPartitioning);
511: PetscTruth match;
517: PetscTypeCompare((PetscObject)part,type,&match);
518: if (match) return(0);
520: if (part->setupcalled) {
521: (*part->ops->destroy)(part);
522: part->data = 0;
523: part->setupcalled = 0;
524: }
526: /* Get the function pointers for the method requested */
527: if (!MatPartitioningRegisterAllCalled){ MatPartitioningRegisterAll(0);}
528: PetscFListFind(part->comm,MatPartitioningList,type,(void (**)(void)) &r);
530: if (!r) {SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown partitioning type %s",type);}
532: part->ops->destroy = (PetscErrorCode (*)(MatPartitioning)) 0;
533: part->ops->view = (PetscErrorCode (*)(MatPartitioning,PetscViewer)) 0;
534: (*r)(part);
536: PetscStrfree(part->type_name);
537: PetscStrallocpy(type,&part->type_name);
538: return(0);
539: }
543: /*@
544: MatPartitioningSetFromOptions - Sets various partitioning options from the
545: options database.
547: Collective on MatPartitioning
549: Input Parameter:
550: . part - the partitioning context.
552: Options Database Command:
553: $ -mat_partitioning_type <type>
554: $ Use -help for a list of available methods
555: $ (for instance, parmetis)
557: Level: beginner
559: .keywords: partitioning, set, method, type
560: @*/
561: PetscErrorCode PETSCMAT_DLLEXPORT MatPartitioningSetFromOptions(MatPartitioning part)
562: {
564: PetscTruth flag;
565: char type[256];
566: const char *def;
569: if (!MatPartitioningRegisterAllCalled){ MatPartitioningRegisterAll(0);}
570: PetscOptionsBegin(part->comm,part->prefix,"Partitioning options","MatOrderings");
571: if (!part->type_name) {
572: #if defined(PETSC_HAVE_PARMETIS)
573: def = MAT_PARTITIONING_PARMETIS;
574: #else
575: def = MAT_PARTITIONING_CURRENT;
576: #endif
577: } else {
578: def = part->type_name;
579: }
580: PetscOptionsList("-mat_partitioning_type","Type of partitioner","MatPartitioningSetType",MatPartitioningList,def,type,256,&flag);
581: if (flag) {
582: MatPartitioningSetType(part,type);
583: }
584: /*
585: Set the type if it was never set.
586: */
587: if (!part->type_name) {
588: MatPartitioningSetType(part,def);
589: }
591: if (part->ops->setfromoptions) {
592: (*part->ops->setfromoptions)(part);
593: }
594: PetscOptionsEnd();
595: return(0);
596: }