Actual source code: scotch.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  2: #include <../src/mat/impls/adj/mpi/mpiadj.h>       /*I "petscmat.h" I*/

  4: EXTERN_C_BEGIN
  5: #include <ptscotch.h>
  6: EXTERN_C_END

  8: typedef struct {
  9:   double     imbalance;
 10:   SCOTCH_Num strategy;
 11: } MatPartitioning_PTScotch;

 15: /*@
 16:    MatPartitioningPTScotchSetImbalance - Sets the value of the load imbalance
 17:    ratio to be used during strategy selection.

 19:    Collective on MatPartitioning

 21:    Input Parameters:
 22: +  part - the partitioning context
 23: -  imb  - the load imbalance ratio

 25:    Options Database:
 26: .  -mat_partitioning_ptscotch_imbalance <imb>

 28:    Note:
 29:    Must be in the range [0,1]. The default value is 0.01.

 31:    Level: advanced

 33: .seealso: MatPartitioningPTScotchSetStrategy(), MatPartitioningPTScotchGetImbalance()
 34: @*/
 35: PetscErrorCode MatPartitioningPTScotchSetImbalance(MatPartitioning part,PetscReal imb)
 36: {

 42:   PetscTryMethod(part,"MatPartitioningPTScotchSetImbalance_C",(MatPartitioning,PetscReal),(part,imb));
 43:   return(0);
 44: }

 48: PetscErrorCode MatPartitioningPTScotchSetImbalance_PTScotch(MatPartitioning part,PetscReal imb)
 49: {
 50:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;

 53:   if (imb==PETSC_DEFAULT) scotch->imbalance = 0.01;
 54:   else {
 55:     if (imb<0.0 || imb>1.0) SETERRQ(PetscObjectComm((PetscObject)part),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of imb. Must be in range [0,1]");
 56:     scotch->imbalance = (double)imb;
 57:   }
 58:   return(0);
 59: }

 63: /*@
 64:    MatPartitioningPTScotchGetImbalance - Gets the value of the load imbalance
 65:    ratio used during strategy selection.

 67:    Not Collective

 69:    Input Parameter:
 70: .  part - the partitioning context

 72:    Output Parameter:
 73: .  imb  - the load imbalance ratio

 75:    Level: advanced

 77: .seealso: MatPartitioningPTScotchSetImbalance()
 78: @*/
 79: PetscErrorCode MatPartitioningPTScotchGetImbalance(MatPartitioning part,PetscReal *imb)
 80: {

 86:   PetscUseMethod(part,"MatPartitioningPTScotchGetImbalance_C",(MatPartitioning,PetscReal*),(part,imb));
 87:   return(0);
 88: }

 92: PetscErrorCode MatPartitioningPTScotchGetImbalance_PTScotch(MatPartitioning part,PetscReal *imb)
 93: {
 94:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;

 97:   *imb = scotch->imbalance;
 98:   return(0);
 99: }

103: /*@
104:    MatPartitioningPTScotchSetStrategy - Sets the strategy to be used in PTScotch.

106:    Collective on MatPartitioning

108:    Input Parameters:
109: +  part - the partitioning context
110: -  strategy - the strategy, one of
111: .vb
112:      MP_PTSCOTCH_QUALITY     - Prioritize quality over speed
113:      MP_PTSCOTCH_SPEED       - Prioritize speed over quality
114:      MP_PTSCOTCH_BALANCE     - Enforce load balance
115:      MP_PTSCOTCH_SAFETY      - Avoid methods that may fail
116:      MP_PTSCOTCH_SCALABILITY - Favor scalability as much as possible
117: .ve

119:    Options Database:
120: .  -mat_partitioning_ptscotch_strategy [quality,speed,balance,safety,scalability] - strategy

122:    Level: advanced

124:    Notes:
125:    The default is MP_SCOTCH_QUALITY. See the PTScotch documentation for more information.

127: .seealso: MatPartitioningPTScotchSetImbalance(), MatPartitioningPTScotchGetStrategy()
128: @*/
129: PetscErrorCode MatPartitioningPTScotchSetStrategy(MatPartitioning part,MPPTScotchStrategyType strategy)
130: {

136:   PetscTryMethod(part,"MatPartitioningPTScotchSetStrategy_C",(MatPartitioning,MPPTScotchStrategyType),(part,strategy));
137:   return(0);
138: }

142: PetscErrorCode MatPartitioningPTScotchSetStrategy_PTScotch(MatPartitioning part,MPPTScotchStrategyType strategy)
143: {
144:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;

147:   switch (strategy) {
148:   case MP_PTSCOTCH_QUALITY:     scotch->strategy = SCOTCH_STRATQUALITY; break;
149:   case MP_PTSCOTCH_SPEED:       scotch->strategy = SCOTCH_STRATSPEED; break;
150:   case MP_PTSCOTCH_BALANCE:     scotch->strategy = SCOTCH_STRATBALANCE; break;
151:   case MP_PTSCOTCH_SAFETY:      scotch->strategy = SCOTCH_STRATSAFETY; break;
152:   case MP_PTSCOTCH_SCALABILITY: scotch->strategy = SCOTCH_STRATSCALABILITY; break;
153:   }
154:   return(0);
155: }

159: /*@
160:    MatPartitioningPTScotchGetStrategy - Gets the strategy used in PTScotch.

162:    Not Collective

164:    Input Parameter:
165: .  part - the partitioning context

167:    Output Parameter:
168: .  strategy - the strategy

170:    Level: advanced

172: .seealso: MatPartitioningPTScotchSetStrategy()
173: @*/
174: PetscErrorCode MatPartitioningPTScotchGetStrategy(MatPartitioning part,MPPTScotchStrategyType *strategy)
175: {

181:   PetscUseMethod(part,"MatPartitioningPTScotchGetStrategy_C",(MatPartitioning,MPPTScotchStrategyType*),(part,strategy));
182:   return(0);
183: }

187: PetscErrorCode MatPartitioningPTScotchGetStrategy_PTScotch(MatPartitioning part,MPPTScotchStrategyType *strategy)
188: {
189:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;

192:   switch (scotch->strategy) {
193:   case SCOTCH_STRATQUALITY:     *strategy = MP_PTSCOTCH_QUALITY; break;
194:   case SCOTCH_STRATSPEED:       *strategy = MP_PTSCOTCH_SPEED; break;
195:   case SCOTCH_STRATBALANCE:     *strategy = MP_PTSCOTCH_BALANCE; break;
196:   case SCOTCH_STRATSAFETY:      *strategy = MP_PTSCOTCH_SAFETY; break;
197:   case SCOTCH_STRATSCALABILITY: *strategy = MP_PTSCOTCH_SCALABILITY; break;
198:   }
199:   return(0);
200: }

204: PetscErrorCode MatPartitioningView_PTScotch(MatPartitioning part, PetscViewer viewer)
205: {
206:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
207:   PetscErrorCode           ierr;
208:   PetscBool                isascii;
209:   const char               *str=0;

212:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
213:   if (isascii) {
214:     switch (scotch->strategy) {
215:     case SCOTCH_STRATQUALITY:     str = "Prioritize quality over speed"; break;
216:     case SCOTCH_STRATSPEED:       str = "Prioritize speed over quality"; break;
217:     case SCOTCH_STRATBALANCE:     str = "Enforce load balance"; break;
218:     case SCOTCH_STRATSAFETY:      str = "Avoid methods that may fail"; break;
219:     case SCOTCH_STRATSCALABILITY: str = "Favor scalability as much as possible"; break;
220:     }
221:     PetscViewerASCIIPrintf(viewer,"  Strategy=%s\n",str);
222:     PetscViewerASCIIPrintf(viewer,"  Load imbalance ratio=%g\n",scotch->imbalance);
223:   }
224:   return(0);
225: }

229: PetscErrorCode MatPartitioningSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject,MatPartitioning part)
230: {
231:   PetscErrorCode           ierr;
232:   PetscBool                flag;
233:   PetscReal                r;
234:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
235:   MPPTScotchStrategyType   strat;

238:   MatPartitioningPTScotchGetStrategy(part,&strat);
239:   PetscOptionsHead(PetscOptionsObject,"PTScotch partitioning options");
240:   PetscOptionsEnum("-mat_partitioning_ptscotch_strategy","Strategy","MatPartitioningPTScotchSetStrategy",MPPTScotchStrategyTypes,(PetscEnum)strat,(PetscEnum*)&strat,&flag);
241:   if (flag) { MatPartitioningPTScotchSetStrategy(part,strat); }
242:   PetscOptionsReal("-mat_partitioning_ptscotch_imbalance","Load imbalance ratio","MatPartitioningPTScotchSetImbalance",scotch->imbalance,&r,&flag);
243:   if (flag) { MatPartitioningPTScotchSetImbalance(part,r); }
244:   PetscOptionsTail();
245:   return(0);
246: }

