Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/kmetis.c
3206 views
/*!1\file2\brief The top-level routines for multilevel k-way partitioning that minimizes3the edge cut.45\date Started 7/28/19976\author George7\author Copyright 1997-2011, Regents of the University of Minnesota8\version\verbatim $Id: kmetis.c 13905 2013-03-25 13:21:20Z karypis $ \endverbatim9*/1011#include "metislib.h"121314/*************************************************************************/15/*! This function is the entry point for MCKMETIS */16/*************************************************************************/17int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy,18idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts,19real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval,20idx_t *part)21{22int sigrval=0, renumber=0;23graph_t *graph;24ctrl_t *ctrl;2526/* set up malloc cleaning code and signal catchers */27if (!gk_malloc_init())28return METIS_ERROR_MEMORY;2930gk_sigtrap();3132if ((sigrval = gk_sigcatch()) != 0)33goto SIGTHROW;343536/* set up the run parameters */37ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec);38if (!ctrl) {39gk_siguntrap();40return METIS_ERROR_INPUT;41}4243/* if required, change the numbering to 0 */44if (ctrl->numflag == 1) {45Change2CNumbering(*nvtxs, xadj, adjncy);46renumber = 1;47}4849/* set up the graph */50graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt);5152/* set up multipliers for making balance computations easier */53SetupKWayBalMultipliers(ctrl, graph);5455/* set various run parameters that depend on the graph */56ctrl->CoarsenTo = gk_max((*nvtxs)/(20*gk_log2(*nparts)), 30*(*nparts));57ctrl->nIparts = (ctrl->CoarsenTo == 30*(*nparts) ? 4 : 5);5859/* take care contiguity requests for disconnected graphs */60if (ctrl->contig && !IsConnected(graph, 0))61gk_errexit(SIGERR, "METIS Error: A contiguous partition is requested for a non-contiguous input graph.\n");6263/* allocate workspace memory */64AllocateWorkSpace(ctrl, graph);6566/* start the partitioning */67IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl));68IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr));6970*objval = MlevelKWayPartitioning(ctrl, graph, part);7172IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr));73IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl));7475/* clean up */76FreeCtrl(&ctrl);7778SIGTHROW:79/* if required, change the numbering back to 1 */80if (renumber)81Change2FNumbering(*nvtxs, xadj, adjncy, part);8283gk_siguntrap();84gk_malloc_cleanup(0);8586return metis_rcode(sigrval);87}888990/*************************************************************************/91/*! This function computes a k-way partitioning of a graph that minimizes92the specified objective function.9394\param ctrl is the control structure95\param graph is the graph to be partitioned96\param part is the vector that on return will store the partitioning9798\returns the objective value of the partitoning. The partitioning99itself is stored in the part vector.100*/101/*************************************************************************/102idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part)103{104idx_t i, j, objval=0, curobj=0, bestobj=0;105real_t curbal=0.0, bestbal=0.0;106graph_t *cgraph;107int status;108109110for (i=0; i<ctrl->ncuts; i++) {111cgraph = CoarsenGraph(ctrl, graph);112113IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));114AllocateKWayPartitionMemory(ctrl, cgraph);115116/* Release the work space */117FreeWorkSpace(ctrl);118119/* Compute the initial partitioning */120InitKWayPartitioning(ctrl, cgraph);121122/* Re-allocate the work space */123AllocateWorkSpace(ctrl, graph);124AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges);125126IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));127IFSET(ctrl->dbglvl, METIS_DBG_IPART,128printf("Initial %"PRIDX"-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval));129130RefineKWay(ctrl, graph, cgraph);131132switch (ctrl->objtype) {133case METIS_OBJTYPE_CUT:134curobj = graph->mincut;135break;136137case METIS_OBJTYPE_VOL:138curobj = graph->minvol;139break;140141default:142gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);143}144145curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors);146147if (i == 0148|| (curbal <= 0.0005 && bestobj > curobj)149|| (bestbal > 0.0005 && curbal < bestbal)) {150icopy(graph->nvtxs, graph->where, part);151bestobj = curobj;152bestbal = curbal;153}154155FreeRData(graph);156157if (bestobj == 0)158break;159}160161FreeGraph(&graph);162163return bestobj;164}165166167/*************************************************************************/168/*! This function computes the initial k-way partitioning using PMETIS169*/170/*************************************************************************/171void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph)172{173idx_t i, ntrials, options[METIS_NOPTIONS], curobj=0, bestobj=0;174idx_t *bestwhere=NULL;175real_t *ubvec=NULL;176int status;177178METIS_SetDefaultOptions(options);179options[METIS_OPTION_NITER] = 10;180options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;181options[METIS_OPTION_NO2HOP] = ctrl->no2hop;182183184ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec");185for (i=0; i<graph->ncon; i++)186ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts));187188189switch (ctrl->objtype) {190case METIS_OBJTYPE_CUT:191case METIS_OBJTYPE_VOL:192options[METIS_OPTION_NCUTS] = ctrl->nIparts;193status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,194graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,195graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,196options, &curobj, graph->where);197198if (status != METIS_OK)199gk_errexit(SIGERR, "Failed during initial partitioning\n");200201break;202203#ifdef XXX /* This does not seem to help */204case METIS_OBJTYPE_VOL:205bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere");206options[METIS_OPTION_NCUTS] = 2;207208ntrials = (ctrl->nIparts+1)/2;209for (i=0; i<ntrials; i++) {210status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon,211graph->xadj, graph->adjncy, graph->vwgt, graph->vsize,212graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec,213options, &curobj, graph->where);214if (status != METIS_OK)215gk_errexit(SIGERR, "Failed during initial partitioning\n");216217curobj = ComputeVolume(graph, graph->where);218219if (i == 0 || bestobj > curobj) {220bestobj = curobj;221if (i < ntrials-1)222icopy(graph->nvtxs, graph->where, bestwhere);223}224225if (bestobj == 0)226break;227}228if (bestobj != curobj)229icopy(graph->nvtxs, bestwhere, graph->where);230231break;232#endif233234default:235gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype);236}237238gk_free((void **)&ubvec, &bestwhere, LTERM);239240}241242243244245