00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <assert.h>
00015 #include <metis.h>
00016 #include "fem_impl.h"
00017 #include "cktimer.h"
00018
00019 class NList
00020 {
00021 int nn;
00022 int sn;
00023 int *elts;
00024 static int cmp(const void *v1, const void *v2);
00025 public:
00026 NList(void) { sn = 0; nn = 0; elts = 0; }
00027 void init(int _sn) { sn = _sn; nn = 0; elts = new int[sn]; }
00028 void add(int elt);
00029 int found(int elt);
00030 void sort(void) { qsort(elts, nn, sizeof(int), cmp); };
00031 int getnn(void) { return nn; }
00032 int getelt(int n) { assert(n < nn); return elts[n]; }
00033 ~NList() { delete [] elts; }
00034 };
00035
00036 class Nodes
00037 {
00038 int nnodes;
00039 NList *elts;
00040 public:
00041 Nodes(int _nnodes);
00042 ~Nodes() { delete [] elts; }
00043 void add(int node, int elem);
00044 int nelems(int node)
00045 {
00046 assert(node < nnodes);
00047 return elts[node].getnn();
00048 }
00049 int getelt(int node, int n)
00050 {
00051 assert(node < nnodes);
00052 return elts[node].getelt(n);
00053 }
00054 };
00055
00056 class Graph
00057 {
00058 int nelems;
00059 NList *nbrs;
00060 public:
00061 Graph(int elems);
00062 ~Graph() { delete [] nbrs; }
00063 void add(int elem1, int elem2);
00064 int elems(int elem)
00065 {
00066 assert(elem<nelems);
00067 return nbrs[elem].getnn();
00068 }
00069 void toAdjList(int *&adjStart,int *&adjList);
00070 };
00071
00072 int NList::cmp(const void *v1, const void *v2)
00073 {
00074 int *e1 = (int *) v1;
00075 int *e2 = (int *) v2;
00076 if(*e1==*e2) return 0;
00077 else if(*e1 < *e2) return -1;
00078 else return 1;
00079 }
00080
00081 void NList::add(int elt)
00082 {
00083
00084
00085
00086
00087 if (sn <= nn) {
00088 sn *= 2;
00089 int *telts = new int[sn];
00090 for (int i=0; i<nn; i++)
00091 telts[i] = elts[i];
00092 delete[] elts;
00093 elts = telts;
00094 }
00095
00096
00097 elts[nn++] = elt;
00098 }
00099
00100 int NList::found(int elt)
00101 {
00102 for(int i = 0; i < nn; i++)
00103 {
00104 if(elts[i] == elt)
00105 return 1;
00106 }
00107 return 0;
00108 }
00109
00110 Nodes::Nodes(int _nnodes)
00111 {
00112 nnodes = _nnodes;
00113 elts = new NList[nnodes];
00114
00115 for(int i=0; i<nnodes; i++) {
00116 elts[i].init(10);
00117 }
00118 }
00119
00120 void Nodes::add(int node, int elem)
00121 {
00122 assert(node < nnodes);
00123 elts[node].add(elem);
00124 }
00125
00126 Graph::Graph(int _nelems)
00127 {
00128 nelems = _nelems;
00129 nbrs = new NList[nelems];
00130
00131 for(int i=0; i<nelems; i++)
00132 {
00133 nbrs[i].init(10);
00134 }
00135 }
00136
00137 void Graph::add(int elem1, int elem2)
00138 {
00139 assert(elem1 < nelems);
00140 assert(elem2 < nelems);
00141
00142
00143
00144 if(!nbrs[elem1].found(elem2))
00145 {
00146 nbrs[elem1].add(elem2);
00147 nbrs[elem2].add(elem1);
00148 }
00149 }
00150
00151
00152 void Graph::toAdjList(int *&adjStart,int *&adjList)
00153 {
00154 int e,i;
00155 adjStart=new int[nelems+1];
00156 adjStart[0]=0;
00157 for (e=0;e<nelems;e++)
00158 adjStart[e+1]=adjStart[e]+elems(e);
00159 adjList=new int[adjStart[nelems]];
00160 int *adjOut=adjList;
00161 for (e=0;e<nelems;e++)
00162 for (i=nbrs[e].getnn()-1;i>=0;i--)
00163 *(adjOut++)=nbrs[e].getelt(i);
00164 }
00165
00166
00167 void mesh2graph(const FEM_Mesh *m, Graph *g)
00168 {
00169 Nodes nl(m->node.size());
00170
00171
00172 int globalCount=0,t,e,n;
00173 for(t=0;t<m->elem.size();t++)
00174 if (m->elem.has(t)) {
00175 const FEM_Elem &k=m->elem[t];
00176 for(e=0;e<k.size();e++,globalCount++)
00177 for(n=0;n<k.getNodesPer();n++)
00178 nl.add(k.getConn(e,n),globalCount);
00179 }
00180
00181
00182
00183
00184 int i, j;
00185 for(i = 0; i < m->node.size(); i++) {
00186 int nn = nl.nelems(i);
00187 for(j = 0; j < nn; j++) {
00188 int e1 = nl.getelt(i, j);
00189 for(int k = j + 1; k < nn; k++) {
00190 int e2 = nl.getelt(i, k);
00191 g->add(e1, e2);
00192 }
00193 }
00194 }
00195 }
00196
00197
00198
00199
00200
00201 void FEM_Mesh_partition(const FEM_Mesh *mesh,int nchunks,int *elem2chunk)
00202 {
00203 CkThresholdTimer time("FEM Split> Building graph for metis partitioner",1.0);
00204 int nelems=mesh->nElems();
00205 if (nchunks==1) {
00206 for (int i=0;i<nelems;i++) elem2chunk[i]=0;
00207 return;
00208 }
00209 Graph g(nelems);
00210 mesh2graph(mesh,&g);
00211
00212 int *adjStart;
00213 int *adjList;
00214 g.toAdjList(adjStart,adjList);
00215 int ecut,ncon=1;
00216 time.start("FEM Split> Calling metis partitioner");
00217 if (nchunks<8)
00218 METIS_PartGraphRecursive(&nelems, &ncon, adjStart, adjList, NULL, NULL, NULL,
00219 &nchunks, NULL, NULL, NULL, &ecut, elem2chunk);
00220 else
00221 METIS_PartGraphKway(&nelems, &ncon, adjStart, adjList, NULL, NULL, NULL,
00222 &nchunks, NULL, NULL, NULL, &ecut, elem2chunk);
00223 delete[] adjStart;
00224 delete[] adjList;
00225 }