250: PetscErrorCode MatPartitioningApply_PTScotch(MatPartitioning part,IS *partitioning)
251: {
252:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
253:   PetscErrorCode           ierr;
254:   PetscMPIInt              rank;
255:   Mat                      mat  = part->adj;
256:   Mat_MPIAdj               *adj = (Mat_MPIAdj*)mat->data;
257:   PetscBool                flg;
258:   PetscInt                 i,j,wgtflag=0,bs=1,nold;
259:   PetscReal                *vwgttab,deltval;
260:   SCOTCH_Num               *locals,*velotab,*veloloctab,*edloloctab,vertlocnbr,edgelocnbr,nparts=part->n;
261:   SCOTCH_Arch              archdat;
262:   SCOTCH_Dgraph            grafdat;
263:   SCOTCH_Dmapping          mappdat;
264:   SCOTCH_Strat             stradat;

267:   MPI_Comm_rank(PetscObjectComm((PetscObject)part),&rank);
268:   PetscObjectTypeCompare((PetscObject)mat,MATMPIADJ,&flg);
269:   if (!flg) {
270:     /* bs indicates if the converted matrix is "reduced" from the original and hence the
271:        resulting partition results need to be stretched to match the original matrix */
272:     nold = mat->rmap->n;
273:     MatConvert(mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat);
274:     bs   = nold/mat->rmap->n;
275:     adj  = (Mat_MPIAdj*)mat->data;
276:   }

278:   PetscMalloc1(mat->rmap->n+1,&locals);
279:   PetscMalloc1(nparts,&vwgttab);
280:   PetscMalloc1(nparts,&velotab);
281:   for (j=0; j<nparts; j++) {
282:     if (part->part_weights) vwgttab[j] = part->part_weights[j]*nparts;
283:     else vwgttab[j] = 1.0;
284:   }
285:   for (i=0; i<nparts; i++) {
286:     deltval = PetscAbsReal(vwgttab[i]-PetscFloorReal(vwgttab[i]+0.5));
287:     if (deltval>0.01) {
288:       for (j=0; j<nparts; j++) vwgttab[j] /= deltval;
289:     }
290:   }
291:   for (i=0; i<nparts; i++) velotab[i] = (SCOTCH_Num)(vwgttab[i] + 0.5);
292:   PetscFree(vwgttab);

294:   SCOTCH_dgraphInit(&grafdat,PetscObjectComm((PetscObject)part));

296:   vertlocnbr = mat->rmap->range[rank+1] - mat->rmap->range[rank];
297:   edgelocnbr = adj->i[vertlocnbr];
298:   veloloctab = (!part->vertex_weights && !(wgtflag & 2)) ? part->vertex_weights : NULL;
299:   edloloctab = (!adj->values && !(wgtflag & 1)) ? adj->values : NULL;

301:   SCOTCH_dgraphBuild(&grafdat,0,vertlocnbr,vertlocnbr,adj->i,adj->i+1,veloloctab,
302:                             NULL,edgelocnbr,edgelocnbr,adj->j,NULL,edloloctab);

304: #if defined(PETSC_USE_DEBUG)
305:   SCOTCH_dgraphCheck(&grafdat);
306: #endif

308:   SCOTCH_archInit(&archdat);
309:   SCOTCH_stratInit(&stradat);
310:   SCOTCH_stratDgraphMapBuild(&stradat,scotch->strategy,nparts,nparts,scotch->imbalance);

312:   SCOTCH_archCmpltw(&archdat,nparts,velotab);
313:   SCOTCH_dgraphMapInit(&grafdat,&mappdat,&archdat,locals);
314:   SCOTCH_dgraphMapCompute(&grafdat,&mappdat,&stradat);

316:   SCOTCH_dgraphMapExit (&grafdat,&mappdat);
317:   SCOTCH_archExit(&archdat);
318:   SCOTCH_stratExit(&stradat);
319:   SCOTCH_dgraphExit(&grafdat);
320:   PetscFree(velotab);

322:   if (bs > 1) {
323:     PetscInt *newlocals;
324:     PetscMalloc1(bs*mat->rmap->n,&newlocals);
325:     for (i=0;i<mat->rmap->n;i++) {
326:       for (j=0;j<bs;j++) {
327:         newlocals[bs*i+j] = locals[i];
328:       }
329:     }
330:     PetscFree(locals);
331:     ISCreateGeneral(PetscObjectComm((PetscObject)part),bs*mat->rmap->n,newlocals,PETSC_OWN_POINTER,partitioning);
332:   } else {
333:     ISCreateGeneral(PetscObjectComm((PetscObject)part),mat->rmap->n,locals,PETSC_OWN_POINTER,partitioning);
334:   }

336:   if (!flg) {
337:     MatDestroy(&mat);
338:   }
339:   return(0);
340: }

