00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #ifndef __FEM_PARALLEL_PART_H__
00010 #define __FEM_PARALLEL_PART_H__
00011 
00012 
00013 
00014 #ifdef PARALLEL_DEBUG
00015 #define DEBUG(x) x
00016 #else
00017 #define DEBUG(x)
00018 #endif
00019 
00020 #define MESH_CHUNK_TAG 3000
00021 
00022 template <class T, bool PUP_EVERY_ELEMENT=true >
00023 class DefaultListEntry {
00024 public:
00025     inline void accumulate(T& a, const T& b) { a += b; }
00026     
00027     inline T getIdentity() { return T(); }
00028     inline bool pupEveryElement(){ return PUP_EVERY_ELEMENT; }
00029 };
00030 
00031 template <class T>
00032 class ElemList{
00033 public:
00034     CkVec<T> *vec;
00035     ElemList(){
00036         vec = new CkVec<T>();
00037     }
00038     ~ElemList(){
00039         delete vec;
00040     }
00041     ElemList(const ElemList &rhs){
00042         *this=rhs;
00043     }
00044     ElemList& operator=(const ElemList& rhs){
00045          vec = new CkVec<T>();
00046         *vec = *(rhs.vec);
00047     }
00048     ElemList& operator+=(const ElemList& rhs){
00049         
00050 
00051 
00052         int len = vec->size();
00053         for(int i=0;i<rhs.vec->length();i++){
00054             int flag=0;
00055             for(int j=0;j<len;j++){
00056                 if((*vec)[j] == (*(rhs.vec))[i]){                   
00057                     flag = 1;
00058                     break;
00059                 }
00060             }
00061             if(!flag){
00062                 vec->push_back((*(rhs.vec))[i]);
00063             }   
00064         }
00065     }
00066     ElemList(const T &val){
00067         vec =new CkVec<T>();
00068         vec->push_back(val);
00069     };
00070     virtual void pup(PUP::er &p){
00071         if(p.isUnpacking()){
00072             vec = new CkVec<T>();
00073         }
00074         pupCkVec(p,*vec);
00075     }
00076 };
00077 
00078 class NodeElem {
00079 public:
00080     
00081     int global;
00082     
00083 
00084 
00085 
00086     int numShared;
00087     
00088 
00089 
00090 
00091     int *shared;
00092     NodeElem(){
00093         global = -1;
00094         numShared = 0;
00095         shared = NULL;
00096     }
00097     NodeElem(int g_,int num_){
00098         global = g_; numShared= num_;
00099         if(numShared != 0){
00100             shared = new int[numShared];
00101         }else{
00102             shared = NULL;
00103         }
00104     }
00105     NodeElem(int g_){
00106         global = g_;
00107         numShared = 0;
00108         shared = NULL;
00109     }
00110     NodeElem(const NodeElem &rhs){
00111         shared=NULL;
00112         *this = rhs;
00113     }
00114     NodeElem& operator=(const NodeElem &rhs){
00115         global = rhs.global;
00116         numShared = rhs.numShared;
00117         if(shared != NULL){
00118             delete [] shared;
00119         }
00120         shared = new int[numShared];
00121         memcpy(shared,rhs.shared,numShared*sizeof(int));
00122     }
00123 
00124     bool operator == (const NodeElem &rhs){
00125         if(global == rhs.global){
00126             return true;
00127         }else{
00128             return false;
00129         }
00130     }
00131     virtual void pup(PUP::er &p){
00132         p | global;
00133         p | numShared;
00134         if(p.isUnpacking()){
00135             if(numShared != 0){
00136                 shared = new int[numShared];
00137             }else{
00138                 shared = NULL;
00139             }
00140         }
00141         p(shared,numShared);
00142     }
00143     ~NodeElem(){
00144         if(shared != NULL){
00145             delete [] shared;
00146         }
00147     }
00148 };
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 class MeshElem{
00158     public: 
00159     FEM_Mesh *m;
00160     CkVec<int> gedgechunk; 
00161     MeshElem(){
00162         m = new FEM_Mesh;
00163     }
00164     MeshElem(int dummy){
00165         m = new FEM_Mesh;
00166     }
00167     ~MeshElem(){
00168         delete m;
00169     }
00170     MeshElem(const MeshElem &rhs){
00171         m = NULL;
00172         *this = rhs;
00173     }
00174     MeshElem& operator=(const MeshElem &rhs){
00175         if(m != NULL){
00176             delete m;
00177         }   
00178         m = new FEM_Mesh;
00179         m->copyShape(*(rhs.m));
00180         (*this)+= rhs;
00181     }
00182     MeshElem& operator+=(const MeshElem &rhs){
00183         int oldel = m->nElems();
00184         m->copyShape(*(rhs.m));
00185         for(int i=0;i<rhs.m->node.size();i++){
00186             m->node.push_back((rhs.m)->node,i);
00187         }   
00188         if((rhs.m)->elem.size()>0){
00189             for(int t=0;t<(rhs.m)->elem.size();t++){
00190                 if((rhs.m)->elem.has(t)){
00191                     for(int e=0;e<(rhs.m)->elem.get(t).size();e++){
00192                         m->elem[t].push_back((rhs.m)->elem.get(t),e);
00193                     }   
00194                 }   
00195             }
00196         }   
00197     }
00198     virtual void pup(PUP::er &p){
00199         if(p.isUnpacking()){
00200             m = new FEM_Mesh;
00201         }
00202         m->pup(p);
00203     }
00204 };
00205 
00206 
00207 class Hashnode{
00208 public:
00209     class tupledata{
00210         public:
00211         enum {MAX_TUPLE = 8};
00212             int nodes[MAX_TUPLE];
00213             tupledata(int _nodes[MAX_TUPLE]){
00214                 memcpy(nodes,_nodes,sizeof(int)*MAX_TUPLE);
00215             }
00216             tupledata(tupledata &rhs){
00217                 memcpy(nodes,rhs.nodes,sizeof(int)*MAX_TUPLE);
00218             }
00219             tupledata(){};
00220             
00221             char *toString(int numnodes,char *str){
00222                 str[0]='\0';
00223                 for(int i=0;i<numnodes;i++){
00224                     sprintf(&str[strlen(str)],"%d ",nodes[i]);
00225                 }
00226                 return str;
00227             }
00228             int &operator[](int i){
00229                 return nodes[i];
00230             }
00231             const int &operator[](int i) const {
00232                 return nodes[i];
00233             }
00234             virtual void pup(PUP::er &p){
00235                 p(nodes,MAX_TUPLE);
00236             }
00237     };
00238     int numnodes; 
00239     
00240     tupledata nodes;    
00241     int chunk;      
00242     int elementNo;      
00243     Hashnode(){
00244         numnodes=0;
00245     };
00246     Hashnode(int _num,int _chunk,int _elNo,int _nodes[tupledata::MAX_TUPLE]): nodes(_nodes){
00247         numnodes = _num;
00248         chunk = _chunk;
00249         elementNo = _elNo;
00250     }
00251     Hashnode(const Hashnode &rhs){
00252         *this = rhs;
00253     }
00254     Hashnode &operator=(const Hashnode &rhs){
00255         numnodes = rhs.numnodes;
00256         for(int i=0;i<numnodes;i++){
00257             nodes[i] = rhs.nodes[i];
00258         }
00259         chunk = rhs.chunk;
00260         elementNo = rhs.elementNo;
00261     }
00262     bool operator==(const Hashnode &rhs){
00263         if(numnodes != rhs.numnodes){
00264             return false;
00265         }
00266         for(int i=0;i<numnodes;i++){
00267             if(nodes[i] != rhs.nodes[i]){
00268                 return false;
00269             }
00270         }
00271         if(chunk != rhs.chunk){
00272             return false;
00273         }
00274         if(elementNo != rhs.elementNo){
00275             return false;
00276         }
00277         return true;
00278     }
00279     bool equals(tupledata &tuple){
00280         for(int i=0;i<numnodes;i++){
00281             if(tuple.nodes[i] != nodes[i]){
00282                 return false;
00283             }
00284         }
00285         return true;
00286     }
00287     virtual void pup(PUP::er &p){
00288         p | numnodes;
00289         p | nodes;
00290         p | chunk;
00291         p | elementNo;
00292     }
00293 };
00294 
00295 template <class T>
00296 ostream& operator << (ostream& os, const ElemList<T> & s){
00297 };
00298 
00299 template <class T>
00300 CkOutStream& operator << (CkOutStream& os, const ElemList<T>& s) {
00301 };
00302 
00303 typedef MSA2D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
00304 
00305 typedef MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINT;
00306 
00307 typedef ElemList<int> IntList;
00308 typedef MSA1D<IntList, DefaultListEntry<IntList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINTLIST;
00309 
00310 typedef ElemList<NodeElem> NodeList;
00311 typedef MSA1D<NodeList, DefaultListEntry<NodeList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DNODELIST;
00312 
00313 typedef MSA1D<MeshElem,DefaultEntry<MeshElem,true>,1> MSA1DFEMMESH;
00314 
00315 typedef ElemList<Hashnode> Hashtuple;
00316 typedef MSA1D<Hashtuple,DefaultListEntry<Hashtuple,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DHASH;
00317 
00318 
00319 
00320 struct conndata{
00321     int nelem;
00322     int nnode;
00323     MSA1DINT arr1;
00324     MSA1DINT arr2;
00325 
00326     void pup(PUP::er &p){
00327         p|nelem;
00328         p|nnode;
00329         arr1.pup(p);
00330         arr2.pup(p);
00331     }
00332 };
00333 
00334 
00335 
00336 
00337 
00338 struct partconndata{
00339     int nelem;
00340     int startindex;
00341     int *eptr,*eind;
00342     int *part;
00343     ~partconndata(){
00344         delete [] eptr;
00345         delete [] eind;
00346         delete [] part;
00347     };
00348 };
00349 
00350 
00351 
00352 
00353 struct ghostdata{
00354     int numLayers;
00355     FEM_Ghost_Layer **layers;
00356     void pup(PUP::er &p){
00357         p | numLayers;
00358         if(p.isUnpacking()){
00359             layers = new FEM_Ghost_Layer *[numLayers];
00360             for(int i=0;i<numLayers;i++){
00361                 layers[i] = new FEM_Ghost_Layer;
00362             }
00363 
00364         }
00365         for(int i=0;i<numLayers;i++){
00366             layers[i]->pup(p);
00367         }
00368     }
00369     ~ghostdata(){
00370             printf("destructor on ghostdata called \n");
00371             for(int i=0;i<numLayers;i++){
00372                     delete layers[i];
00373             }
00374             delete [] layers;
00375     };
00376 };
00377 
00378 
00379 class MsaHashtable{
00380 public:
00381     int numSlots;
00382     MSA1DHASH table;
00383     MsaHashtable(int _numSlots,int numWorkers):numSlots(_numSlots),table(_numSlots,numWorkers){
00384     }
00385     MsaHashtable(){};
00386 
00387     virtual void pup(PUP::er &p){
00388         p | numSlots;
00389         p | table;
00390     }
00391     int addTuple(int *tuple,int nodesPerTuple,int chunk,int elementNo){
00392         
00393         
00394         
00395         for(int i=0;i<nodesPerTuple-1;i++){
00396             for(int j=i+1;j<nodesPerTuple;j++){
00397                 if(tuple[j] < tuple[i]){
00398                     int t = tuple[j];
00399                     tuple[j] = tuple[i];
00400                     tuple[i] = t;
00401                 }
00402             }
00403         }
00404         
00405         long long sum = 0;
00406         for(int i=0;i<nodesPerTuple;i++){
00407             sum = sum *numSlots + tuple[i];
00408         }
00409         int index = (int )(sum %(long )numSlots);
00410         Hashnode entry(nodesPerTuple,chunk,elementNo,tuple);
00411     
00412         Hashtuple &list=table.accumulate(index);
00413         list.vec->push_back(entry);
00414         char str[100];
00415         DEBUG(printf("[%d] adding tuple %s element %d to index %d \n",chunk,entry.nodes.toString(nodesPerTuple,str),elementNo,index));
00416         return index;
00417     }
00418 
00419     void print(){
00420         char str[100];
00421         for(int i=0;i<numSlots;i++){
00422             const Hashtuple &t = table.get(i);
00423             for(int j=0;j<t.vec->size();j++){
00424                 Hashnode &tuple = (*t.vec)[j];
00425                 printf("ghost element chunk %d element %d index %d tuple < %s>\n",tuple.chunk,tuple.elementNo,i,tuple.nodes.toString(tuple.numnodes,str));
00426             }
00427         }
00428     }
00429     void sync(){
00430         table.sync();
00431     }
00432     const Hashtuple &get(int i){
00433         return table.get(i);
00434     }
00435     
00436 };
00437 
00438 
00439 
00440 int FEM_master_parallel_part(int ,int ,FEM_Comm_t);
00441 int FEM_slave_parallel_part(int ,int ,FEM_Comm_t);
00442 struct partconndata* FEM_call_parmetis(struct conndata &data,FEM_Comm_t comm_context);
00443 void FEM_write_nodepart(MSA1DINTLIST    &nodepart,struct partconndata *data);
00444 void FEM_write_part2node(MSA1DINTLIST   &nodepart,MSA1DNODELIST &part2node,struct partconndata *data,MPI_Comm comm_context);
00445 void FEM_write_part2elem(MSA1DINTLIST &part2elem,struct partconndata *data,MPI_Comm comm_context);
00446 FEM_Mesh * FEM_break_mesh(FEM_Mesh *m,int numElements,int numChunks);
00447 void sendBrokenMeshes(FEM_Mesh *mesh_array,FEM_Comm_t comm_context);
00448 void    FEM_write_part2mesh(MSA1DFEMMESH &part2mesh,struct partconndata *partdata,struct conndata *data,MSA1DINTLIST &nodepart,int numChunks,int myChunk,FEM_Mesh *mypiece);
00449 void addIDXLists(FEM_Mesh *m,NodeList &lnodes,int myChunk);
00450 struct ghostdata *gatherGhosts();
00451 void makeGhosts(FEM_Mesh *m,MPI_Comm comm,int masterRank,int numLayers,FEM_Ghost_Layer **layers);
00452 void makeGhost(FEM_Mesh *m,MPI_Comm comm,int masterRank,int totalShared,FEM_Ghost_Layer *layer, CkHashtableT<CkHashtableAdaptorT<int>,char> &sharedNode,CkHashtableT<CkHashtableAdaptorT<int>,int> &global2local);
00453 bool sharedWith(int lnode,int chunk,FEM_Mesh *m);
00454 
00455 #endif