int SCOTCH_stratGraphClusterBuild ( SCOTCH_Strat * const straptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num pwgtval, /*+ Threshold part weight +*/ const double densval, /*+ Threshold density value +*/ const double bbalval) /*+ Maximum imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; char pwgttab[32]; char denstab[32]; char * difsptr; char * exasptr; sprintf (bbaltab, "%lf", bbalval); sprintf (denstab, "%lf", densval); sprintf (pwgttab, GNUMSTRING, pwgtval); strcpy (bufftab, "r{job=u,map=t,poli=L,sep=/((load><PWGT>)&!(edge>vert*<DENS>*(vert-1)))?(<BIPA>m{vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}})<EXAS>;}"); stringSubst (bufftab, "<BIPA>", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}}|"); if ((flagval & SCOTCH_STRATBALANCE) != 0) exasptr = "f{bal=0}"; else exasptr = ""; if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "(d{pass=40}|)"; stringSubst (bufftab, "<EXAS>", exasptr); stringSubst (bufftab, "<DIFS>", difsptr); stringSubst (bufftab, "<BBAL>", bbaltab); stringSubst (bufftab, "<DENS>", denstab); stringSubst (bufftab, "<PWGT>", pwgttab); if (SCOTCH_stratGraphMap (straptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphClusterBuild: error in sequential mapping strategy"); return (1); } return (0); }
int SCOTCH_stratGraphMapBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num partnbr, /*+ Number of expected parts/size +*/ const double balrat) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[64]; double bbalval; Gunum parttmp; /* "Unsigned" so that ">>" will always insert "0"s */ int blogval; double blogtmp; char * difsptr; char * exasptr; for (parttmp = partnbr, blogval = 1; parttmp != 0; parttmp >>= 1, blogval ++) ; /* Get log2 of number of parts */ blogtmp = 1.0 / (double) blogval; /* Taylor development of (1 + balrat) ^ (1 / blogval) */ bbalval = (balrat * blogtmp) * (1.0 + (blogtmp - 1.0) * (balrat * 0.5 * (1.0 + (blogtmp - 2.0) * balrat / 3.0))); sprintf (bbaltab, "%lf", bbalval); strcpy (bufftab, "r{job=t,map=t,poli=S,sep=(m{type=h,vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}}|m{type=h,vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}})<EXAS>}"); if ((flagval & SCOTCH_STRATBALANCE) != 0) exasptr = "f{bal=0}"; else exasptr = ""; if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "(d{dif=1,rem=1,pass=40}|)"; stringSubst (bufftab, "<EXAS>", exasptr); stringSubst (bufftab, "<DIFS>", difsptr); stringSubst (bufftab, "<BBAL>", bbaltab); if (SCOTCH_stratGraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphMapBuild: error in sequential mapping strategy"); return (1); } return (0); }
int SCOTCH_stratGraphMapBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num partnbr, /*+ Number of expected parts +*/ const double kbalval) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char kbaltab[32]; char bbaltab[32]; char * difsptr; char * exasptr; sprintf (kbaltab, "%lf", kbalval); sprintf (bbaltab, "%lf", kbalval); strcpy (bufftab, "r{job=t,map=t,poli=S,bal=<KBAL>,sep=(<BIPA>m{type=h,vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}})<EXAS>}"); stringSubst (bufftab, "<BIPA>", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{type=h,vert=80,low=h{pass=10}f{bal=<BBAL>,move=80},asc=b{bnd=<DIFS>f{bal=<BBAL>,move=80},org=f{bal=<BBAL>,move=80}}}|"); if ((flagval & SCOTCH_STRATBALANCE) != 0) exasptr = "f{bal=0}"; else exasptr = ""; if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "(d{dif=1,rem=0,pass=40}|)"; stringSubst (bufftab, "<EXAS>", exasptr); stringSubst (bufftab, "<DIFS>", difsptr); stringSubst (bufftab, "<KBAL>", kbaltab); stringSubst (bufftab, "<BBAL>", kbaltab); if (SCOTCH_stratGraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphMapBuild: error in sequential mapping strategy"); return (1); } return (0); }
// Call scotch with options from dictionary. Foam::label Foam::scotchDecomp::decompose ( const List<int>& adjncy, const List<int>& xadj, const scalarField& cWeights, List<int>& finalDecomp ) { // Dump graph if (decompositionDict_.found("scotchCoeffs")) { const dictionary& scotchCoeffs = decompositionDict_.subDict("scotchCoeffs"); if (scotchCoeffs.found("writeGraph")) { Switch writeGraph(scotchCoeffs.lookup("writeGraph")); if (writeGraph) { OFstream str(mesh_.time().path() / mesh_.name() + ".grf"); Info<< "Dumping Scotch graph file to " << str.name() << endl << "Use this in combination with gpart." << endl; label version = 0; str << version << nl; // Numer of vertices str << xadj.size()-1 << ' ' << adjncy.size() << nl; // Numbering starts from 0 label baseval = 0; // Has weights? label hasEdgeWeights = 0; label hasVertexWeights = 0; label numericflag = 10*hasEdgeWeights+hasVertexWeights; str << baseval << ' ' << numericflag << nl; for (label cellI = 0; cellI < xadj.size()-1; cellI++) { label start = xadj[cellI]; label end = xadj[cellI+1]; str << end-start; for (label i = start; i < end; i++) { str << ' ' << adjncy[i]; } str << nl; } } } } // Strategy // ~~~~~~~~ // Default. SCOTCH_Strat stradat; check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit"); if (decompositionDict_.found("scotchCoeffs")) { const dictionary& scotchCoeffs = decompositionDict_.subDict("scotchCoeffs"); string strategy; if (scotchCoeffs.readIfPresent("strategy", strategy)) { if (debug) { Info<< "scotchDecomp : Using strategy " << strategy << endl; } SCOTCH_stratGraphMap(&stradat, strategy.c_str()); //fprintf(stdout, "S\tStrat="); //SCOTCH_stratSave(&stradat, stdout); //fprintf(stdout, "\n"); } } // Graph // ~~~~~ List<int> velotab; // Check for externally provided cellweights and if so initialise weights scalar minWeights = gMin(cWeights); if (cWeights.size() > 0) { if (minWeights <= 0) { WarningIn ( "scotchDecomp::decompose" "(const pointField&, const scalarField&)" ) << "Illegal minimum weight " << minWeights << endl; } if (cWeights.size() != xadj.size()-1) { FatalErrorIn ( "scotchDecomp::decompose" "(const pointField&, const scalarField&)" ) << "Number of cell weights " << cWeights.size() << " does not equal number of cells " << xadj.size()-1 << exit(FatalError); } // Convert to integers. velotab.setSize(cWeights.size()); forAll(velotab, i) { velotab[i] = int(cWeights[i]/minWeights); } } SCOTCH_Graph grafdat; check(SCOTCH_graphInit(&grafdat), "SCOTCH_graphInit"); check ( SCOTCH_graphBuild ( &grafdat, 0, // baseval, c-style numbering xadj.size()-1, // vertnbr, nCells xadj.begin(), // verttab, start index per cell into adjncy &xadj[1], // vendtab, end index ,, velotab.begin(), // velotab, vertex weights NULL, // vlbltab adjncy.size(), // edgenbr, number of arcs adjncy.begin(), // edgetab NULL // edlotab, edge weights ), "SCOTCH_graphBuild" ); check(SCOTCH_graphCheck(&grafdat), "SCOTCH_graphCheck"); // Architecture // ~~~~~~~~~~~~ // (fully connected network topology since using switch) SCOTCH_Arch archdat; check(SCOTCH_archInit(&archdat), "SCOTCH_archInit"); List<label> processorWeights; if (decompositionDict_.found("scotchCoeffs")) { const dictionary& scotchCoeffs = decompositionDict_.subDict("scotchCoeffs"); scotchCoeffs.readIfPresent("processorWeights", processorWeights); } if (processorWeights.size()) { if (debug) { Info<< "scotchDecomp : Using procesor weights " << processorWeights << endl; } check ( SCOTCH_archCmpltw(&archdat, nProcessors_, processorWeights.begin()), "SCOTCH_archCmpltw" ); } else { check ( SCOTCH_archCmplt(&archdat, nProcessors_), "SCOTCH_archCmplt" ); } //SCOTCH_Mapping mapdat; //SCOTCH_graphMapInit(&grafdat, &mapdat, &archdat, NULL); //SCOTCH_graphMapCompute(&grafdat, &mapdat, &stradat); /* Perform mapping */ //SCOTCH_graphMapExit(&grafdat, &mapdat); // Hack:switch off fpu error trapping # ifdef LINUX_GNUC int oldExcepts = fedisableexcept ( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW ); # endif finalDecomp.setSize(xadj.size()-1); finalDecomp = 0; check ( SCOTCH_graphMap ( &grafdat, &archdat, &stradat, // const SCOTCH_Strat * finalDecomp.begin() // parttab ), "SCOTCH_graphMap" ); # ifdef LINUX_GNUC feenableexcept(oldExcepts); # endif //finalDecomp.setSize(xadj.size()-1); //check //( // SCOTCH_graphPart // ( // &grafdat, // nProcessors_, // partnbr // &stradat, // const SCOTCH_Strat * // finalDecomp.begin() // parttab // ), // "SCOTCH_graphPart" //); // Release storage for graph SCOTCH_graphExit(&grafdat); // Release storage for strategy SCOTCH_stratExit(&stradat); // Release storage for network topology SCOTCH_archExit(&archdat); return 0; }
int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Num grafflag; /* Source graph properties */ SCOTCH_Arch archdat; /* Target architecture */ SCOTCH_Strat stradat; /* Mapping strategy */ SCOTCH_Mapping mapdat; /* Mapping data */ Clock runtime[2]; /* Timing variables */ double kbalval; /* Imbalance tolerance value */ int flagval; SCOTCH_Num straval; char * straptr; int i, j; flagval = C_FLAGNONE; /* Default behavior */ straval = 0; /* No strategy flags */ straptr = NULL; i = strlen (argv[0]); if ((i >= 5) && (strncmp (argv[0] + i - 5, "gpart", 5) == 0)) { flagval |= C_FLAGPART; C_paraNbr = 1; /* One more parameter */ C_fileNbr = 3; /* One less file to provide */ errorProg ("gpart"); } else errorProg ("gmap"); intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } grafflag = 0; /* Use vertex and edge weights */ SCOTCH_stratInit (&stradat); /* Set default mapping strategy */ kbalval = 0.01; /* Set default load imbalance value */ for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < C_paraNbr) { /* If number of parameters not reached */ if ((C_partNbr = atoi (argv[i])) < 1) /* Get the number of parts */ errorPrint ("main: invalid number of parts (\"%s\")", argv[i]); C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_fileNbr) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : case 'b' : flagval |= C_FLAGKBALVAL; kbalval = atof (&argv[i][2]); if ((kbalval < 0.0) || (kbalval > 1.0) || ((kbalval == 0.0) && ((argv[i][2] != '0') && (argv[i][2] != '.')))) { errorPrint ("main: invalid load imbalance ratio"); } break; case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; default : errorPrint ("main: invalid strategy selection option (\"%c\")", argv[i][j]); } } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : case 'm' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratGraphMap (&stradat, straptr); break; case 'S' : case 's' : /* Source graph parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'E' : case 'e' : grafflag |= 2; /* Do not load edge weights */ break; case 'V' : case 'v' : grafflag |= 1; /* Do not load vertex weights */ break; default : errorPrint ("main: invalid source graph option (\"%c\")", argv[i][j]); } } break; case 'V' : fprintf (stderr, "gmap/gpart, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'M' : case 'm' : flagval |= C_FLAGVERBMAP; break; case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter \"%c\" in \"%s\"", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option (\"%s\")", argv[i]); } } } if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ C_fileTab[3].name = C_fileTab[2].name; /* Put provided file names at their right place */ C_fileTab[2].name = C_fileTab[1].name; C_fileTab[1].name = "-"; } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, grafflag); /* Read source graph */ SCOTCH_archInit (&archdat); /* Create architecture structure */ if ((flagval & C_FLAGPART) != 0) /* If program run as the partitioner */ SCOTCH_archCmplt (&archdat, C_partNbr); /* Create a complete graph of proper size */ else { SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ C_partNbr = SCOTCH_archSize (&archdat); } if ((straval != 0) || ((flagval & C_FLAGKBALVAL) != 0)) { if (straptr != NULL) errorPrint ("main: options '-b' / '-c' and '-m' are exclusive"); SCOTCH_stratGraphMapBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, kbalval); } clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); clockStart (&runtime[1]); SCOTCH_graphMapInit (&grafdat, &mapdat, &archdat, NULL); SCOTCH_graphMapCompute (&grafdat, &mapdat, &stradat); /* Perform mapping */ clockStop (&runtime[1]); /* Get computation time */ clockStart (&runtime[0]); SCOTCH_graphMapSave (&grafdat, &mapdat, C_filepntrmapout); /* Write mapping */ clockStop (&runtime[0]); /* Get output time */ if (flagval & C_FLAGVERBSTR) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if (flagval & C_FLAGVERBTIM) { fprintf (C_filepntrlogout, "T\tMapping\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", (double) clockVal (&runtime[1]), (double) clockVal (&runtime[0]), (double) clockVal (&runtime[0]) + (double) clockVal (&runtime[1])); } if (flagval & C_FLAGVERBMAP) SCOTCH_graphMapView (&grafdat, &mapdat, C_filepntrlogout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphMapExit (&grafdat, &mapdat); SCOTCH_graphExit (&grafdat); SCOTCH_stratExit (&stradat); SCOTCH_archExit (&archdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); }
int SCOTCH_stratGraphMapBuild ( SCOTCH_Strat * const straptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num partnbr, /*+ Number of expected parts/size +*/ const double kbalval) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[64]; char kbaltab[64]; char kmovtab[64]; char mvrttab[64]; Gunum parttmp; /* "Unsigned" so that ">>" will always insert "0"s */ const char * difkptr; const char * difsptr; const char * exasptr; const char * exaxptr; sprintf (bbaltab, "%lf", kbalval); sprintf (kbaltab, "%lf", kbalval); sprintf (kmovtab, GNUMSTRING, ((flagval & SCOTCH_STRATQUALITY) != 0) ? 200 : 80); sprintf (mvrttab, GNUMSTRING, MAX ((20 * partnbr), 10000)); strcpy (bufftab, ((flagval & SCOTCH_STRATRECURSIVE) != 0) ? "<RECU>" /* Use only the recursive bipartitioning framework */ : "m{vert=<MVRT>,low=<RECU>,asc=b{bnd=<DIFK>f{bal=<KBAL>,move=<KMOV>},org=f{bal=<KBAL>,move=<KMOV>}}}<EXAX>"); stringSubst (bufftab, "<RECU>", "r{job=t,map=t,poli=S,bal=<KBAL>,sep=<BSEP><EXAS>}"); stringSubst (bufftab, "<BSEP>", ((flagval & SCOTCH_STRATQUALITY) != 0) ? "<BSEQ>|<BSEQ>|<BSEQ>" : "<BSEQ>|<BSEQ>"); stringSubst (bufftab, "<BSEQ>", "m{vert=120,low=h{pass=10}f{bal=<BBAL>,move=120},asc=b{bnd=f{bal=<BBAL>,move=120},org=f{bal=<BBAL>,move=120}}}"); if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "d{pass=40}"; difkptr = "d{pass=40}"; if ((flagval & SCOTCH_STRATBALANCE) != 0) { exasptr = "f{bal=<KBAL>}"; exaxptr = "x{bal=<KBAL>}f{bal=<KBAL>,move=<KMOV>}"; } else { exasptr = ""; exaxptr = ""; } stringSubst (bufftab, "<MVRT>", mvrttab); stringSubst (bufftab, "<EXAX>", exaxptr); stringSubst (bufftab, "<EXAS>", exasptr); stringSubst (bufftab, "<DIFS>", difsptr); stringSubst (bufftab, "<DIFK>", difkptr); stringSubst (bufftab, "<KMOV>", kmovtab); stringSubst (bufftab, "<KBAL>", kbaltab); stringSubst (bufftab, "<BBAL>", bbaltab); if (SCOTCH_stratGraphMap (straptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphMapBuild: error in sequential mapping strategy"); return (1); } return (0); }
/* Internal function : biPartBoxCompute * it computes a new numbering of graph vertices, using a bipartitioning. * * - graf : the input graph * - vertNbr : the number of vertices * - boxVertNbr : the number of vertices of each box * - permVrtTab : the new numbering * * returning 0 if OK, 1 else */ int biPartBoxCompute(SCOTCH_Graph graf, int vertNbr, int boxVertNbr, SCOTCH_Num *permVrtTab) { int boxNbr, vertIdx, boxIdx; SCOTCH_Num tmp, tmp2, *partTab, *partNumTab, *partPrmTab; SCOTCH_Strat strat ; /* Computing the number of boxes */ boxNbr = vertNbr / boxVertNbr; if (boxNbr * boxVertNbr != vertNbr) { boxNbr = boxNbr + 1; } /* Initializing SCOTCH functions */ CHECK_SCOTCH(SCOTCH_stratInit(&strat), "scotch_stratInit", 0) ; CHECK_SCOTCH(SCOTCH_stratGraphMap(&strat, "r{job=t,map=t,poli=S,sep=m{type=h,vert=80,low=h{pass=10}f{bal=0.005,move=0},asc=b{bnd=f{bal=0.05,move=0},org=f{bal=0.05,move=0}}}|m{type=h,vert=80,low=h{pass=10}f{bal=0.005,move=0},asc=b{bnd=f{bal=0.05,move=0},org=f{bal=0.05,move=0}}}}"), "scotch_stratGraphMap", 0) ; partTab = (SCOTCH_Num *)M_calloc(vertNbr, sizeof(SCOTCH_Num), "boxCompute"); /* Partionning the graph */ CHECK_SCOTCH(SCOTCH_graphPart(&graf, boxNbr, &strat, partTab), "scotch_graphPart", 0); partNumTab = (SCOTCH_Num *)M_calloc(boxNbr, sizeof(SCOTCH_Num), "boxCompute"); if (!memset(partNumTab, 0, boxNbr*sizeof(SCOTCH_Num))) { perror("memset"); return 0; } /* Computing the number of elements of each box */ for( vertIdx = 0 ; vertIdx< vertNbr ;vertIdx++) partNumTab[partTab[vertIdx]] += 1; /* partition permutation tabular */ partPrmTab = (SCOTCH_Num *)M_calloc(vertNbr + 1, sizeof(SCOTCH_Num), "boxCompute"); /* Copying the previous tabular in order to have the index of the first * element of each box * */ tmp = partNumTab[0]; partNumTab[0] = 0; for(boxIdx = 1; boxIdx < boxNbr ; boxIdx++) { tmp2 = partNumTab[boxIdx]; partNumTab[boxIdx] = partNumTab[boxIdx-1] + tmp; tmp = tmp2; } /* partPrmTab is built such as each vertex belongs to his box */ for( vertIdx = 0;vertIdx< vertNbr;vertIdx++) partPrmTab[partNumTab[partTab[vertIdx]]++] = vertIdx; /* Infering the new numbering */ for (vertIdx = 0; vertIdx < vertNbr ; vertIdx++) permVrtTab[partPrmTab[vertIdx] + 1] = vertIdx + 1; M_free(partTab); M_free(partNumTab); M_free(partPrmTab); SCOTCH_stratExit(&strat) ; return 0; }
/* Internal function : kPartBoxCompute * it computes a new numbering of graph vertices, using a k-partitioning. * Assuming that baseval of the graph is 1 * * - graf : the input graph * - vertNbr : the number of vertices * - boxVertNbr : the number of vertices of each box * - permVrtTab : the new numbering * * returning 0 if OK, 1 else */ int kPartBoxCompute(SCOTCH_Graph graf, int vertNbr, int boxVertNbr, SCOTCH_Num *permVrtTab) { int boxNbr, vertIdx; SCOTCH_Num logMaxVal, SupMaxVal, InfMaxVal, maxVal; char s[200]; SCOTCH_Num *sortPartTb; SCOTCH_Strat strat ; SCOTCH_Arch arch; /* Computing the number of boxes */ boxNbr = vertNbr / boxVertNbr; if (boxNbr * boxVertNbr != vertNbr) { boxNbr = boxNbr + 1; } /* Initializing SCOTCH functions */ CHECK_SCOTCH(SCOTCH_stratInit(&strat), "scotch_stratInit", 0) ; CHECK_SCOTCH(SCOTCH_archVcmplt(&arch), "scotch_archVcmplt", 0) ; sprintf(s, "m{vert=%d,low=r{job=t,map=t,poli=S,sep=m{type=h,vert=80,low=h{pass=10}f{bal=0.0005,move=80},asc=f{bal=0.005,move=80}}}}", vertNbr / boxVertNbr); CHECK_SCOTCH(SCOTCH_stratGraphMap(&strat, s), "scotch_stratGraphMap", 0) ; sortPartTb= (SCOTCH_Num *)M_calloc(2*vertNbr, sizeof(SCOTCH_Num), "boxCompute"); /* Partionning the graph */ CHECK_SCOTCH(SCOTCH_graphMap(&graf, &arch, &strat, sortPartTb), "scotch_graphMap", 0); // Looking for the max value in sortPartTb and computing sortPartTb as // followed : // - sortPartTb[2i] is the box value // - sortPartTb[2i+1] is the vertex number maxVal = sortPartTb[0]; for (vertIdx = vertNbr - 1 ; vertIdx >= 0 ; vertIdx--) { sortPartTb[2*vertIdx] = sortPartTb[vertIdx]; sortPartTb[2*vertIdx+1] = vertIdx + 1; if (sortPartTb[vertIdx] > maxVal) maxVal = sortPartTb[vertIdx]; } // Determining the log of MaxVal logMaxVal = 0; while ( maxVal > 0) { logMaxVal++; maxVal >>= 1; } // Infering the interval in which box values will be InfMaxVal = logMaxVal << logMaxVal; SupMaxVal = (logMaxVal << (logMaxVal + 1)) - 1; // Increasing box values until they are in the previous interval for (vertIdx = 0 ; vertIdx < vertNbr ; vertIdx++) { while (!(sortPartTb[2*vertIdx] >= InfMaxVal && sortPartTb[2*vertIdx] <= SupMaxVal)) { sortPartTb[2*vertIdx] <<= 1; } } // Sorting the tabular, which contains box values and vertex numbers _SCOTCHintSort2asc1(sortPartTb, vertNbr); /* Infering the new numbering */ for (vertIdx = 0; vertIdx < vertNbr ; vertIdx++) { permVrtTab[sortPartTb[2*vertIdx + 1]] = vertIdx + 1; } SCOTCH_stratExit(&strat) ; SCOTCH_archExit(&arch) ; M_free(sortPartTb); return 0; }