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