source: branches/numpy/pymetis/metis-4.0/Lib/mesh.c @ 6971

Last change on this file since 6971 was 3085, checked in by ole, 19 years ago

Moved pyvolution.mesh.py to pyvolution.test_mesh.py in order to avoid confusion with pmesh.

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