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