[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 | **************************************************************************/ |
---|
| 22 | void 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 | **************************************************************************/ |
---|
| 120 | void 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 | } |
---|