void gk_graph_FreeContents(gk_graph_t *graph) { gk_free((void *)&graph->xadj, &graph->adjncy, &graph->iadjwgt, &graph->fadjwgt, &graph->ivwgts, &graph->fvwgts, &graph->ivsizes, &graph->fvsizes, &graph->vlabels, LTERM); }
idx_t ComputeRealCutFromMoved(idx_t *vtxdist, idx_t *mvtxdist, idx_t *part, idx_t *mpart, char *filename, MPI_Comm comm) { idx_t i, j, nvtxs, mype, npes, cut; idx_t *xadj, *adjncy, *gpart, *gmpart, *perm, *sizes; MPI_Status status; gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); if (mype != 0) { gkMPI_Send((void *)part, vtxdist[mype+1]-vtxdist[mype], IDX_T, 0, 1, comm); gkMPI_Send((void *)mpart, mvtxdist[mype+1]-mvtxdist[mype], IDX_T, 0, 1, comm); } else { /* Processor 0 does all the rest */ gpart = imalloc(vtxdist[npes], "ComputeRealCut: gpart"); icopy(vtxdist[1], part, gpart); gmpart = imalloc(mvtxdist[npes], "ComputeRealCut: gmpart"); icopy(mvtxdist[1], mpart, gmpart); for (i=1; i<npes; i++) { gkMPI_Recv((void *)(gpart+vtxdist[i]), vtxdist[i+1]-vtxdist[i], IDX_T, i, 1, comm, &status); gkMPI_Recv((void *)(gmpart+mvtxdist[i]), mvtxdist[i+1]-mvtxdist[i], IDX_T, i, 1, comm, &status); } /* OK, now go and reconstruct the permutation to go from the graph to mgraph */ perm = imalloc(vtxdist[npes], "ComputeRealCut: perm"); sizes = ismalloc(npes+1, 0, "ComputeRealCut: sizes"); for (i=0; i<vtxdist[npes]; i++) sizes[gpart[i]]++; MAKECSR(i, npes, sizes); for (i=0; i<vtxdist[npes]; i++) perm[i] = sizes[gpart[i]]++; /* Ok, now read the graph from the file */ ReadMetisGraph(filename, &nvtxs, &xadj, &adjncy); /* OK, now compute the cut */ for (cut=0, i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (gmpart[perm[i]] != gmpart[perm[adjncy[j]]]) cut++; } } cut = cut/2; gk_free((void **)&gpart, &gmpart, &perm, &sizes, &xadj, &adjncy, LTERM); return cut; } return 0; }
void FreeCtrl(ctrl_t **r_ctrl) { ctrl_t *ctrl = *r_ctrl; FreeWorkSpace(ctrl); gk_free((void **)&ctrl->tpwgts, &ctrl->pijbm, &ctrl->ubfactors, &ctrl->maxvwgt, &ctrl, LTERM); *r_ctrl = NULL; }
/************************************************************************* * This function is the entry point for PWMETIS that accepts exact weights * for the target partitions **************************************************************************/ void METIS_WPartGraphRecursive(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, float *tpwgts, idxtype *options, idxtype *edgecut, idxtype *part) { idxtype i, j; GraphType graph; CtrlType ctrl; float *mytpwgts; if (*numflag == 1) Change2CNumbering(*nvtxs, xadj, adjncy); SetUpGraph(&graph, OP_PMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, *wgtflag); if (options[0] == 0) { /* Use the default parameters */ ctrl.CType = PMETIS_CTYPE; ctrl.IType = PMETIS_ITYPE; ctrl.RType = PMETIS_RTYPE; ctrl.dbglvl = PMETIS_DBGLVL; } else { ctrl.CType = options[OPTION_CTYPE]; ctrl.IType = options[OPTION_ITYPE]; ctrl.RType = options[OPTION_RTYPE]; ctrl.dbglvl = options[OPTION_DBGLVL]; } ctrl.optype = OP_PMETIS; ctrl.CoarsenTo = 20; ctrl.maxvwgt = 1.5*(idxsum(*nvtxs, graph.vwgt, 1)/ctrl.CoarsenTo); mytpwgts = gk_fmalloc(*nparts, "PWMETIS: mytpwgts"); for (i=0; i<*nparts; i++) mytpwgts[i] = tpwgts[i]; InitRandom(-1); AllocateWorkSpace(&ctrl, &graph, *nparts); IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl)); IFSET(ctrl.dbglvl, DBG_TIME, gk_startcputimer(ctrl.TotalTmr)); *edgecut = MlevelRecursiveBisection(&ctrl, &graph, *nparts, part, mytpwgts, 1.000, 0); IFSET(ctrl.dbglvl, DBG_TIME, gk_stopcputimer(ctrl.TotalTmr)); IFSET(ctrl.dbglvl, DBG_TIME, PrintTimers(&ctrl)); FreeWorkSpace(&ctrl, &graph); gk_free((void **)&mytpwgts, LTERM); if (*numflag == 1) Change2FNumbering(*nvtxs, xadj, adjncy, part); }
void FreeWorkSpace(ctrl_t *ctrl) { gk_mcoreDestroy(&ctrl->mcore, ctrl->dbglvl & METIS_DBG_INFO); IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" nbrpool statistics\n" " nbrpoolsize: %12zu nbrpoolcpos: %12zu\n" " nbrpoolreallocs: %12zu\n\n", ctrl->nbrpoolsize, ctrl->nbrpoolcpos, ctrl->nbrpoolreallocs)); gk_free((void **) &ctrl->cnbrpool, &ctrl->vnbrpool, LTERM); ctrl->nbrpoolsize = 0; ctrl->nbrpoolcpos = 0; if (ctrl->minconn) { iFreeMatrix(&(ctrl->adids), ctrl->nparts, INIT_MAXNAD); iFreeMatrix(&(ctrl->adwgts), ctrl->nparts, INIT_MAXNAD); gk_free((void **) &ctrl->pvec1, &ctrl->pvec2, &ctrl->maxnads, &ctrl->nads, LTERM); } }
int main(int argc, char *argv[]) { graph_t *graph, *fgraph; char filename[256]; idx_t wgtflag; params_t params; if (argc != 2 && argc != 3) { printf("Usage: %s <GraphFile> [FixedGraphFile (for storing the fixed graph)]\n", argv[0]); exit(0); } memset((void *) ¶ms, 0, sizeof(params_t)); params.filename = gk_strdup(argv[1]); graph = ReadGraph(¶ms); if (graph->nvtxs == 0) { printf("Empty graph!\n"); exit(0); } printf("**********************************************************************\n"); printf("%s", METISTITLE); printf(" (HEAD: %s, Built on: %s, %s)\n", SVNINFO, __DATE__, __TIME__); printf(" size of idx_t: %zubits, real_t: %zubits, idx_t *: %zubits\n", 8 * sizeof(idx_t), 8 * sizeof(real_t), 8 * sizeof(idx_t * )); printf("\n"); printf("Graph Information ---------------------------------------------------\n"); printf(" Name: %s, #Vertices: %"PRIDX", #Edges: %"PRIDX"\n\n", params.filename, graph->nvtxs, graph->nedges / 2); printf("Checking Graph... ---------------------------------------------------\n"); if (CheckGraph(graph, 1, 1)) { printf(" The format of the graph is correct!\n"); } else { printf(" The format of the graph is incorrect!\n"); if (argc == 3) { fgraph = FixGraph(graph); WriteGraph(fgraph, argv[2]); FreeGraph(&fgraph); printf(" A corrected version was stored at %s\n", argv[2]); } } printf("\n**********************************************************************\n"); FreeGraph(&graph); gk_free((void **) ¶ms.filename, ¶ms.tpwgtsfile, ¶ms.tpwgts, LTERM); }
/************************************************************************* * This function is the entry point for KMETIS with seed specification * in options[7] **************************************************************************/ void METIS_PartGraphKway2(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, idxtype *wgtflag, idxtype *numflag, idxtype *nparts, idxtype *options, idxtype *edgecut, idxtype *part) { idxtype i; float *tpwgts; tpwgts = gk_fmalloc(*nparts, "KMETIS: tpwgts"); for (i=0; i<*nparts; i++) tpwgts[i] = 1.0/(1.0*(*nparts)); METIS_WPartGraphKway2(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part); gk_free((void **)&tpwgts, LTERM); }
/************************************************************************* * This function uses simple counting sort to return a permutation array * corresponding to the sorted order. The keys are agk_fsumed to start from * 0 and they are positive. This sorting is used during matching. **************************************************************************/ void BucketSortKeysInc(idxtype n, idxtype max, idxtype *keys, idxtype *tperm, idxtype *perm) { idxtype i, ii; idxtype *counts; counts = idxsmalloc(max+2, 0, "BucketSortKeysInc: counts"); for (i=0; i<n; i++) counts[keys[i]]++; MAKECSR(i, max+1, counts); for (ii=0; ii<n; ii++) { i = tperm[ii]; perm[counts[keys[i]]++] = i; } gk_free((void **)&counts, LTERM); }
/************************************************************************* * This function computes the balance of the element partitioning **************************************************************************/ real_t ComputeElementBalance(idx_t ne, idx_t nparts, idx_t *where) { idx_t i; idx_t *kpwgts; real_t balance; kpwgts = ismalloc(nparts, 0, "ComputeElementBalance: kpwgts"); for (i=0; i<ne; i++) kpwgts[where[i]]++; balance = 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)); gk_free((void **)&kpwgts, LTERM); return balance; }
/************************************************************************* * Custom mscanf() routine **************************************************************************/ int mscanf(char *format,...) { char *new_format; int rc; va_list argp; gk_strstr_replace(format, D_PATTERN, D_SCAN_REPLACEMENT, "g", &new_format); /*mprintf("new_format: %s\n", new_format);*/ va_start(argp, format); rc = vscanf((char *)new_format, argp); va_end(argp); gk_free((void **)&new_format, LTERM); return rc; }
/************************************************************************* * Custom mfprintf() routine **************************************************************************/ int mfprintf(FILE *stream, char *format,...) { char *new_format; int rc; va_list argp; gk_strstr_replace(format, D_PATTERN, D_PRINT_REPLACEMENT, "g", &new_format); /*mprintf("new_format: %s\n", new_format);*/ va_start(argp, format); rc = vfprintf(stream, (char *)new_format, argp); va_end(argp); gk_free((void **)&new_format, LTERM); return rc; }
void FreeWSpace(ctrl_t *ctrl) { ctrl->dbglvl = 0; gk_mcoreDestroy(&ctrl->mcore, (ctrl->dbglvl&DBG_INFO)); if (ctrl->dbglvl&DBG_INFO) { printf(" nbrpool statistics [pe:%"PRIDX"]\n" " nbrpoolsize: %12zu nbrpoolcpos: %12zu\n" " nbrpoolreallocs: %12zu\n\n", ctrl->mype, ctrl->nbrpoolsize, ctrl->nbrpoolcpos, ctrl->nbrpoolreallocs); } gk_free((void **)&ctrl->cnbrpool, LTERM); ctrl->nbrpoolsize = 0; ctrl->nbrpoolcpos = 0; }
void gk_find_frequent_itemsets(int ntrans, int *tranptr, int *tranind, int minfreq, int maxfreq, int minlen, int maxlen, void (*process_itemset)(void *stateptr, int nitems, int *itemids, int ntrans, int *transids), void *stateptr) { ssize_t i; gk_csr_t *mat, *pmat; isparams_t params; int *pattern; /* Create the matrix */ mat = gk_csr_Create(); mat->nrows = ntrans; mat->ncols = tranind[gk_iargmax(tranptr[ntrans], tranind)]+1; mat->rowptr = gk_zmalloc(ntrans+1, "gk_find_frequent_itemsets: mat.rowptr"); for (i=0; i<ntrans+1; i++) mat->rowptr[i] = tranptr[i]; mat->rowind = gk_icopy(tranptr[ntrans], tranind, gk_imalloc(tranptr[ntrans], "gk_find_frequent_itemsets: mat.rowind")); mat->colids = gk_iincset(mat->ncols, 0, gk_imalloc(mat->ncols, "gk_find_frequent_itemsets: mat.colids")); /* Setup the parameters */ params.minfreq = minfreq; params.maxfreq = (maxfreq == -1 ? mat->nrows : maxfreq); params.minlen = minlen; params.maxlen = (maxlen == -1 ? mat->ncols : maxlen); params.tnitems = mat->ncols; params.callback = process_itemset; params.stateptr = stateptr; params.rmarker = gk_ismalloc(mat->nrows, 0, "gk_find_frequent_itemsets: rmarker"); params.cand = gk_ikvmalloc(mat->ncols, "gk_find_frequent_itemsets: cand"); /* Perform the initial projection */ gk_csr_CreateIndex(mat, GK_CSR_COL); pmat = itemsets_project_matrix(¶ms, mat, -1); gk_csr_Free(&mat); pattern = gk_imalloc(pmat->ncols, "gk_find_frequent_itemsets: pattern"); itemsets_find_frequent_itemsets(¶ms, pmat, 0, pattern); gk_csr_Free(&pmat); gk_free((void **)&pattern, ¶ms.rmarker, ¶ms.cand, LTERM); }
/************************************************************************* * This function performs a coarse decomposition and determines the * min-cover. * REF: Pothen ACMTrans. on Amth Software **************************************************************************/ void MinCover_Decompose(idxtype *xadj, idxtype *adjncy, idxtype asize, idxtype bsize, idxtype *mate, idxtype *cover, idxtype *csize) { idxtype i, k; idxtype *where; idxtype card[10]; where = idxmalloc(bsize, "MinCover_Decompose: where"); for (i=0; i<10; i++) card[i] = 0; for (i=0; i<asize; i++) where[i] = SC; for (; i<bsize; i++) where[i] = SR; for (i=0; i<asize; i++) if (mate[i] == -1) MinCover_ColDFS(xadj, adjncy, i, mate, where, INCOL); for (; i<bsize; i++) if (mate[i] == -1) MinCover_RowDFS(xadj, adjncy, i, mate, where, INROW); for (i=0; i<bsize; i++) card[where[i]]++; k = 0; if (idxtype_abs(card[VC]+card[SC]-card[HR]) < idxtype_abs(card[VC]-card[SR]-card[HR])) { /* S = VC+SC+HR */ /* mprintf("%D %D ",vc+sc, hr); */ for (i=0; i<bsize; i++) if (where[i] == VC || where[i] == SC || where[i] == HR) cover[k++] = i; } else { /* S = VC+SR+HR */ /* mprintf("%D %D ",vc, hr+sr); */ for (i=0; i<bsize; i++) if (where[i] == VC || where[i] == SR || where[i] == HR) cover[k++] = i; } *csize = k; gk_free((void **)&where, LTERM); }
void gk_AllocMatrix(void ***r_matrix, size_t elmlen, size_t ndim1, size_t ndim2) { gk_idx_t i, j; void **matrix; *r_matrix = NULL; if ((matrix = (void **)gk_malloc(ndim1*sizeof(void *), "gk_AllocMatrix: matrix")) == NULL) return; for (i=0; i<ndim1; i++) { if ((matrix[i] = (void *)gk_malloc(ndim2*elmlen, "gk_AllocMatrix: matrix[i]")) == NULL) { for (j=0; j<i; j++) gk_free((void **)&matrix[j], LTERM); return; } } *r_matrix = matrix; }
/************************************************************************* * This function is the entry point for detecting contacts between * bounding boxes and surface nodes **************************************************************************/ void METIS_FindContacts(void *raw_cinfo, idxtype *nboxes, double *boxcoords, idxtype *nparts, idxtype **r_cntptr, idxtype **r_cntind) { idxtype i, ncnts, tncnts, maxtncnts; idxtype *cntptr, *cntind, *auxcntind, *stack, *marker; ContactInfoType *cinfo; cinfo = (ContactInfoType *)raw_cinfo; maxtncnts = 6*(*nboxes); cntptr = idxsmalloc(*nboxes+1, 0, "METIS_FindContacts: cntptr"); cntind = idxmalloc(maxtncnts, "METIS_FindContacts: cntind"); auxcntind = idxmalloc(*nparts, "METIS_FindContacts: auxcntind"); stack = idxmalloc(cinfo->nnodes, "METIS_FindContacts: stack"); marker = idxsmalloc(*nparts, 0, "METIS_FindContacts: marker"); /* Go through each box and determine its contacting partitions */ for (tncnts=0, i=0; i<*nboxes; i++) { ncnts = FindBoxContacts(cinfo, boxcoords+i*6, stack, auxcntind, marker); if (ncnts == 0) mprintf("CSearchError: Box has no contacts!\n"); if (ncnts + tncnts >= maxtncnts) { maxtncnts += (tncnts+ncnts)*(*nboxes-i)/i; if ((cntind = (idxtype *)realloc(cntind, maxtncnts*sizeof(idxtype))) == NULL) errexit("Realloc failed! of %d words!\n", maxtncnts); } cntptr[i] = ncnts; idxcopy(ncnts, auxcntind, cntind+tncnts); tncnts += ncnts; } MAKECSR(i, *nboxes, cntptr); *r_cntptr = cntptr; *r_cntind = cntind; gk_free((void **)&auxcntind, &stack, &marker, LTERM); }
/************************************************************************* * This function takes a graph and produces a bisection by using a region * growing algorithm. The resulting partition is returned in * graph->where **************************************************************************/ void MocGrowBisection2(CtrlType *ctrl, GraphType *graph, float *tpwgts, float *ubvec) { idxtype i, j, k, nvtxs, ncon, from, bestcut, mincut, nbfs, inbfs; idxtype *bestwhere, *where; nvtxs = graph->nvtxs; MocAllocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = idxmalloc(nvtxs, "BisectGraph: bestwhere"); nbfs = 2*(nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS); for (inbfs=0; inbfs<nbfs; inbfs++) { idxset(nvtxs, 1, where); where[RandomInRange(nvtxs)] = 0; MocCompute2WayPartitionParams(ctrl, graph); MocBalance2Way2(ctrl, graph, tpwgts, ubvec); MocFM_2WayEdgeRefine2(ctrl, graph, tpwgts, ubvec, 4); MocBalance2Way2(ctrl, graph, tpwgts, ubvec); MocFM_2WayEdgeRefine2(ctrl, graph, tpwgts, ubvec, 4); if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; idxcopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; idxcopy(nvtxs, bestwhere, where); gk_free((void **)&bestwhere, LTERM); }
/************************************************************************* * This function reads the spd matrix **************************************************************************/ void ReadCoordinates(GraphType *graph, char *filename) { idxtype i, j, k, l, nvtxs, fmt, readew, readvw, ncon, edge, ewgt; FILE *fpin; char *line; fpin = gk_fopen(filename, "r", __func__); nvtxs = graph->nvtxs; graph->coords = gk_dsmalloc(3*nvtxs, 0.0, "ReadCoordinates: coords"); line = gk_cmalloc(MAXLINE+1, "ReadCoordinates: line"); for (i=0; i<nvtxs; i++) { fgets(line, MAXLINE, fpin); msscanf(line, "%lf %lf %lf", graph->coords+3*i+0, graph->coords+3*i+1, graph->coords+3*i+2); } gk_fclose(fpin); gk_free((void **)&line, LTERM); }
idx_t ComputeRealCut(idx_t *vtxdist, idx_t *part, char *filename, MPI_Comm comm) { idx_t i, j, nvtxs, mype, npes, cut; idx_t *xadj, *adjncy, *gpart; MPI_Status status; gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); if (mype != 0) { gkMPI_Send((void *)part, vtxdist[mype+1]-vtxdist[mype], IDX_T, 0, 1, comm); } else { /* Processor 0 does all the rest */ gpart = imalloc(vtxdist[npes], "ComputeRealCut: gpart"); icopy(vtxdist[1], part, gpart); for (i=1; i<npes; i++) gkMPI_Recv((void *)(gpart+vtxdist[i]), vtxdist[i+1]-vtxdist[i], IDX_T, i, 1, comm, &status); ReadMetisGraph(filename, &nvtxs, &xadj, &adjncy); /* OK, now compute the cut */ for (cut=0, i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { if (gpart[i] != gpart[adjncy[j]]) cut++; } } cut = cut/2; gk_free((void **)&gpart, &xadj, &adjncy, LTERM); return cut; } return 0; }
/************************************************************************* * This function partitions a finite element mesh by partitioning its dual * graph using KMETIS and then assigning nodes in a load balanced fashion. **************************************************************************/ int METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart) { int sigrval=0, renumber=0, ptype; idx_t i, j; idx_t *xadj=NULL, *adjncy=NULL, *nptr=NULL, *nind=NULL; idx_t ncon=1, pnumflag=0; int rstatus = METIS_OK; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; renumber = GETOPTION(options, METIS_OPTION_NUMBERING, 0); ptype = GETOPTION(options, METIS_OPTION_PTYPE, METIS_PTYPE_KWAY); /* renumber the mesh */ if (renumber) { ChangeMesh2CNumbering(*ne, eptr, eind); options[METIS_OPTION_NUMBERING] = 0; } /* get the dual graph */ rstatus = METIS_MeshToDual(ne, nn, eptr, eind, ncommon, &pnumflag, &xadj, &adjncy); if (rstatus != METIS_OK) raise(SIGERR); /* partition the graph */ if (ptype == METIS_PTYPE_KWAY) rstatus = METIS_PartGraphKway(ne, &ncon, xadj, adjncy, vwgt, vsize, NULL, nparts, tpwgts, NULL, options, objval, epart); else rstatus = METIS_PartGraphRecursive(ne, &ncon, xadj, adjncy, vwgt, vsize, NULL, nparts, tpwgts, NULL, options, objval, epart); if (rstatus != METIS_OK) raise(SIGERR); /* construct the node-element list */ nptr = ismalloc(*nn+1, 0, "METIS_PartMeshDual: nptr"); nind = imalloc(eptr[*ne], "METIS_PartMeshDual: nind"); for (i=0; i<*ne; i++) { for (j=eptr[i]; j<eptr[i+1]; j++) nptr[eind[j]]++; } MAKECSR(i, *nn, nptr); for (i=0; i<*ne; i++) { for (j=eptr[i]; j<eptr[i+1]; j++) nind[nptr[eind[j]]++] = i; } SHIFTCSR(i, *nn, nptr); /* partition the other side of the mesh */ InduceRowPartFromColumnPart(*nn, nptr, nind, npart, epart, *nparts, tpwgts); gk_free((void **)&nptr, &nind, LTERM); SIGTHROW: if (renumber) { ChangeMesh2FNumbering2(*ne, *nn, eptr, eind, epart, npart); options[METIS_OPTION_NUMBERING] = 1; } METIS_Free(xadj); METIS_Free(adjncy); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); }
void InduceRowPartFromColumnPart(idx_t nrows, idx_t *rowptr, idx_t *rowind, idx_t *rpart, idx_t *cpart, idx_t nparts, real_t *tpwgts) { idx_t i, j, k, me; idx_t nnbrs, *pwgts, *nbrdom, *nbrwgt, *nbrmrk; idx_t *itpwgts; pwgts = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: pwgts"); nbrdom = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: nbrdom"); nbrwgt = ismalloc(nparts, 0, "InduceRowPartFromColumnPart: nbrwgt"); nbrmrk = ismalloc(nparts, -1, "InduceRowPartFromColumnPart: nbrmrk"); iset(nrows, -1, rpart); /* setup the integer target partition weights */ itpwgts = imalloc(nparts, "InduceRowPartFromColumnPart: itpwgts"); if (tpwgts == NULL) { iset(nparts, 1+nrows/nparts, itpwgts); } else { for (i=0; i<nparts; i++) itpwgts[i] = 1+nrows*tpwgts[i]; } /* first assign the rows consisting only of columns that belong to a single partition. Assign rows that are empty to -2 (un-assigned) */ for (i=0; i<nrows; i++) { if (rowptr[i+1]-rowptr[i] == 0) { rpart[i] = -2; continue; } me = cpart[rowind[rowptr[i]]]; for (j=rowptr[i]+1; j<rowptr[i+1]; j++) { if (cpart[rowind[j]] != me) break; } if (j == rowptr[i+1]) { rpart[i] = me; pwgts[me]++; } } /* next assign the rows consisting of columns belonging to multiple partitions in a balanced way */ for (i=0; i<nrows; i++) { if (rpart[i] == -1) { for (nnbrs=0, j=rowptr[i]; j<rowptr[i+1]; j++) { me = cpart[rowind[j]]; if (nbrmrk[me] == -1) { nbrdom[nnbrs] = me; nbrwgt[nnbrs] = 1; nbrmrk[me] = nnbrs++; } else { nbrwgt[nbrmrk[me]]++; } } ASSERT(nnbrs > 0); /* assign it first to the domain with most things in common */ rpart[i] = nbrdom[iargmax(nnbrs, nbrwgt)]; /* if overweight, assign it to the light domain */ if (pwgts[rpart[i]] > itpwgts[rpart[i]]) { for (j=0; j<nnbrs; j++) { if (pwgts[nbrdom[j]] < itpwgts[nbrdom[j]] || pwgts[nbrdom[j]]-itpwgts[nbrdom[j]] < pwgts[rpart[i]]-itpwgts[rpart[i]]) { rpart[i] = nbrdom[j]; break; } } } pwgts[rpart[i]]++; /* reset nbrmrk array */ for (j=0; j<nnbrs; j++) nbrmrk[nbrdom[j]] = -1; } } gk_free((void **)&pwgts, &nbrdom, &nbrwgt, &nbrmrk, &itpwgts, LTERM); }
gk_seq_t *gk_seq_ReadGKMODPSSM(char *filename) { gk_seq_t *seq; gk_idx_t i, j, ii; size_t ntokens, nbytes, len; FILE *fpin; gk_Tokens_t tokens; static char *AAORDER = "ARNDCQEGHILKMFPSTWYVBZX*"; static int PSSMWIDTH = 20; char *header, line[MAXLINELEN]; gk_i2cc2i_t *converter; header = gk_cmalloc(PSSMWIDTH, "gk_seq_ReadGKMODPSSM: header"); converter = gk_i2cc2i_create_common(AAORDER); gk_getfilestats(filename, &len, &ntokens, NULL, &nbytes); len --; seq = gk_malloc(sizeof(gk_seq_t),"gk_seq_ReadGKMODPSSM"); gk_seq_init(seq); seq->len = len; seq->sequence = gk_imalloc(len, "gk_seq_ReadGKMODPSSM"); seq->pssm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); seq->psfm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); seq->nsymbols = PSSMWIDTH; seq->name = gk_getbasename(filename); fpin = gk_fopen(filename,"r","gk_seq_ReadGKMODPSSM"); /* Read the header line */ if (fgets(line, MAXLINELEN-1, fpin) == NULL) errexit("Unexpected end of file: %s\n", filename); gk_strtoupper(line); gk_strtokenize(line, " \t\n", &tokens); for (i=0; i<PSSMWIDTH; i++) header[i] = tokens.list[i][0]; gk_freetokenslist(&tokens); /* Read the rest of the lines */ for (i=0, ii=0; ii<len; ii++) { if (fgets(line, MAXLINELEN-1, fpin) == NULL) errexit("Unexpected end of file: %s\n", filename); gk_strtoupper(line); gk_strtokenize(line, " \t\n", &tokens); seq->sequence[i] = converter->c2i[(int)tokens.list[1][0]]; for (j=0; j<PSSMWIDTH; j++) { seq->pssm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+j]); seq->psfm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+PSSMWIDTH+j]); } gk_freetokenslist(&tokens); i++; } seq->len = i; /* Reset the length if certain characters were skipped */ gk_free((void **)&header, LTERM); gk_fclose(fpin); return seq; }
void InitKWayPartitioningRB(ctrl_t *ctrl, graph_t *graph) { idx_t i, options[METIS_NOPTIONS], curobj=0; idx_t *bestwhere=NULL; real_t *ubvec=NULL; int status; METIS_SetDefaultOptions(options); options[METIS_OPTION_NITER] = 10; options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; options[METIS_OPTION_NO2HOP] = ctrl->no2hop; options[METIS_OPTION_ONDISK] = ctrl->ondisk; ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec"); for (i=0; i<graph->ncon; i++) ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts)); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: case METIS_OBJTYPE_VOL: options[METIS_OPTION_NCUTS] = ctrl->nIparts; status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); break; #ifdef XXX /* This does not seem to help */ case METIS_OBJTYPE_VOL: bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere"); options[METIS_OPTION_NCUTS] = 2; ntrials = (ctrl->nIparts+1)/2; for (i=0; i<ntrials; i++) { status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); curobj = ComputeVolume(graph, graph->where); if (i == 0 || bestobj > curobj) { bestobj = curobj; if (i < ntrials-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (bestobj == 0) break; } if (bestobj != curobj) icopy(graph->nvtxs, bestwhere, graph->where); break; #endif default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } gk_free((void **)&ubvec, &bestwhere, LTERM); }
int METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm) { int sigrval=0, renumber=0; idx_t i, ii, j, l, nnvtxs=0; graph_t *graph=NULL; ctrl_t *ctrl; idx_t *cptr, *cind, *piperm; int numflag = 0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* set up the run time parameters */ ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); if (!ctrl) { gk_siguntrap(); return METIS_ERROR_INPUT; } /* if required, change the numbering to 0 */ if (ctrl->numflag == 1) { Change2CNumbering(*nvtxs, xadj, adjncy); renumber = 1; } IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); /* prune the dense columns */ if (ctrl->pfactor > 0.0) { piperm = imalloc(*nvtxs, "OMETIS: piperm"); graph = PruneGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, piperm, ctrl->pfactor); if (graph == NULL) { /* if there was no prunning, cleanup the pfactor */ gk_free((void **)&piperm, LTERM); ctrl->pfactor = 0.0; } else { nnvtxs = graph->nvtxs; ctrl->compress = 0; /* disable compression if prunning took place */ } } /* compress the graph; note that compression only happens if not prunning has taken place. */ if (ctrl->compress) { cptr = imalloc(*nvtxs+1, "OMETIS: cptr"); cind = imalloc(*nvtxs, "OMETIS: cind"); graph = CompressGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, cptr, cind); if (graph == NULL) { /* if there was no compression, cleanup the compress flag */ gk_free((void **)&cptr, &cind, LTERM); ctrl->compress = 0; } else { nnvtxs = graph->nvtxs; ctrl->cfactor = 1.0*(*nvtxs)/nnvtxs; if (ctrl->cfactor > 1.5 && ctrl->nseps == 1) ctrl->nseps = 2; //ctrl->nseps = (idx_t)(ctrl->cfactor*ctrl->nseps); } } /* if no prunning and no compression, setup the graph in the normal way. */ if (ctrl->pfactor == 0.0 && ctrl->compress == 0) graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); ASSERT(CheckGraph(graph, ctrl->numflag, 1)); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* do the nested dissection ordering */ if (ctrl->ccorder) MlevelNestedDissectionCC(ctrl, graph, iperm, graph->nvtxs); else MlevelNestedDissection(ctrl, graph, iperm, graph->nvtxs); if (ctrl->pfactor > 0.0) { /* Order any prunned vertices */ icopy(nnvtxs, iperm, perm); /* Use perm as an auxiliary array */ for (i=0; i<nnvtxs; i++) iperm[piperm[i]] = perm[i]; for (i=nnvtxs; i<*nvtxs; i++) iperm[piperm[i]] = i; gk_free((void **)&piperm, LTERM); } else if (ctrl->compress) { /* Uncompress the ordering */ /* construct perm from iperm */ for (i=0; i<nnvtxs; i++) perm[iperm[i]] = i; for (l=ii=0; ii<nnvtxs; ii++) { i = perm[ii]; for (j=cptr[i]; j<cptr[i+1]; j++) iperm[cind[j]] = l++; } gk_free((void **)&cptr, &cind, LTERM); } for (i=0; i<*nvtxs; i++) perm[iperm[i]] = i; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); SIGTHROW: /* if required, change the numbering back to 1 */ if (renumber) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); }
/************************************************************************* * Let the game begin **************************************************************************/ int main(int argc, char *argv[]) { idx_t i, j, npes, mype, optype, nparts, adptf, options[10]; idx_t *part=NULL, *sizes=NULL; graph_t graph; real_t ipc2redist, *xyz=NULL, *tpwgts=NULL, ubvec[MAXNCON]; MPI_Comm comm; idx_t numflag=0, wgtflag=0, ndims, edgecut; char xyzfilename[8192]; MPI_Init(&argc, &argv); MPI_Comm_dup(MPI_COMM_WORLD, &comm); gkMPI_Comm_size(comm, &npes); gkMPI_Comm_rank(comm, &mype); if (argc != 8) { if (mype == 0) printf("Usage: %s <graph-file> <op-type> <nparts> <adapth-factor> <ipc2redist> <dbglvl> <seed>\n", argv[0]); MPI_Finalize(); exit(0); } optype = atoi(argv[2]); nparts = atoi(argv[3]); adptf = atoi(argv[4]); ipc2redist = atof(argv[5]); options[0] = 1; options[PMV3_OPTION_DBGLVL] = atoi(argv[6]); options[PMV3_OPTION_SEED] = atoi(argv[7]); if (mype == 0) printf("reading file: %s\n", argv[1]); ParallelReadGraph(&graph, argv[1], comm); /* Remove the edges for testing */ /*iset(graph.vtxdist[mype+1]-graph.vtxdist[mype]+1, 0, graph.xadj); */ rset(graph.ncon, 1.05, ubvec); tpwgts = rmalloc(nparts*graph.ncon, "tpwgts"); rset(nparts*graph.ncon, 1.0/(real_t)nparts, tpwgts); /* ChangeToFortranNumbering(graph.vtxdist, graph.xadj, graph.adjncy, mype, npes); numflag = 1; nvtxs = graph.vtxdist[mype+1]-graph.vtxdist[mype]; nedges = graph.xadj[nvtxs]; printf("%"PRIDX" %"PRIDX"\n", isum(nvtxs, graph.xadj, 1), isum(nedges, graph.adjncy, 1)); */ if (optype >= 20) { sprintf(xyzfilename, "%s.xyz", argv[1]); xyz = ReadTestCoordinates(&graph, xyzfilename, &ndims, comm); } if (mype == 0) printf("finished reading file: %s\n", argv[1]); part = ismalloc(graph.nvtxs, mype%nparts, "main: part"); sizes = imalloc(2*npes, "main: sizes"); switch (optype) { case 1: wgtflag = 3; ParMETIS_V3_PartKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &graph.ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); WritePVector(argv[1], graph.vtxdist, part, MPI_COMM_WORLD); break; case 2: wgtflag = 3; options[PMV3_OPTION_PSR] = PARMETIS_PSR_COUPLED; ParMETIS_V3_RefineKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &graph.ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); WritePVector(argv[1], graph.vtxdist, part, MPI_COMM_WORLD); break; case 3: options[PMV3_OPTION_PSR] = PARMETIS_PSR_COUPLED; graph.vwgt = ismalloc(graph.nvtxs, 1, "main: vwgt"); if (npes > 1) { AdaptGraph(&graph, adptf, comm); } else { wgtflag = 3; ParMETIS_V3_PartKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &graph.ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); printf("Initial partitioning with edgecut of %"PRIDX"\n", edgecut); for (i=0; i<graph.ncon; i++) { for (j=0; j<graph.nvtxs; j++) { if (part[j] == i) graph.vwgt[j*graph.ncon+i] = adptf; else graph.vwgt[j*graph.ncon+i] = 1; } } } wgtflag = 3; ParMETIS_V3_AdaptiveRepart(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, NULL, graph.adjwgt, &wgtflag, &numflag, &graph.ncon, &nparts, tpwgts, ubvec, &ipc2redist, options, &edgecut, part, &comm); break; case 4: ParMETIS_V3_NodeND(graph.vtxdist, graph.xadj, graph.adjncy, &numflag, options, part, sizes, &comm); /* WriteOVector(argv[1], graph.vtxdist, part, comm); */ break; case 5: ParMETIS_SerialNodeND(graph.vtxdist, graph.xadj, graph.adjncy, &numflag, options, part, sizes, &comm); /* WriteOVector(argv[1], graph.vtxdist, part, comm); */ printf("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], sizes[5], sizes[6]); break; case 11: /* TestAdaptiveMETIS(graph.vtxdist, graph.xadj, graph.adjncy, part, options, adptf, comm); */ break; case 20: wgtflag = 3; ParMETIS_V3_PartGeomKway(graph.vtxdist, graph.xadj, graph.adjncy, graph.vwgt, graph.adjwgt, &wgtflag, &numflag, &ndims, xyz, &graph.ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &comm); break; case 21: ParMETIS_V3_PartGeom(graph.vtxdist, &ndims, xyz, part, &comm); break; } /* printf("%"PRIDX" %"PRIDX"\n", isum(nvtxs, graph.xadj, 1), isum(nedges, graph.adjncy, 1)); */ gk_free((void **)&part, &sizes, &tpwgts, &graph.vtxdist, &graph.xadj, &graph.adjncy, &graph.vwgt, &graph.adjwgt, &xyz, LTERM); MPI_Comm_free(&comm); MPI_Finalize(); return 0; }
/************************************************************************* * This function performs a k-way directed diffusion **************************************************************************/ real_t WavefrontDiffusion(ctrl_t *ctrl, graph_t *graph, idx_t *home) { idx_t ii, i, j, k, l, nvtxs, nedges, nparts; idx_t from, to, edge, done, nswaps, noswaps, totalv, wsize; idx_t npasses, first, second, third, mind, maxd; idx_t *xadj, *adjncy, *adjwgt, *where, *perm; idx_t *rowptr, *colind, *ed, *psize; real_t *transfer, *tmpvec; real_t balance = -1.0, *load, *solution, *workspace; real_t *nvwgt, *npwgts, flowFactor, cost, ubfactor; matrix_t matrix; ikv_t *cand; idx_t ndirty, nclean, dptr, clean; nvtxs = graph->nvtxs; nedges = graph->nedges; xadj = graph->xadj; nvwgt = graph->nvwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; nparts = ctrl->nparts; ubfactor = ctrl->ubvec[0]; matrix.nrows = nparts; flowFactor = 0.35; flowFactor = (ctrl->mype == 2) ? 0.50 : flowFactor; flowFactor = (ctrl->mype == 3) ? 0.75 : flowFactor; flowFactor = (ctrl->mype == 4) ? 1.00 : flowFactor; /* allocate memory */ solution = rmalloc(4*nparts+2*nedges, "WavefrontDiffusion: solution"); tmpvec = solution + nparts; npwgts = solution + 2*nparts; load = solution + 3*nparts; matrix.values = solution + 4*nparts; transfer = matrix.transfer = solution + 4*nparts + nedges; perm = imalloc(2*nvtxs+2*nparts+nedges+1, "WavefrontDiffusion: perm"); ed = perm + nvtxs; psize = perm + 2*nvtxs; rowptr = matrix.rowptr = perm + 2*nvtxs + nparts; colind = matrix.colind = perm + 2*nvtxs + 2*nparts + 1; /*GKTODO - Potential problem with this malloc */ wsize = gk_max(sizeof(real_t)*nparts*6, sizeof(idx_t)*(nvtxs+nparts*2+1)); workspace = (real_t *)gk_malloc(wsize, "WavefrontDiffusion: workspace"); cand = ikvmalloc(nvtxs, "WavefrontDiffusion: cand"); /*****************************/ /* Populate empty subdomains */ /*****************************/ iset(nparts, 0, psize); for (i=0; i<nvtxs; i++) psize[where[i]]++; mind = iargmin(nparts, psize); maxd = iargmax(nparts, psize); if (psize[mind] == 0) { for (i=0; i<nvtxs; i++) { k = (RandomInRange(nvtxs)+i)%nvtxs; if (where[k] == maxd) { where[k] = mind; psize[mind]++; psize[maxd]--; break; } } } iset(nvtxs, 0, ed); rset(nparts, 0.0, npwgts); for (i=0; i<nvtxs; i++) { npwgts[where[i]] += nvwgt[i]; for (j=xadj[i]; j<xadj[i+1]; j++) ed[i] += (where[i] != where[adjncy[j]] ? adjwgt[j] : 0); } ComputeLoad(graph, nparts, load, ctrl->tpwgts, 0); done = 0; /* zero out the tmpvec array */ rset(nparts, 0.0, tmpvec); npasses = gk_min(nparts/2, NGD_PASSES); for (l=0; l<npasses; l++) { /* Set-up and solve the diffusion equation */ nswaps = 0; /************************/ /* Solve flow equations */ /************************/ SetUpConnectGraph(graph, &matrix, (idx_t *)workspace); /* check for disconnected subdomains */ for(i=0; i<matrix.nrows; i++) { if (matrix.rowptr[i]+1 == matrix.rowptr[i+1]) { cost = (real_t)(ctrl->mype); goto CleanUpAndExit; } } ConjGrad2(&matrix, load, solution, 0.001, workspace); ComputeTransferVector(1, &matrix, solution, transfer, 0); GetThreeMax(nparts, load, &first, &second, &third); if (l%3 == 0) { FastRandomPermute(nvtxs, perm, 1); } else { /*****************************/ /* move dirty vertices first */ /*****************************/ ndirty = 0; for (i=0; i<nvtxs; i++) { if (where[i] != home[i]) ndirty++; } dptr = 0; for (i=0; i<nvtxs; i++) { if (where[i] != home[i]) perm[dptr++] = i; else perm[ndirty++] = i; } PASSERT(ctrl, ndirty == nvtxs); ndirty = dptr; nclean = nvtxs-dptr; FastRandomPermute(ndirty, perm, 0); FastRandomPermute(nclean, perm+ndirty, 0); } if (ctrl->mype == 0) { for (j=nvtxs, k=0, ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (ed[i] != 0) { cand[k].key = -ed[i]; cand[k++].val = i; } else { cand[--j].key = 0; cand[j].val = i; } } ikvsorti(k, cand); } for (ii=0; ii<nvtxs/3; ii++) { i = (ctrl->mype == 0) ? cand[ii].val : perm[ii]; from = where[i]; /* don't move out the last vertex in a subdomain */ if (psize[from] == 1) continue; clean = (from == home[i]) ? 1 : 0; /* only move from top three or dirty vertices */ if (from != first && from != second && from != third && clean) continue; /* Scatter the sparse transfer row into the dense tmpvec row */ for (j=rowptr[from]+1; j<rowptr[from+1]; j++) tmpvec[colind[j]] = transfer[j]; for (j=xadj[i]; j<xadj[i+1]; j++) { to = where[adjncy[j]]; if (from != to) { if (tmpvec[to] > (flowFactor * nvwgt[i])) { tmpvec[to] -= nvwgt[i]; INC_DEC(psize[to], psize[from], 1); INC_DEC(npwgts[to], npwgts[from], nvwgt[i]); INC_DEC(load[to], load[from], nvwgt[i]); where[i] = to; nswaps++; /* Update external degrees */ ed[i] = 0; for (k=xadj[i]; k<xadj[i+1]; k++) { edge = adjncy[k]; ed[i] += (to != where[edge] ? adjwgt[k] : 0); if (where[edge] == from) ed[edge] += adjwgt[k]; if (where[edge] == to) ed[edge] -= adjwgt[k]; } break; } } } /* Gather the dense tmpvec row into the sparse transfer row */ for (j=rowptr[from]+1; j<rowptr[from+1]; j++) { transfer[j] = tmpvec[colind[j]]; tmpvec[colind[j]] = 0.0; } ASSERT(fabs(rsum(nparts, tmpvec, 1)) < .0001) } if (l % 2 == 1) { balance = rmax(nparts, npwgts)*nparts; if (balance < ubfactor + 0.035) done = 1; if (GlobalSESum(ctrl, done) > 0) break; noswaps = (nswaps > 0) ? 0 : 1; if (GlobalSESum(ctrl, noswaps) > ctrl->npes/2) break; } } graph->mincut = ComputeSerialEdgeCut(graph); totalv = Mc_ComputeSerialTotalV(graph, home); cost = ctrl->ipc_factor * (real_t)graph->mincut + ctrl->redist_factor * (real_t)totalv; CleanUpAndExit: gk_free((void **)&solution, (void **)&perm, (void **)&workspace, (void **)&cand, LTERM); return cost; }
void FreeVault(vault_t *vault) { gk_csr_Free(&vault->mat); gk_free((void **)&vault, LTERM); }
/************************************************************************* * Let the game begin **************************************************************************/ int main(int argc, char *argv[]) { idxtype i, j, istep, options[10], nn, ne, fstep, lstep, nparts, nboxes, u[3], dim, nchanges, ncomm; char filename[256]; idxtype *mien, *mrng, *part, *oldpart, *sflag, *bestdims, *fepart; double *mxyz, *bxyz; idxtype *xadj, *adjncy, *cntptr, *cntind; idxtype numflag = 0, wgtflag = 0, edgecut, etype=2; void *cinfo; FILE *fpin; long long int *ltmp; if (argc != 6) { mfprintf(stderr, "Usage: %s <nn> <ne> <fstep> <lstep> <nparts>\n", argv[0]); exit(0); } nn = atoi(argv[1]); ne = atoi(argv[2]); fstep = atoi(argv[3]); lstep = atoi(argv[4]); nparts = atoi(argv[5]); mprintf("Reading %s, nn: %D, ne: %D, fstep: %D, lstep: %D, nparts: %D\n", filename, nn, ne, fstep, lstep, nparts); mien = idxmalloc(4*ne, "main: mien"); mxyz = gk_dmalloc(3*nn, "main: mxyz"); mrng = idxmalloc(4*ne, "main: mrng"); bxyz = gk_dmalloc(6*ne*4, "main: bxyz"); fepart = idxmalloc(nn, "main: fepart"); part = idxmalloc(nn, "main: part"); oldpart = idxmalloc(nn, "main: oldpart"); sflag = idxmalloc(nn, "main: sflag"); bestdims = idxsmalloc(2*nparts, -1, "main: bestdims"); xadj = idxmalloc(nn+1, "main: xadj"); adjncy = idxmalloc(50*nn, "main: adjncy"); /*======================================================================== * Read the initial mesh and setup the graph and contact information *========================================================================*/ msprintf(filename, "mien.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mien"); fread(mien, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mien[i] = Flip_int32(mien[i]); GKfclose(fpin); msprintf(filename, "mxyz.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mxyz"); fread(mxyz, sizeof(double), 3*nn, fpin); for (i=0; i<3*nn; i++) { ltmp = (long long int *)(mxyz+i); *ltmp = Flip_int64(*ltmp); } GKfclose(fpin); mprintf("%e %e %e\n", mxyz[3*0+0], mxyz[3*0+1], mxyz[3*0+2]); msprintf(filename, "mrng.%04D", fstep); fpin = GKfopen(filename, "rb", "main: mrng"); fread(mrng, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mrng[i] = Flip_int32(mrng[i]); GKfclose(fpin); /*======================================================================== * Determine which nodes are in the surface *========================================================================*/ iset(nn, 0, sflag); for (i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } } mprintf("Contact Nodes: %D of %D\n", isum(nn, sflag), nn); /*======================================================================== * Compute the FE partition *========================================================================*/ numflag = mien[idxargmin(4*ne, mien)]; METIS_MeshToNodal(&ne, &nn, mien, &etype, &numflag, xadj, adjncy); options[0] = 0; METIS_PartGraphVKway(&nn, xadj, adjncy, NULL, NULL, &wgtflag, &numflag, &nparts, options, &edgecut, fepart); mprintf("K-way partitioning Volume: %D\n", edgecut); /*======================================================================== * Get into the loop in which you go over the different configurations *========================================================================*/ for (istep=fstep; istep<=lstep; istep++) { msprintf(filename, "mxyz.%04D", istep); mprintf("Reading %s...............................................................\n", filename); fpin = GKfopen(filename, "rb", "main: mxyz"); fread(mxyz, sizeof(double), 3*nn, fpin); for (i=0; i<3*nn; i++) { ltmp = (long long int *)(mxyz+i); *ltmp = Flip_int64(*ltmp); } GKfclose(fpin); msprintf(filename, "mrng.%04D", istep); fpin = GKfopen(filename, "rb", "main: mrng"); fread(mrng, sizeof(int), 4*ne, fpin); for (i=0; i<4*ne; i++) mrng[i] = Flip_int32(mrng[i]); GKfclose(fpin); /* Determine which nodes are in the surface */ iset(nn, 0, sflag); for (i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ sflag[mien[4*i+1]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ sflag[mien[4*i+0]-1] = 1; sflag[mien[4*i+2]-1] = 1; sflag[mien[4*i+3]-1] = 1; } } mprintf("Contact Nodes: %D of %D\n", isum(nn, sflag), nn); /* Determine the bounding boxes of the surface elements */ for (nboxes=0, i=0; i<ne; i++) { if (mrng[4*i+0] > 0) { /* 1, 2, 3 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+1]-1; u[2] = mien[4*i+2]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+1] > 0) { /* 1, 2, 4 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+1]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+2] > 0) { /* 2, 3, 4 */ u[0] = mien[4*i+1]-1; u[1] = mien[4*i+2]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } if (mrng[4*i+3] > 0) { /* 1, 3, 4 */ u[0] = mien[4*i+0]-1; u[1] = mien[4*i+2]-1; u[2] = mien[4*i+3]-1; bxyz[6*nboxes+0] = bxyz[6*nboxes+3] = mxyz[3*u[0]+0]; bxyz[6*nboxes+1] = bxyz[6*nboxes+4] = mxyz[3*u[0]+1]; bxyz[6*nboxes+2] = bxyz[6*nboxes+5] = mxyz[3*u[0]+2]; for (j=1; j<3; j++) { for (dim=0; dim<3; dim++) { bxyz[6*nboxes+dim] = (bxyz[6*nboxes+dim] > mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+dim]); bxyz[6*nboxes+3+dim] = (bxyz[6*nboxes+3+dim] < mxyz[3*u[j]+dim] ? mxyz[3*u[j]+dim] : bxyz[6*nboxes+3+dim]); } } nboxes++; } } cinfo = METIS_PartSurfForContactRCB(&nn, mxyz, sflag, &nparts, part, bestdims); METIS_FindContacts(cinfo, &nboxes, bxyz, &nparts, &cntptr, &cntind); METIS_FreeContactInfo(cinfo); nchanges = 0; if (istep > fstep) { for (i=0; i<nn; i++) nchanges += (part[i] != oldpart[i] ? 1 : 0); } idxcopy(nn, part, oldpart); ncomm = ComputeMapCost(nn, nparts, fepart, part); mprintf("Contacting Elements: %D Indices: %D Nchanges: %D MapCost: %D\n", nboxes, cntptr[nboxes]-nboxes, nchanges, ncomm); gk_free((void **)&cntptr, &cntind, LTERM); } }
int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, char **new_str) { gk_idx_t i; int j, rc, flags, global, nmatches; size_t len, rlen, nlen, offset, noffset; regex_t re; regmatch_t matches[10]; /* Parse the options */ flags = REG_EXTENDED; if (strchr(options, 'i') != NULL) flags = flags | REG_ICASE; global = (strchr(options, 'g') != NULL ? 1 : 0); /* Compile the regex */ if ((rc = regcomp(&re, pattern, flags)) != 0) { len = regerror(rc, &re, NULL, 0); *new_str = gk_cmalloc(len, "gk_strstr_replace: new_str"); regerror(rc, &re, *new_str, len); return 0; } /* Prepare the output string */ len = strlen(str); nlen = 2*len; noffset = 0; *new_str = gk_cmalloc(nlen+1, "gk_strstr_replace: new_str"); /* Get into the matching-replacing loop */ rlen = strlen(replacement); offset = 0; nmatches = 0; do { rc = regexec(&re, str+offset, 10, matches, 0); if (rc == REG_ESPACE) { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("regexec ran out of memory."); regfree(&re); return 0; } else if (rc == REG_NOMATCH) { if (nlen-noffset < len-offset) { nlen += (len-offset) - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strcpy(*new_str+noffset, str+offset); noffset += (len-offset); break; } else { /* A match was found! */ nmatches++; /* Copy the left unmatched portion of the string */ if (matches[0].rm_so > 0) { if (nlen-noffset < matches[0].rm_so) { nlen += matches[0].rm_so - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strncpy(*new_str+noffset, str+offset, matches[0].rm_so); noffset += matches[0].rm_so; } /* Go and append the replacement string */ for (i=0; i<rlen; i++) { switch (replacement[i]) { case '\\': if (i+1 < rlen) { if (nlen-noffset < 1) { nlen += nlen + 1; *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } *new_str[noffset++] = replacement[++i]; } else { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("Error in replacement string. Missing character following '\'."); regfree(&re); return 0; } break; case '$': if (i+1 < rlen) { j = (int)(replacement[++i] - '0'); if (j < 0 || j > 9) { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("Error in captured subexpression specification."); regfree(&re); return 0; } if (nlen-noffset < matches[j].rm_eo-matches[j].rm_so) { nlen += nlen + (matches[j].rm_eo-matches[j].rm_so); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strncpy(*new_str+noffset, str+offset+matches[j].rm_so, matches[j].rm_eo); noffset += matches[j].rm_eo-matches[j].rm_so; } else { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("Error in replacement string. Missing subexpression number folloing '$'."); regfree(&re); return 0; } break; default: if (nlen-noffset < 1) { nlen += nlen + 1; *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } (*new_str)[noffset++] = replacement[i]; } } /* Update the offset of str for the next match */ offset += matches[0].rm_eo; if (!global) { /* Copy the right portion of the string if no 'g' option */ if (nlen-noffset < len-offset) { nlen += (len-offset) - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strcpy(*new_str+noffset, str+offset); noffset += (len-offset); } } } while (global); (*new_str)[noffset] = '\0'; regfree(&re); return nmatches + 1; }
/************************************************************************* * This function performs a coarse decomposition and determines the * min-cover. * REF: Pothen ACMTrans. on Amth Software **************************************************************************/ void MinCover_Decompose(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *mate, idx_t *cover, idx_t *csize) { idx_t i, k; idx_t *where; idx_t card[10]; where = imalloc(bsize, "MinCover_Decompose: where"); for (i = 0; i < 10; i++) { card[i] = 0; } for (i = 0; i < asize; i++) { where[i] = SC; } for (; i < bsize; i++) { where[i] = SR; } for (i = 0; i < asize; i++) { if (mate[i] == -1) { MinCover_ColDFS(xadj, adjncy, i, mate, where, INCOL); } } for (; i < bsize; i++) { if (mate[i] == -1) { MinCover_RowDFS(xadj, adjncy, i, mate, where, INROW); } } for (i = 0; i < bsize; i++) { card[where[i]]++; } k = 0; if (iabs(card[VC] + card[SC] - card[HR]) < iabs(card[VC] - card[SR] - card[HR])) { /* S = VC+SC+HR */ /* printf("%"PRIDX" %"PRIDX" ",vc+sc, hr); */ for (i = 0; i < bsize; i++) { if (where[i] == VC || where[i] == SC || where[i] == HR) { cover[k++] = i; } } } else { /* S = VC+SR+HR */ /* printf("%"PRIDX" %"PRIDX" ",vc, hr+sr); */ for (i = 0; i < bsize; i++) { if (where[i] == VC || where[i] == SR || where[i] == HR) { cover[k++] = i; } } } *csize = k; gk_free((void **) &where, LTERM); }