Actual source code: scotch.c
petsc-3.4.5 2014-06-29
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: PetscTryMethod(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: PetscTryMethod(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(MatPartitioning part)
230: {
231: PetscErrorCode ierr;
232: PetscBool flag;
233: PetscReal r;
234: MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
235: MPPTScotchStrategyType strat;
238: PetscOptionsHead("PTScotch partitioning options");
239: PetscOptionsEnum("-mat_partitioning_ptscotch_strategy","Strategy","MatPartitioningPTScotchSetStrategy",MPPTScotchStrategyTypes,(PetscEnum)MP_PTSCOTCH_QUALITY,(PetscEnum*)&strat,&flag);
240: if (flag) { MatPartitioningPTScotchSetStrategy(part,strat); }
241: PetscOptionsReal("-mat_partitioning_ptscotch_imbalance","Load imbalance ratio","MatPartitioningPTScotchSetImbalance",scotch->imbalance,&r,&flag);
242: if (flag) { MatPartitioningPTScotchSetImbalance(part,r); }
243: PetscOptionsTail();
244: return(0);
245: }
249: PetscErrorCode MatPartitioningApply_PTScotch(MatPartitioning part,IS *partitioning)
250: {
251: MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
252: PetscErrorCode ierr;
253: PetscMPIInt rank;
254: Mat mat = part->adj;
255: Mat_MPIAdj *adj = (Mat_MPIAdj*)mat->data;
256: PetscBool flg;
257: PetscInt i,j,wgtflag=0,bs=1,nold;
258: PetscReal *vwgttab,deltval;
259: SCOTCH_Num *locals,*velotab,*veloloctab,*edloloctab,vertlocnbr,edgelocnbr,nparts=part->n;
260: SCOTCH_Arch archdat;
261: SCOTCH_Dgraph grafdat;
262: SCOTCH_Dmapping mappdat;
263: SCOTCH_Strat stradat;
266: MPI_Comm_rank(PetscObjectComm((PetscObject)part),&rank);
267: PetscObjectTypeCompare((PetscObject)mat,MATMPIADJ,&flg);
268: if (!flg) {
269: /* bs indicates if the converted matrix is "reduced" from the original and hence the
270: resulting partition results need to be stretched to match the original matrix */
271: nold = mat->rmap->n;
272: MatConvert(mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat);
273: bs = nold/mat->rmap->n;
274: adj = (Mat_MPIAdj*)mat->data;
275: }
277: PetscMalloc((mat->rmap->n+1)*sizeof(SCOTCH_Num),&locals);
278: PetscMalloc(nparts*sizeof(PetscReal),&vwgttab);
279: PetscMalloc(nparts*sizeof(SCOTCH_Num),&velotab);
280: for (j=0; j<nparts; j++) {
281: if (part->part_weights) vwgttab[j] = part->part_weights[j]*nparts;
282: else vwgttab[j] = 1.0;
283: }
284: for (i=0; i<nparts; i++) {
285: deltval = PetscAbsReal(vwgttab[i]-floor(vwgttab[i]+0.5));
286: if (deltval>0.01) {
287: for (j=0; j<nparts; j++) vwgttab[j] /= deltval;
288: }
289: }
290: for (i=0; i<nparts; i++) velotab[i] = (SCOTCH_Num)(vwgttab[i] + 0.5);
291: PetscFree(vwgttab);
293: SCOTCH_dgraphInit(&grafdat,PetscObjectComm((PetscObject)part));
295: vertlocnbr = mat->rmap->range[rank+1] - mat->rmap->range[rank];
296: edgelocnbr = adj->i[vertlocnbr];
297: veloloctab = (!part->vertex_weights && !(wgtflag & 2)) ? part->vertex_weights : NULL;
298: edloloctab = (!adj->values && !(wgtflag & 1)) ? adj->values : NULL;
300: SCOTCH_dgraphBuild(&grafdat,0,vertlocnbr,vertlocnbr,adj->i,adj->i+1,veloloctab,
301: NULL,edgelocnbr,edgelocnbr,adj->j,NULL,edloloctab);
303: #if defined(PETSC_USE_DEBUG)
304: SCOTCH_dgraphCheck(&grafdat);
305: #endif
307: SCOTCH_archInit(&archdat);
308: SCOTCH_stratInit(&stradat);
309: SCOTCH_stratDgraphMapBuild(&stradat,scotch->strategy,nparts,nparts,scotch->imbalance);
311: SCOTCH_archCmpltw(&archdat,nparts,velotab);
312: SCOTCH_dgraphMapInit(&grafdat,&mappdat,&archdat,locals);
313: SCOTCH_dgraphMapCompute(&grafdat,&mappdat,&stradat);
315: SCOTCH_dgraphMapExit (&grafdat,&mappdat);
316: SCOTCH_archExit(&archdat);
317: SCOTCH_stratExit(&stradat);
318: SCOTCH_dgraphExit(&grafdat);
319: PetscFree(velotab);
321: if (bs > 1) {
322: PetscInt *newlocals;
323: PetscMalloc(bs*mat->rmap->n*sizeof(PetscInt),&newlocals);
324: for (i=0;i<mat->rmap->n;i++) {
325: for (j=0;j<bs;j++) {
326: newlocals[bs*i+j] = locals[i];
327: }
328: }
329: PetscFree(locals);
330: ISCreateGeneral(PetscObjectComm((PetscObject)part),bs*mat->rmap->n,newlocals,PETSC_OWN_POINTER,partitioning);
331: } else {
332: ISCreateGeneral(PetscObjectComm((PetscObject)part),mat->rmap->n,locals,PETSC_OWN_POINTER,partitioning);
333: }
335: if (!flg) {
336: MatDestroy(&mat);
337: }
338: return(0);
339: }
343: PetscErrorCode MatPartitioningDestroy_PTScotch(MatPartitioning part)
344: {
345: MatPartitioning_PTScotch *scotch = (MatPartitioning_PTScotch*)part->data;
346: PetscErrorCode ierr;
349: PetscFree(scotch);
350: /* clear composed functions */
351: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetImbalance_C",NULL);
352: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetImbalance_C",NULL);
353: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetStrategy_C",NULL);
354: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetStrategy_C",NULL);
355: return(0);
356: }
358: /*MC
359: MATPARTITIONINGPTSCOTCH - Creates a partitioning context via the external package SCOTCH.
361: Level: beginner
363: Notes: See http://www.labri.fr/perso/pelegrin/scotch/
365: .keywords: Partitioning, create, context
367: .seealso: MatPartitioningSetType(), MatPartitioningType
368: M*/
372: PETSC_EXTERN PetscErrorCode MatPartitioningCreate_PTScotch(MatPartitioning part)
373: {
374: PetscErrorCode ierr;
375: MatPartitioning_PTScotch *scotch;
378: PetscNewLog(part,MatPartitioning_PTScotch,&scotch);
379: part->data = (void*)scotch;
381: scotch->imbalance = 0.01;
382: scotch->strategy = SCOTCH_STRATQUALITY;
384: part->ops->apply = MatPartitioningApply_PTScotch;
385: part->ops->view = MatPartitioningView_PTScotch;
386: part->ops->setfromoptions = MatPartitioningSetFromOptions_PTScotch;
387: part->ops->destroy = MatPartitioningDestroy_PTScotch;
389: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetImbalance_C",MatPartitioningPTScotchSetImbalance_PTScotch);
390: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetImbalance_C",MatPartitioningPTScotchGetImbalance_PTScotch);
391: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchSetStrategy_C",MatPartitioningPTScotchSetStrategy_PTScotch);
392: PetscObjectComposeFunction((PetscObject)part,"MatPartitioningPTScotchGetStrategy_C",MatPartitioningPTScotchGetStrategy_PTScotch);
393: return(0);
394: }