aboutsummaryrefslogtreecommitdiff
path: root/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-07-15 18:09:46 -0800
committerTor Aamodt <[email protected]>2010-07-15 18:09:46 -0800
commit69f2911e04ffb1b19eef1fafb8c040af271f656e (patch)
tree231d3b6bdc3a202f7c255bfcf7bf2c36e32cee9e /benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c
creating branch for adding support for CUDA 3.x and Fermi
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829]
Diffstat (limited to 'benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c')
-rw-r--r--benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c
new file mode 100644
index 0000000..4ca3a2a
--- /dev/null
+++ b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/meshpart.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright 1997, Regents of the University of Minnesota
+ *
+ * meshpart.c
+ *
+ * This file contains routines for partitioning finite element meshes.
+ *
+ * Started 9/29/97
+ * George
+ *
+ * $Id: meshpart.c,v 1.1 2003/07/16 15:55:08 karypis Exp $
+ *
+ */
+
+#include <metis.h>
+
+
+/*************************************************************************
+* This function partitions a finite element mesh by partitioning its nodal
+* graph using KMETIS and then assigning elements in a load balanced fashion.
+**************************************************************************/
+void METIS_PartMeshNodal(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag,
+ int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
+{
+ int i, j, k, me;
+ idxtype *xadj, *adjncy, *pwgts;
+ int options[10], pnumflag=0, wgtflag=0;
+ 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(*nn+1, "METIS_MESHPARTNODAL: xadj");
+ adjncy = idxmalloc(20*(*nn), "METIS_MESHPARTNODAL: adjncy");
+
+ METIS_MeshToNodal(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
+
+ adjncy = realloc(adjncy, xadj[*nn]*sizeof(idxtype));
+
+ options[0] = 0;
+ METIS_PartGraphKway(nn, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, npart);
+
+ /* OK, now compute an element partition based on the nodal partition npart */
+ idxset(*ne, -1, epart);
+ pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTNODAL: pwgts");
+ for (i=0; i<*ne; i++) {
+ me = npart[elmnts[i*esize]];
+ for (j=1; j<esize; j++) {
+ if (npart[elmnts[i*esize+j]] != me)
+ break;
+ }
+ if (j == esize) {
+ epart[i] = me;
+ pwgts[me]++;
+ }
+ }
+
+ maxpwgt = 1.03*(*ne)/(*nparts);
+ for (i=0; i<*ne; i++) {
+ if (epart[i] == -1) { /* Assign the boundary element */
+ nnbrs = 0;
+ for (j=0; j<esize; j++) {
+ me = npart[elmnts[i*esize+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) {
+ epart[i] = nbrind[j];
+ }
+ else {
+ /* If that fails, assign it to a light domain */
+ for (j=0; j<nnbrs; j++) {
+ if (pwgts[nbrind[j]] < maxpwgt) {
+ epart[i] = nbrind[j];
+ break;
+ }
+ }
+ if (j == nnbrs)
+ epart[i] = nbrind[iamax(nnbrs, nbrwgt)];
+ }
+ pwgts[epart[i]]++;
+ }
+ }
+
+ if (*numflag == 1)
+ ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
+
+ GKfree(&xadj, &adjncy, &pwgts, LTERM);
+
+}
+
+
+/*************************************************************************
+* This function partitions a finite element mesh by partitioning its dual
+* graph using KMETIS and then assigning nodes in a load balanced fashion.
+**************************************************************************/
+void METIS_PartMeshDual(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag,
+ int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
+{
+ int i, j, k, me;
+ idxtype *xadj, *adjncy, *pwgts, *nptr, *nind;
+ int options[10], pnumflag=0, wgtflag=0;
+ 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, NULL, 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);
+
+}