source: inundation/pymetis/metis-4.0/Lib/mesh.c @ 2891

Last change on this file since 2891 was 2051, checked in by jack, 19 years ago

Python interface to metis. Currently provides only the
METIS_PartMeshNodal function, since that is what is currently needed for partitioning.
Module name is metis.

File size: 10.4 KB
Line 
1/*
2 * Copyright 1997, Regents of the University of Minnesota
3 *
4 * mesh.c
5 *
6 * This file contains routines for converting 3D and 4D finite element
7 * meshes into dual or nodal graphs
8 *
9 * Started 8/18/97
10 * George
11 *
12 * $Id: mesh.c,v 1.1 1998/11/27 17:59:20 karypis Exp $
13 *
14 */
15
16#include <metis.h>
17
18/*****************************************************************************
19* This function creates a graph corresponding to the dual of a finite element
20* mesh. At this point the supported elements are triangles, tetrahedrons, and
21* bricks.
22******************************************************************************/
23void METIS_MeshToDual(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
24                      idxtype *dxadj, idxtype *dadjncy)
25{
26  int esizes[] = {-1, 3, 4, 8, 4};
27
28  if (*numflag == 1)
29    ChangeMesh2CNumbering((*ne)*esizes[*etype], elmnts);
30
31  GENDUALMETIS(*ne, *nn, *etype, elmnts, dxadj, dadjncy);
32
33  if (*numflag == 1)
34    ChangeMesh2FNumbering((*ne)*esizes[*etype], elmnts, *ne, dxadj, dadjncy);
35}
36
37
38/*****************************************************************************
39* This function creates a graph corresponding to the finite element mesh.
40* At this point the supported elements are triangles, tetrahedrons.
41******************************************************************************/
42void METIS_MeshToNodal(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
43                       idxtype *dxadj, idxtype *dadjncy)
44{
45  int esizes[] = {-1, 3, 4, 8, 4};
46
47  if (*numflag == 1)
48    ChangeMesh2CNumbering((*ne)*esizes[*etype], elmnts);
49
50  switch (*etype) {
51    case 1:
52      TRINODALMETIS(*ne, *nn, elmnts, dxadj, dadjncy);
53      break;
54    case 2:
55      TETNODALMETIS(*ne, *nn, elmnts, dxadj, dadjncy);
56      break;
57    case 3:
58      HEXNODALMETIS(*ne, *nn, elmnts, dxadj, dadjncy);
59      break;
60    case 4:
61      QUADNODALMETIS(*ne, *nn, elmnts, dxadj, dadjncy);
62      break;
63  }
64
65  if (*numflag == 1)
66    ChangeMesh2FNumbering((*ne)*esizes[*etype], elmnts, *nn, dxadj, dadjncy);
67}
68
69
70
71/*****************************************************************************
72* This function creates the dual of a finite element mesh
73******************************************************************************/
74void GENDUALMETIS(int nelmnts, int nvtxs, int etype, idxtype *elmnts, idxtype *dxadj, idxtype *dadjncy)
75{
76   int i, j, jj, k, kk, kkk, l, m, n, nedges, mask;
77   idxtype *nptr, *nind;
78   idxtype *mark, ind[200], wgt[200];
79   int esize, esizes[] = {-1, 3, 4, 8, 4},
80       mgcnum, mgcnums[] = {-1, 2, 3, 4, 2};
81
82   mask = (1<<11)-1;
83   mark = idxsmalloc(mask+1, -1, "GENDUALMETIS: mark");
84
85   /* Get the element size and magic number for the particular element */
86   esize = esizes[etype];
87   mgcnum = mgcnums[etype];
88
89   /* Construct the node-element list first */
90   nptr = idxsmalloc(nvtxs+1, 0, "GENDUALMETIS: nptr");
91   for (j=esize*nelmnts, i=0; i<j; i++) 
92     nptr[elmnts[i]]++;
93   MAKECSR(i, nvtxs, nptr);
94
95   nind = idxmalloc(nptr[nvtxs], "GENDUALMETIS: nind");
96   for (k=i=0; i<nelmnts; i++) {
97     for (j=0; j<esize; j++, k++) 
98       nind[nptr[elmnts[k]]++] = i;
99   }
100   for (i=nvtxs; i>0; i--)
101     nptr[i] = nptr[i-1];
102   nptr[0] = 0;
103
104   for (i=0; i<nelmnts; i++) 
105     dxadj[i] = esize*i;
106
107   for (i=0; i<nelmnts; i++) {
108     for (m=j=0; j<esize; j++) {
109       n = elmnts[esize*i+j];
110       for (k=nptr[n+1]-1; k>=nptr[n]; k--) {
111         if ((kk = nind[k]) <= i)
112           break;
113
114         kkk = kk&mask;
115         if ((l = mark[kkk]) == -1) {
116           ind[m] = kk;
117           wgt[m] = 1;
118           mark[kkk] = m++;
119         }
120         else if (ind[l] == kk) {
121           wgt[l]++;
122         }
123         else {
124           for (jj=0; jj<m; jj++) {
125             if (ind[jj] == kk) {
126               wgt[jj]++;
127               break;
128             }
129           }
130           if (jj == m) {
131             ind[m] = kk;
132             wgt[m++] = 1;
133           }
134         }
135       }
136     }
137     for (j=0; j<m; j++) {
138       if (wgt[j] == mgcnum) {
139         k = ind[j];
140         dadjncy[dxadj[i]++] = k;
141         dadjncy[dxadj[k]++] = i;
142       }
143       mark[ind[j]&mask] = -1;
144     }
145   }
146
147   /* Go and consolidate the dxadj and dadjncy */
148   for (j=i=0; i<nelmnts; i++) {
149     for (k=esize*i; k<dxadj[i]; k++, j++)
150       dadjncy[j] = dadjncy[k];
151     dxadj[i] = j;
152   }
153   for (i=nelmnts; i>0; i--)
154     dxadj[i] = dxadj[i-1];
155   dxadj[0] = 0;
156
157   free(mark);
158   free(nptr);
159   free(nind);
160
161}
162
163
164
165
166/*****************************************************************************
167* This function creates the nodal graph of a finite element mesh
168******************************************************************************/
169void TRINODALMETIS(int nelmnts, int nvtxs, idxtype *elmnts, idxtype *dxadj, idxtype *dadjncy)
170{
171   int i, j, jj, k, kk, kkk, l, m, n, nedges;
172   idxtype *nptr, *nind;
173   idxtype *mark;
174
175   /* Construct the node-element list first */
176   nptr = idxsmalloc(nvtxs+1, 0, "TRINODALMETIS: nptr");
177   for (j=3*nelmnts, i=0; i<j; i++) 
178     nptr[elmnts[i]]++;
179   MAKECSR(i, nvtxs, nptr);
180
181   nind = idxmalloc(nptr[nvtxs], "TRINODALMETIS: nind");
182   for (k=i=0; i<nelmnts; i++) {
183     for (j=0; j<3; j++, k++) 
184       nind[nptr[elmnts[k]]++] = i;
185   }
186   for (i=nvtxs; i>0; i--)
187     nptr[i] = nptr[i-1];
188   nptr[0] = 0;
189
190
191   mark = idxsmalloc(nvtxs, -1, "TRINODALMETIS: mark");
192
193   nedges = dxadj[0] = 0;
194   for (i=0; i<nvtxs; i++) {
195     mark[i] = i;
196     for (j=nptr[i]; j<nptr[i+1]; j++) {
197       for (jj=3*nind[j], k=0; k<3; k++, jj++) {
198         kk = elmnts[jj];
199         if (mark[kk] != i) {
200           mark[kk] = i;
201           dadjncy[nedges++] = kk;
202         }
203       }
204     }
205     dxadj[i+1] = nedges;
206   }
207
208   free(mark);
209   free(nptr);
210   free(nind);
211
212}
213
214
215/*****************************************************************************
216* This function creates the nodal graph of a finite element mesh
217******************************************************************************/
218void TETNODALMETIS(int nelmnts, int nvtxs, idxtype *elmnts, idxtype *dxadj, idxtype *dadjncy)
219{
220   int i, j, jj, k, kk, kkk, l, m, n, nedges;
221   idxtype *nptr, *nind;
222   idxtype *mark;
223
224   /* Construct the node-element list first */
225   nptr = idxsmalloc(nvtxs+1, 0, "TETNODALMETIS: nptr");
226   for (j=4*nelmnts, i=0; i<j; i++) 
227     nptr[elmnts[i]]++;
228   MAKECSR(i, nvtxs, nptr);
229
230   nind = idxmalloc(nptr[nvtxs], "TETNODALMETIS: nind");
231   for (k=i=0; i<nelmnts; i++) {
232     for (j=0; j<4; j++, k++) 
233       nind[nptr[elmnts[k]]++] = i;
234   }
235   for (i=nvtxs; i>0; i--)
236     nptr[i] = nptr[i-1];
237   nptr[0] = 0;
238
239
240   mark = idxsmalloc(nvtxs, -1, "TETNODALMETIS: mark");
241
242   nedges = dxadj[0] = 0;
243   for (i=0; i<nvtxs; i++) {
244     mark[i] = i;
245     for (j=nptr[i]; j<nptr[i+1]; j++) {
246       for (jj=4*nind[j], k=0; k<4; k++, jj++) {
247         kk = elmnts[jj];
248         if (mark[kk] != i) {
249           mark[kk] = i;
250           dadjncy[nedges++] = kk;
251         }
252       }
253     }
254     dxadj[i+1] = nedges;
255   }
256
257   free(mark);
258   free(nptr);
259   free(nind);
260
261}
262
263
264/*****************************************************************************
265* This function creates the nodal graph of a finite element mesh
266******************************************************************************/
267void HEXNODALMETIS(int nelmnts, int nvtxs, idxtype *elmnts, idxtype *dxadj, idxtype *dadjncy)
268{
269   int i, j, jj, k, kk, kkk, l, m, n, nedges;
270   idxtype *nptr, *nind;
271   idxtype *mark;
272   int table[8][3] = {1, 3, 4,
273                      0, 2, 5,
274                      1, 3, 6,
275                      0, 2, 7,
276                      0, 5, 7,
277                      1, 4, 6,
278                      2, 5, 7,
279                      3, 4, 6};
280
281   /* Construct the node-element list first */
282   nptr = idxsmalloc(nvtxs+1, 0, "HEXNODALMETIS: nptr");
283   for (j=8*nelmnts, i=0; i<j; i++) 
284     nptr[elmnts[i]]++;
285   MAKECSR(i, nvtxs, nptr);
286
287   nind = idxmalloc(nptr[nvtxs], "HEXNODALMETIS: nind");
288   for (k=i=0; i<nelmnts; i++) {
289     for (j=0; j<8; j++, k++) 
290       nind[nptr[elmnts[k]]++] = i;
291   }
292   for (i=nvtxs; i>0; i--)
293     nptr[i] = nptr[i-1];
294   nptr[0] = 0;
295
296
297   mark = idxsmalloc(nvtxs, -1, "HEXNODALMETIS: mark");
298
299   nedges = dxadj[0] = 0;
300   for (i=0; i<nvtxs; i++) {
301     mark[i] = i;
302     for (j=nptr[i]; j<nptr[i+1]; j++) {
303       jj=8*nind[j];
304       for (k=0; k<8; k++) {
305         if (elmnts[jj+k] == i)
306           break;
307       }
308       ASSERT(k != 8);
309
310       /* You found the index, now go and put the 3 neighbors */
311       kk = elmnts[jj+table[k][0]];
312       if (mark[kk] != i) {
313         mark[kk] = i;
314         dadjncy[nedges++] = kk;
315       }
316       kk = elmnts[jj+table[k][1]];
317       if (mark[kk] != i) {
318         mark[kk] = i;
319         dadjncy[nedges++] = kk;
320       }
321       kk = elmnts[jj+table[k][2]];
322       if (mark[kk] != i) {
323         mark[kk] = i;
324         dadjncy[nedges++] = kk;
325       }
326     }
327     dxadj[i+1] = nedges;
328   }
329
330   free(mark);
331   free(nptr);
332   free(nind);
333
334}
335
336
337/*****************************************************************************
338* This function creates the nodal graph of a finite element mesh
339******************************************************************************/
340void QUADNODALMETIS(int nelmnts, int nvtxs, idxtype *elmnts, idxtype *dxadj, idxtype *dadjncy)
341{
342   int i, j, jj, k, kk, kkk, l, m, n, nedges;
343   idxtype *nptr, *nind;
344   idxtype *mark;
345   int table[4][2] = {1, 3, 
346                      0, 2,
347                      1, 3, 
348                      0, 2}; 
349
350   /* Construct the node-element list first */
351   nptr = idxsmalloc(nvtxs+1, 0, "QUADNODALMETIS: nptr");
352   for (j=4*nelmnts, i=0; i<j; i++) 
353     nptr[elmnts[i]]++;
354   MAKECSR(i, nvtxs, nptr);
355
356   nind = idxmalloc(nptr[nvtxs], "QUADNODALMETIS: nind");
357   for (k=i=0; i<nelmnts; i++) {
358     for (j=0; j<4; j++, k++) 
359       nind[nptr[elmnts[k]]++] = i;
360   }
361   for (i=nvtxs; i>0; i--)
362     nptr[i] = nptr[i-1];
363   nptr[0] = 0;
364
365
366   mark = idxsmalloc(nvtxs, -1, "QUADNODALMETIS: mark");
367
368   nedges = dxadj[0] = 0;
369   for (i=0; i<nvtxs; i++) {
370     mark[i] = i;
371     for (j=nptr[i]; j<nptr[i+1]; j++) {
372       jj=4*nind[j];
373       for (k=0; k<4; k++) {
374         if (elmnts[jj+k] == i)
375           break;
376       }
377       ASSERT(k != 4);
378
379       /* You found the index, now go and put the 2 neighbors */
380       kk = elmnts[jj+table[k][0]];
381       if (mark[kk] != i) {
382         mark[kk] = i;
383         dadjncy[nedges++] = kk;
384       }
385       kk = elmnts[jj+table[k][1]];
386       if (mark[kk] != i) {
387         mark[kk] = i;
388         dadjncy[nedges++] = kk;
389       }
390     }
391     dxadj[i+1] = nedges;
392   }
393
394   free(mark);
395   free(nptr);
396   free(nind);
397
398}
Note: See TracBrowser for help on using the repository browser.