/************************************************************************* * Let the game begin **************************************************************************/ main(int argc, char *argv[]) { int i, j, ne, nn, etype, numflag=0; idxtype *elmnts, *xadj, *adjncy; timer IOTmr, DUALTmr; char fileout[256], etypestr[4][5] = {"TRI", "TET", "HEX", "QUAD"}; if (argc != 2) { printf("Usage: %s <meshfile>\n",argv[0]); exit(0); } cleartimer(IOTmr); cleartimer(DUALTmr); starttimer(IOTmr); elmnts = ReadMesh(argv[1], &ne, &nn, &etype); stoptimer(IOTmr); printf("**********************************************************************\n"); printf("%s", METISTITLE); printf("Mesh Information ----------------------------------------------------\n"); printf(" Name: %s, #Elements: %d, #Nodes: %d, Etype: %s\n\n", argv[1], ne, nn, etypestr[etype-1]); printf("Forming Dual Graph... -----------------------------------------------\n"); xadj = idxmalloc(ne+1, "main: xadj"); adjncy = idxmalloc(10*ne, "main: adjncy"); starttimer(DUALTmr); METIS_MeshToDual(&ne, &nn, elmnts, &etype, &numflag, xadj, adjncy); stoptimer(DUALTmr); printf(" Dual Information: #Vertices: %d, #Edges: %d\n", ne, xadj[ne]/2); sprintf(fileout, "%s.dgraph", argv[1]); starttimer(IOTmr); WriteGraph(fileout, ne, xadj, adjncy); stoptimer(IOTmr); printf("\nTiming Information --------------------------------------------------\n"); printf(" I/O: \t\t %7.3f\n", gettimer(IOTmr)); printf(" Dual Creation:\t\t %7.3f\n", gettimer(DUALTmr)); printf("**********************************************************************\n"); GKfree(&elmnts, &xadj, &adjncy, LTERM); }
/**************************************************************************** * mexFunction: gateway routine for MATLAB interface. *****************************************************************************/ void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Argument checking if (nrhs != 5) mexErrMsgIdAndTxt(FUNC_NAME, "Wrong input."); if (nlhs != 2) mexErrMsgIdAndTxt(FUNC_NAME, "Wrong output."); // Input and output variables idx_t ne = (idx_t) mxGetScalar(ne_in); idx_t nn = (idx_t) mxGetScalar(nn_in); idx_t *eptr; GetIdxArray(eptr_in,&eptr); idx_t *eind; GetIdxArray(eind_in,&eind); idx_t ncommon = (idx_t) mxGetScalar(ncommon_in); idx_t numflag = 0; idx_t *xadj = NULL; idx_t *adjncy = NULL; // Metis main function int info = METIS_MeshToDual( &ne, &nn, eptr, eind, &ncommon, &numflag, &xadj, &adjncy); CheckReturn(info, FUNC_NAME); // Output xadj_out = mxCreateDoubleMatrix(1,ne+1,mxREAL); mxSetData(xadj_out,mxMalloc(sizeof(double)*(ne+1))); double *xadj_out_pr = mxGetPr(xadj_out); for(idx_t i=0; i<ne+1; i++) xadj_out_pr[i] = (double) xadj[i]; idx_t n = (idx_t) xadj[ne+1]; adjncy_out = mxCreateDoubleMatrix(1,n,mxREAL); mxSetData(adjncy_out,mxMalloc(sizeof(double)*n)); double *adjncy_out_pr = mxGetPr(adjncy_out); for(idx_t i=0; i<n; i++) adjncy_out_pr[i] = (double) adjncy[i]; }
/************************************************************************* * 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 metis_meshtodual__(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, idxtype *dxadj, idxtype *dadjncy) { METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy); }
void METIS_MESHTODUAL(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, idxtype *dxadj, idxtype *dadjncy) { METIS_MeshToDual(ne, nn, elmnts, etype, numflag, dxadj, dadjncy); }
void METIS_PartMeshDual_WV(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, int *nparts, int *edgecut, idxtype *epart, idxtype *npart, idxtype *vwgts) { int i, j, k, me; idxtype *xadj, *adjncy, *pwgts, *nptr, *nind; int options[10], pnumflag=0, wgtflag=2; int nnbrs, nbrind[200], nbrwgt[200], maxpwgt; int esize, esizes[] = {-1, 3, 4, 8, 4}; esize = esizes[*etype]; if (*numflag == 1) ChangeMesh2CNumbering((*ne)*esize, elmnts); xadj = idxmalloc(*ne+1, "METIS_MESHPARTNODAL: xadj"); adjncy = idxmalloc(esize*(*ne), "METIS_MESHPARTNODAL: adjncy"); METIS_MeshToDual(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy); options[0] = 0; METIS_PartGraphKway(ne, xadj, adjncy, vwgts, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, epart); /* Construct the node-element list */ nptr = idxsmalloc(*nn+1, 0, "METIS_MESHPARTDUAL: nptr"); for (j=esize*(*ne), i=0; i<j; i++) nptr[elmnts[i]]++; MAKECSR(i, *nn, nptr); nind = idxmalloc(nptr[*nn], "METIS_MESHPARTDUAL: nind"); for (k=i=0; i<(*ne); i++) { for (j=0; j<esize; j++, k++) nind[nptr[elmnts[k]]++] = i; } for (i=(*nn); i>0; i--) nptr[i] = nptr[i-1]; nptr[0] = 0; /* OK, now compute a nodal partition based on the element partition npart */ idxset(*nn, -1, npart); pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTDUAL: pwgts"); for (i=0; i<*nn; i++) { me = epart[nind[nptr[i]]]; for (j=nptr[i]+1; j<nptr[i+1]; j++) { if (epart[nind[j]] != me) break; } if (j == nptr[i+1]) { npart[i] = me; pwgts[me]++; } } maxpwgt = 1.03*(*nn)/(*nparts); for (i=0; i<*nn; i++) { if (npart[i] == -1) { /* Assign the boundary element */ nnbrs = 0; for (j=nptr[i]; j<nptr[i+1]; j++) { me = epart[nind[j]]; for (k=0; k<nnbrs; k++) { if (nbrind[k] == me) { nbrwgt[k]++; break; } } if (k == nnbrs) { nbrind[nnbrs] = me; nbrwgt[nnbrs++] = 1; } } /* Try to assign it first to the domain with most things in common */ j = iamax(nnbrs, nbrwgt); if (pwgts[nbrind[j]] < maxpwgt) { npart[i] = nbrind[j]; } else { /* If that fails, assign it to a light domain */ npart[i] = nbrind[0]; for (j=0; j<nnbrs; j++) { if (pwgts[nbrind[j]] < maxpwgt) { npart[i] = nbrind[j]; break; } } } pwgts[npart[i]]++; } } if (*numflag == 1) ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart); GKfree(&xadj, &adjncy, &pwgts, &nptr, &nind, LTERM); }