/************************************************************************* * This function takes a graph and produces a bisection of it **************************************************************************/ int MlevelKWayPartitioning(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *part, float *tpwgts, float ubfactor) { int i, j, nvtxs, tvwgt, tpwgts2[2]; GraphType *cgraph; int wgtflag=3, numflag=0, options[10], edgecut; cgraph = Coarsen2Way(ctrl, graph); IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr)); AllocateKWayPartitionMemory(ctrl, cgraph, nparts); options[0] = 1; options[OPTION_CTYPE] = MATCH_SHEMKWAY; options[OPTION_ITYPE] = IPART_GGPKL; options[OPTION_RTYPE] = RTYPE_FM; options[OPTION_DBGLVL] = 0; METIS_WPartGraphRecursive(&cgraph->nvtxs, cgraph->xadj, cgraph->adjncy, cgraph->vwgt, cgraph->adjwgt, &wgtflag, &numflag, &nparts, tpwgts, options, &edgecut, cgraph->where); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr)); IFSET(ctrl->dbglvl, DBG_IPART, printf("Initial %d-way partitioning cut: %d\n", nparts, edgecut)); IFSET(ctrl->dbglvl, DBG_KWAYPINFO, ComputePartitionInfo(cgraph, nparts, cgraph->where)); RefineKWay(ctrl, graph, cgraph, nparts, tpwgts, ubfactor); idxcopy(graph->nvtxs, graph->where, part); GKfree(&graph->gdata, &graph->rdata, LTERM); return graph->mincut; }
/************************************************************************* * This function is the entry point for PMETIS **************************************************************************/ void METIS_PartGraphRecursive(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, int *options, int *edgecut, idxtype *part) { int i; floattype *tpwgts; tpwgts = fmalloc(*nparts, "KMETIS: tpwgts"); for (i=0; i<*nparts; i++) tpwgts[i] = 1.0/(1.0*(*nparts)); METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part); free(tpwgts); }
/************************************************************************* * This function is the entry point for PMETIS **************************************************************************/ void METIS_PartGraphRecursive(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_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part); gk_free((void **)&tpwgts, LTERM); }
void metis_wpartgraphrecursive__(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, float *tpwgts, int *options, int *edgecut, idxtype *part) { METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part); }
void METIS_WPARTGRAPHRECURSIVE(int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, float *tpwgts, int *options, int *edgecut, idxtype *part) { METIS_WPartGraphRecursive(nvtxs, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, tpwgts, options, edgecut, part); }
// Call Metis with options from dictionary. Foam::label Foam::metisDecomp::decompose ( const List<int>& adjncy, const List<int>& xadj, const scalarField& cWeights, List<int>& finalDecomp ) { // C style numbering int numFlag = 0; // Method of decomposition // recursive: multi-level recursive bisection (default) // k-way: multi-level k-way word method("k-way"); int numCells = xadj.size()-1; // decomposition options. 0 = use defaults List<int> options(5, 0); // processor weights initialised with no size, only used if specified in // a file Field<floatScalar> processorWeights; // cell weights (so on the vertices of the dual) List<int> cellWeights; // face weights (so on the edges of the dual) List<int> faceWeights; // Check for externally provided cellweights and if so initialise weights scalar minWeights = gMin(cWeights); if (cWeights.size() > 0) { if (minWeights <= 0) { WarningIn ( "metisDecomp::decompose" "(const pointField&, const scalarField&)" ) << "Illegal minimum weight " << minWeights << endl; } if (cWeights.size() != numCells) { FatalErrorIn ( "metisDecomp::decompose" "(const pointField&, const scalarField&)" ) << "Number of cell weights " << cWeights.size() << " does not equal number of cells " << numCells << exit(FatalError); } // Convert to integers. cellWeights.setSize(cWeights.size()); forAll(cellWeights, i) { cellWeights[i] = int(cWeights[i]/minWeights); } } // Check for user supplied weights and decomp options if (decompositionDict_.found("metisCoeffs")) { const dictionary& metisCoeffs = decompositionDict_.subDict("metisCoeffs"); word weightsFile; if (metisCoeffs.readIfPresent("method", method)) { if (method != "recursive" && method != "k-way") { FatalErrorIn("metisDecomp::decompose()") << "Method " << method << " in metisCoeffs in dictionary : " << decompositionDict_.name() << " should be 'recursive' or 'k-way'" << exit(FatalError); } Info<< "metisDecomp : Using Metis method " << method << nl << endl; } if (metisCoeffs.readIfPresent("options", options)) { if (options.size() != 5) { FatalErrorIn("metisDecomp::decompose()") << "Number of options in metisCoeffs in dictionary : " << decompositionDict_.name() << " should be 5" << exit(FatalError); } Info<< "metisDecomp : Using Metis options " << options << nl << endl; } if (metisCoeffs.readIfPresent("processorWeights", processorWeights)) { processorWeights /= sum(processorWeights); if (processorWeights.size() != nProcessors_) { FatalErrorIn("metisDecomp::decompose(const pointField&)") << "Number of processor weights " << processorWeights.size() << " does not equal number of domains " << nProcessors_ << exit(FatalError); } } //if (metisCoeffs.readIfPresent("cellWeightsFile", weightsFile)) //{ // Info<< "metisDecomp : Using cell-based weights." << endl; // // IOList<int> cellIOWeights // ( // IOobject // ( // weightsFile, // mesh_.time().timeName(), // mesh_, // IOobject::MUST_READ, // IOobject::AUTO_WRITE // ) // ); // cellWeights.transfer(cellIOWeights); // // if (cellWeights.size() != xadj.size()-1) // { // FatalErrorIn("metisDecomp::decompose(const pointField&)") // << "Number of cell weights " << cellWeights.size() // << " does not equal number of cells " << xadj.size()-1 // << exit(FatalError); // } //} } int nProcs = nProcessors_; // output: cell -> processor addressing finalDecomp.setSize(numCells); // output: number of cut edges int edgeCut = 0; // Vertex weight info int wgtFlag = 0; int* vwgtPtr = NULL; int* adjwgtPtr = NULL; if (cellWeights.size()) { vwgtPtr = cellWeights.begin(); wgtFlag += 2; // Weights on vertices } if (faceWeights.size()) { adjwgtPtr = faceWeights.begin(); wgtFlag += 1; // Weights on edges } if (method == "recursive") { if (processorWeights.size()) { METIS_WPartGraphRecursive ( &numCells, // num vertices in graph const_cast<List<int>&>(xadj).begin(), // indexing into adjncy const_cast<List<int>&>(adjncy).begin(), // neighbour info vwgtPtr, // vertexweights adjwgtPtr, // no edgeweights &wgtFlag, &numFlag, &nProcs, processorWeights.begin(), options.begin(), &edgeCut, finalDecomp.begin() ); } else { METIS_PartGraphRecursive ( &numCells, // num vertices in graph const_cast<List<int>&>(xadj).begin(), // indexing into adjncy const_cast<List<int>&>(adjncy).begin(), // neighbour info vwgtPtr, // vertexweights adjwgtPtr, // no edgeweights &wgtFlag, &numFlag, &nProcs, options.begin(), &edgeCut, finalDecomp.begin() ); } } else { if (processorWeights.size()) { METIS_WPartGraphKway ( &numCells, // num vertices in graph const_cast<List<int>&>(xadj).begin(), // indexing into adjncy const_cast<List<int>&>(adjncy).begin(), // neighbour info vwgtPtr, // vertexweights adjwgtPtr, // no edgeweights &wgtFlag, &numFlag, &nProcs, processorWeights.begin(), options.begin(), &edgeCut, finalDecomp.begin() ); } else { METIS_PartGraphKway ( &numCells, // num vertices in graph const_cast<List<int>&>(xadj).begin(), // indexing into adjncy const_cast<List<int>&>(adjncy).begin(), // neighbour info vwgtPtr, // vertexweights adjwgtPtr, // no edgeweights &wgtFlag, &numFlag, &nProcs, options.begin(), &edgeCut, finalDecomp.begin() ); } } return edgeCut; }
JNIEXPORT jint JNICALL Java_jprime_JMetis_wPartitionGraph( JNIEnv * env, jobject obj, jboolean j_force_PartGraphRecursive, jboolean j_force_PartGraphKway, jint j_num_vertices, jintArray j_xadj, jintArray j_adjncy, jintArray j_vwgt, jintArray j_adjwgt, jint j_wgtflag, jint j_nparts, jfloatArray j_part_weights, jintArray j_options, jintArray j_partioned_nodes){ mysrand(7654321L); //delcare vars jint * xadj=NULL, * adjncy=NULL,* vwgt=NULL, * adjwgt=NULL, * options=NULL, * partioned_nodes=NULL; jfloat* part_weights=NULL; int idx, edges_cut=-1, num_vertices=0, nparts=0, wgtflag=0, numflag=0; jsize xadj_len, adjncy_len, vwgt_len, adjwgt_len, options_len, partioned_nodes_len, part_weights_len; //copy the jsize vars num_vertices=j_num_vertices; nparts=j_nparts; wgtflag=j_wgtflag; //get array lengths xadj_len = (*env)->GetArrayLength(env,j_xadj); adjncy_len = (*env)->GetArrayLength(env,j_adjncy); vwgt_len = (*env)->GetArrayLength(env,j_vwgt); adjwgt_len = (*env)->GetArrayLength(env,j_adjwgt); options_len = (*env)->GetArrayLength(env,j_options); partioned_nodes_len = (*env)->GetArrayLength(env,j_partioned_nodes); part_weights_len = (*env)->GetArrayLength(env,j_part_weights); //create/get local copies xadj = (*env)->GetIntArrayElements(env,j_xadj,0); adjncy = (*env)->GetIntArrayElements(env,j_adjncy,0); part_weights = (*env)->GetFloatArrayElements(env,j_part_weights,0); if(vwgt_len>0) vwgt = (*env)->GetIntArrayElements(env,j_vwgt,0); if(adjwgt_len>0) adjwgt = (*env)->GetIntArrayElements(env,j_adjwgt,0); if(options_len>0) options = (*env)->GetIntArrayElements(env,j_options,0); partioned_nodes = (int*)malloc(sizeof(int)*partioned_nodes_len); //call func if((j_nparts<8 || j_force_PartGraphRecursive) && !j_force_PartGraphKway) { METIS_WPartGraphRecursive( &num_vertices, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &nparts, part_weights, options, &edges_cut, partioned_nodes); } else { METIS_WPartGraphKway( &num_vertices, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &nparts, part_weights, options, &edges_cut, partioned_nodes); } //pop partioned_nodes (*env)->SetIntArrayRegion(env,j_partioned_nodes,0,partioned_nodes_len,partioned_nodes); //free local copies free(partioned_nodes); (*env)->ReleaseIntArrayElements(env, j_xadj, xadj, 0); (*env)->ReleaseIntArrayElements(env, j_adjncy, adjncy, 0); if(vwgt_len>0) (*env)->ReleaseIntArrayElements(env, j_vwgt, vwgt, 0); if(adjwgt_len>0) (*env)->ReleaseIntArrayElements(env, j_adjwgt, adjwgt, 0); if(options_len>0) (*env)->ReleaseIntArrayElements(env, j_options, options, 0); return edges_cut; }