source: inundation/pymetis/metis-4.0/Lib/meshpart.c @ 3381

Last change on this file since 3381 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: 6.1 KB
RevLine 
[2051]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
[3085]33  printf("Inside METIS_PartMeshNodal\n");
34 
[2051]35  if (*numflag == 1)
36    ChangeMesh2CNumbering((*ne)*esize, elmnts);
37
38  xadj = idxmalloc(*nn+1, "METIS_MESHPARTNODAL: xadj");
39  adjncy = idxmalloc(20*(*nn), "METIS_MESHPARTNODAL: adjncy");
40
[3085]41  printf("Calling METIS_MeshToNodal\n");
[2051]42  METIS_MeshToNodal(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
[3085]43  printf("After METIS_MeshToNodal\n");
44   
[2051]45  adjncy = realloc(adjncy, xadj[*nn]*sizeof(idxtype));
46
47  options[0] = 0;
[3085]48  printf("Calling METIS_PartGraphKway\n"); 
[2051]49  METIS_PartGraphKway(nn, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, npart);
50
51  /* OK, now compute an element partition based on the nodal partition npart */
[3085]52  printf("Starting loop 1\n"); 
[2051]53  idxset(*ne, -1, epart);
54  pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTNODAL: pwgts");
55  for (i=0; i<*ne; i++) {
56    me = npart[elmnts[i*esize]];
57    for (j=1; j<esize; j++) {
58      if (npart[elmnts[i*esize+j]] != me)
59        break;
60    }
61    if (j == esize) {
62      epart[i] = me;
63      pwgts[me]++;
64    }
65  }
66
[3085]67  printf("Starting loop 2\n");   
[2051]68  maxpwgt = 1.03*(*ne)/(*nparts);
69  for (i=0; i<*ne; i++) {
70    if (epart[i] == -1) { /* Assign the boundary element */
71      nnbrs = 0;
72      for (j=0; j<esize; j++) {
73        me = npart[elmnts[i*esize+j]];
74        for (k=0; k<nnbrs; k++) {
75          if (nbrind[k] == me) {
76            nbrwgt[k]++;
77            break;
78          }
79        }
80        if (k == nnbrs) {
81          nbrind[nnbrs] = me;
82          nbrwgt[nnbrs++] = 1;
83        }
84      }
85      /* Try to assign it first to the domain with most things in common */
86      j = iamax(nnbrs, nbrwgt);
87      if (pwgts[nbrind[j]] < maxpwgt) {
88        epart[i] = nbrind[j];
89      }
90      else {
91        /* If that fails, assign it to a light domain */
92        for (j=0; j<nnbrs; j++) {
93          if (pwgts[nbrind[j]] < maxpwgt) {
94            epart[i] = nbrind[j];
95            break;
96          }
97        }
98        if (j == nnbrs) 
99          epart[i] = nbrind[iamax(nnbrs, nbrwgt)];
100      }
101      pwgts[epart[i]]++;
102    }
103  }
104
[3085]105  printf("ChangeMesh2FNumbering2\n");   
[2051]106  if (*numflag == 1)
107    ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
108
[3085]109  printf("Free\n");       
[2051]110  GKfree(&xadj, &adjncy, &pwgts, LTERM);
[3085]111  printf("Done\n");     
[2051]112
113}
114
115
116/*************************************************************************
117* This function partitions a finite element mesh by partitioning its dual
118* graph using KMETIS and then assigning nodes in a load balanced fashion.
119**************************************************************************/
120void METIS_PartMeshDual(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
121                        int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
122{
123  int i, j, k, me;
124  idxtype *xadj, *adjncy, *pwgts, *nptr, *nind;
125  int options[10], pnumflag=0, wgtflag=0;
126  int nnbrs, nbrind[200], nbrwgt[200], maxpwgt;
127  int esize, esizes[] = {-1, 3, 4, 8, 4};
128
129  esize = esizes[*etype];
130
131  if (*numflag == 1)
132    ChangeMesh2CNumbering((*ne)*esize, elmnts);
133
134  xadj = idxmalloc(*ne+1, "METIS_MESHPARTNODAL: xadj");
135  adjncy = idxmalloc(esize*(*ne), "METIS_MESHPARTNODAL: adjncy");
136
137  METIS_MeshToDual(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
138
139  options[0] = 0;
140  METIS_PartGraphKway(ne, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, epart);
141
142  /* Construct the node-element list */
143  nptr = idxsmalloc(*nn+1, 0, "METIS_MESHPARTDUAL: nptr");
144  for (j=esize*(*ne), i=0; i<j; i++) 
145    nptr[elmnts[i]]++;
146  MAKECSR(i, *nn, nptr);
147
148  nind = idxmalloc(nptr[*nn], "METIS_MESHPARTDUAL: nind");
149  for (k=i=0; i<(*ne); i++) {
150    for (j=0; j<esize; j++, k++) 
151      nind[nptr[elmnts[k]]++] = i;
152  }
153  for (i=(*nn); i>0; i--)
154    nptr[i] = nptr[i-1];
155  nptr[0] = 0;
156
157
158  /* OK, now compute a nodal partition based on the element partition npart */
159  idxset(*nn, -1, npart);
160  pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTDUAL: pwgts");
161  for (i=0; i<*nn; i++) {
162    me = epart[nind[nptr[i]]];
163    for (j=nptr[i]+1; j<nptr[i+1]; j++) {
164      if (epart[nind[j]] != me)
165        break;
166    }
167    if (j == nptr[i+1]) {
168      npart[i] = me;
169      pwgts[me]++;
170    }
171  }
172
173  maxpwgt = 1.03*(*nn)/(*nparts);
174  for (i=0; i<*nn; i++) {
175    if (npart[i] == -1) { /* Assign the boundary element */
176      nnbrs = 0;
177      for (j=nptr[i]; j<nptr[i+1]; j++) {
178        me = epart[nind[j]];
179        for (k=0; k<nnbrs; k++) {
180          if (nbrind[k] == me) {
181            nbrwgt[k]++;
182            break;
183          }
184        }
185        if (k == nnbrs) {
186          nbrind[nnbrs] = me;
187          nbrwgt[nnbrs++] = 1;
188        }
189      }
190      /* Try to assign it first to the domain with most things in common */
191      j = iamax(nnbrs, nbrwgt);
192      if (pwgts[nbrind[j]] < maxpwgt) {
193        npart[i] = nbrind[j];
194      }
195      else {
196        /* If that fails, assign it to a light domain */
197        npart[i] = nbrind[0];
198        for (j=0; j<nnbrs; j++) {
199          if (pwgts[nbrind[j]] < maxpwgt) {
200            npart[i] = nbrind[j];
201            break;
202          }
203        }
204      }
205      pwgts[npart[i]]++;
206    }
207  }
208
209  if (*numflag == 1)
210    ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
211
212  GKfree(&xadj, &adjncy, &pwgts, &nptr, &nind, LTERM);
213
214}
Note: See TracBrowser for help on using the repository browser.