344: PetscErrorCode MatPartitioningDestroy_PTScotch(MatPartitioning part)
345: {
346:   MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
347:   PetscErrorCode           ierr;

350:   PetscFree(scotch);
351:   /* clear composed functions */
352:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetImbalance_C",NULL);
353:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetImbalance_C",NULL);
354:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetStrategy_C",NULL);
355:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetStrategy_C",NULL);
356:   return(0);
357: }

359: /*MC
360:    MATPARTITIONINGPTSCOTCH - Creates a partitioning context via the external package SCOTCH.

362:    Level: beginner

364:    Notes: See http://www.labri.fr/perso/pelegrin/scotch/

366: .keywords: Partitioning, create, context

368: .seealso: MatPartitioningSetType(), MatPartitioningType
369: M*/

373: PETSC_EXTERN PetscErrorCode MatPartitioningCreate_PTScotch(MatPartitioning part)
374: {
375:   PetscErrorCode           ierr;
376:   MatPartitioning_PTScotch *scotch;

379:   PetscNewLog(part,&scotch);
380:   part->data = (void*)scotch;

382:   scotch->imbalance = 0.01;
383:   scotch->strategy  = SCOTCH_STRATQUALITY;

385:   part->ops->apply          = MatPartitioningApply_PTScotch;
386:   part->ops->view           = MatPartitioningView_PTScotch;
387:   part->ops->setfromoptions = MatPartitioningSetFromOptions_PTScotch;
388:   part->ops->destroy        = MatPartitioningDestroy_PTScotch;

390:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetImbalance_C",MatPartitioningPTScotchSetImbalance_PTScotch);
391:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetImbalance_C",MatPartitioningPTScotchGetImbalance_PTScotch);
392:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetStrategy_C",MatPartitioningPTScotchSetStrategy_PTScotch);
393:   PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetStrategy_C",MatPartitioningPTScotchGetStrategy_PTScotch);
394:   return(0);
395: }