source: branches/numpy/pymetis/metis-4.0/Lib/meshpart.c @ 6982

Last change on this file since 6982 was 3414, checked in by jack, 19 years ago

Added pymetis to the scons scripts

File size: 5.8 KB
Line 
1/*
2 * Copyright 1997, Regents of the University of Minnesota
3 *
4 * meshpart.c
5 *
6 * This file contains routines for partitioning finite element meshes.
7 *
8 * Started 9/29/97
9 * George
10 *
11 * $Id: meshpart.c,v 1.1 1998/11/27 17:59:21 karypis Exp $
12 *
13 */
14
15#include <metis.h>
16
17
18/*************************************************************************
19* This function partitions a finite element mesh by partitioning its nodal
20* graph using KMETIS and then assigning elements in a load balanced fashion.
21**************************************************************************/
22void METIS_PartMeshNodal(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
23                         int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
24{
25  int i, j, k, me;
26  idxtype *xadj, *adjncy, *pwgts;
27  int options[10], pnumflag=0, wgtflag=0;
28  int nnbrs, nbrind[200], nbrwgt[200], maxpwgt;
29  int esize, esizes[] = {-1, 3, 4, 8, 4};
30
31  esize = esizes[*etype];
32
33  if (*numflag == 1)
34    ChangeMesh2CNumbering((*ne)*esize, elmnts);
35
36  xadj = idxmalloc(*nn+1, "METIS_MESHPARTNODAL: xadj");
37  adjncy = idxmalloc(20*(*nn), "METIS_MESHPARTNODAL: adjncy");
38
39  METIS_MeshToNodal(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
40   
41  adjncy = realloc(adjncy, xadj[*nn]*sizeof(idxtype));
42
43  options[0] = 0;
44  METIS_PartGraphKway(nn, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, npart);
45
46  /* OK, now compute an element partition based on the nodal partition npart */
47  idxset(*ne, -1, epart);
48  pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTNODAL: pwgts");
49  for (i=0; i<*ne; i++) {
50    me = npart[elmnts[i*esize]];
51    for (j=1; j<esize; j++) {
52      if (npart[elmnts[i*esize+j]] != me)
53        break;
54    }
55    if (j == esize) {
56      epart[i] = me;
57      pwgts[me]++;
58    }
59  }
60
61  maxpwgt = 1.03*(*ne)/(*nparts);
62  for (i=0; i<*ne; i++) {
63    if (epart[i] == -1) { /* Assign the boundary element */
64      nnbrs = 0;
65      for (j=0; j<esize; j++) {
66        me = npart[elmnts[i*esize+j]];
67        for (k=0; k<nnbrs; k++) {
68          if (nbrind[k] == me) {
69            nbrwgt[k]++;
70            break;
71          }
72        }
73        if (k == nnbrs) {
74          nbrind[nnbrs] = me;
75          nbrwgt[nnbrs++] = 1;
76        }
77      }
78      /* Try to assign it first to the domain with most things in common */
79      j = iamax(nnbrs, nbrwgt);
80      if (pwgts[nbrind[j]] < maxpwgt) {
81        epart[i] = nbrind[j];
82      }
83      else {
84        /* If that fails, assign it to a light domain */
85        for (j=0; j<nnbrs; j++) {
86          if (pwgts[nbrind[j]] < maxpwgt) {
87            epart[i] = nbrind[j];
88            break;
89          }
90        }
91        if (j == nnbrs) 
92          epart[i] = nbrind[iamax(nnbrs, nbrwgt)];
93      }
94      pwgts[epart[i]]++;
95    }
96  }
97
98  if (*numflag == 1)
99    ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
100
101  GKfree(&xadj, &adjncy, &pwgts, LTERM);
102}
103
104
105/*************************************************************************
106* This function partitions a finite element mesh by partitioning its dual
107* graph using KMETIS and then assigning nodes in a load balanced fashion.
108**************************************************************************/
109void METIS_PartMeshDual(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
110                        int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
111{
112  int i, j, k, me;
113  idxtype *xadj, *adjncy, *pwgts, *nptr, *nind;
114  int options[10], pnumflag=0, wgtflag=0;
115  int nnbrs, nbrind[200], nbrwgt[200], maxpwgt;
116  int esize, esizes[] = {-1, 3, 4, 8, 4};
117
118  esize = esizes[*etype];
119
120  if (*numflag == 1)
121    ChangeMesh2CNumbering((*ne)*esize, elmnts);
122
123  xadj = idxmalloc(*ne+1, "METIS_MESHPARTNODAL: xadj");
124  adjncy = idxmalloc(esize*(*ne), "METIS_MESHPARTNODAL: adjncy");
125
126  METIS_MeshToDual(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
127
128  options[0] = 0;
129  METIS_PartGraphKway(ne, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, epart);
130
131  /* Construct the node-element list */
132  nptr = idxsmalloc(*nn+1, 0, "METIS_MESHPARTDUAL: nptr");
133  for (j=esize*(*ne), i=0; i<j; i++) 
134    nptr[elmnts[i]]++;
135  MAKECSR(i, *nn, nptr);
136
137  nind = idxmalloc(nptr[*nn], "METIS_MESHPARTDUAL: nind");
138  for (k=i=0; i<(*ne); i++) {
139    for (j=0; j<esize; j++, k++) 
140      nind[nptr[elmnts[k]]++] = i;
141  }
142  for (i=(*nn); i>0; i--)
143    nptr[i] = nptr[i-1];
144  nptr[0] = 0;
145
146
147  /* OK, now compute a nodal partition based on the element partition npart */
148  idxset(*nn, -1, npart);
149  pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTDUAL: pwgts");
150  for (i=0; i<*nn; i++) {
151    me = epart[nind[nptr[i]]];
152    for (j=nptr[i]+1; j<nptr[i+1]; j++) {
153      if (epart[nind[j]] != me)
154        break;
155    }
156    if (j == nptr[i+1]) {
157      npart[i] = me;
158      pwgts[me]++;
159    }
160  }
161
162  maxpwgt = 1.03*(*nn)/(*nparts);
163  for (i=0; i<*nn; i++) {
164    if (npart[i] == -1) { /* Assign the boundary element */
165      nnbrs = 0;
166      for (j=nptr[i]; j<nptr[i+1]; j++) {
167        me = epart[nind[j]];
168        for (k=0; k<nnbrs; k++) {
169          if (nbrind[k] == me) {
170            nbrwgt[k]++;
171            break;
172          }
173        }
174        if (k == nnbrs) {
175          nbrind[nnbrs] = me;
176          nbrwgt[nnbrs++] = 1;
177        }
178      }
179      /* Try to assign it first to the domain with most things in common */
180      j = iamax(nnbrs, nbrwgt);
181      if (pwgts[nbrind[j]] < maxpwgt) {
182        npart[i] = nbrind[j];
183      }
184      else {
185        /* If that fails, assign it to a light domain */
186        npart[i] = nbrind[0];
187        for (j=0; j<nnbrs; j++) {
188          if (pwgts[nbrind[j]] < maxpwgt) {
189            npart[i] = nbrind[j];
190            break;
191          }
192        }
193      }
194      pwgts[npart[i]]++;
195    }
196  }
197
198  if (*numflag == 1)
199    ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
200
201  GKfree(&xadj, &adjncy, &pwgts, &nptr, &nind, LTERM);
202
203}
Note: See TracBrowser for help on using the repository browser.