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: }