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 }