00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __CHARM_FEM_IMPL_H
00011 #define __CHARM_FEM_IMPL_H
00012 
00013 #include <stdio.h>
00014 
00015 #include "charm-api.h"
00016 #include "ckvector3d.h"
00017 #include "pup_mpi.h"
00018 #define checkMPI pup_checkMPI
00019 #include "tcharm.h"
00020 #include "fem.h"
00021 #include "map.h"
00022 
00023 #include "fem_mesh.h"
00024 #include "idxl_layout.h"
00025 #include "idxl.h"
00026 
00028 
00029 
00030 
00031 
00032 
00033 #define FEM_MAX_ELTYPE 20
00034 
00035 
00036 void FEM_Abort(const char *msg);
00037 void FEM_Abort(const char *caller,const char *sprintf_msg,int int0=0,int int1=0,int int2=0);
00038 
00039 
00040 
00041 
00042 class l2g_t {
00043 public:
00044     
00045     virtual int el(int t,int localNo) const {return localNo;}
00046     
00047     virtual int no(int localNo) const {return localNo;}
00048 };
00049 
00050 
00051 template <class T>
00052 class NumberedVec {
00053     CkPupPtrVec<T, CkPupAlwaysAllocatePtr<T> > vec;
00054     
00055 public:
00056     
00057     void makeLonger(int toHaveElement)
00058     {
00059         int oldSize=vec.size(), newSize=toHaveElement+1;
00060         if (oldSize>=newSize) return; 
00061         vec.resize(newSize);
00062         for (int j=oldSize;j<newSize;j++)
00063             vec[j]=new T;
00064     }
00065     
00066     void reinit(int doomedEl) {
00067         vec[doomedEl].destroy();
00068         vec[doomedEl]=new T;
00069     }
00070     
00071     int size(void) const {return vec.size();}
00072     
00073     
00074     T &operator[](int i) {
00075         if (i>=vec.size()) makeLonger(i);
00076         return *( vec[i] );
00077     }
00078     const T &operator[](int i) const {return *( vec[i] );}
00079     
00080     void pup(PUP::er &p) {
00081         vec.pup(p);
00082     }
00083     friend void operator|(PUP::er &p,NumberedVec<T> &v) {v.pup(p);}
00084 };
00085 
00086 
00087 
00088 template <class T>
00089 class ArrayPtrT : public CkNoncopyable {
00090     T *sto;
00091 public:
00092     ArrayPtrT() {sto=NULL;}
00093     ArrayPtrT(int *src) {sto=src;}
00094     ~ArrayPtrT() {if (sto) delete[] sto;}
00095     void operator=(T *src) {
00096         if (sto) delete[] sto;
00097         sto=src;
00098     }
00099     operator T *(void) {return sto;}
00100     operator const T *(void) const {return sto;}
00101     T& operator[](int i) {return sto[i];}
00102     const T& operator[](int i) const {return sto[i];}
00103 };
00104 typedef ArrayPtrT<int> intArrayPtr;
00105 
00106 
00107 
00108 
00109 template<class T>
00110 class marshallNewHeapCopy {
00111     T *cur;
00112 public:
00113     
00114     marshallNewHeapCopy(T *readFrom) :cur(readFrom) {}
00115     marshallNewHeapCopy(const marshallNewHeapCopy &h) :cur(h.cur) {}
00116     marshallNewHeapCopy(void) { 
00117         cur=new T;
00118     }
00119     
00120     void pup(PUP::er &p) {
00121         cur->pup(p);
00122     }
00123     operator T *() {return cur;}
00124     friend void operator|(PUP::er &p,marshallNewHeapCopy<T> &h) {h.pup(p);}
00125 };
00126 typedef marshallNewHeapCopy<FEM_Mesh> marshallMeshChunk;
00127 
00128 
00131 template<class T>
00132 class FEM_T_List {
00133     CkPupPtrVec<T> list; 
00134 protected:
00135     int FIRST_DT; 
00136     int size(void) const {return list.size();}
00137     
00139     inline void check(int l,const char *caller) const {
00140         if (l<FIRST_DT || l>=FIRST_DT+list.size() || list[l-FIRST_DT]==NULL) 
00141             badIndex(l,caller);
00142     }
00143     
00144     void badIndex(int l,const char *caller) const {
00145         if (l<FIRST_DT || l>FIRST_DT+list.size()) bad(l,0,caller);
00146         else bad(l,1,caller);
00147     }
00148 public:
00149     FEM_T_List(int FIRST_DT_) :FIRST_DT(FIRST_DT_) {}
00150     virtual ~FEM_T_List() {}
00151     void pup(PUP::er &p) { p|list; }
00152     
00154     virtual void bad(int l,int bad_code,const char *caller) const =0;
00155     
00157     int put(T *t) {
00158         for (int i=0;i<list.size();i++) 
00159             if (list[i]==NULL) {
00160                 list[i]=t;
00161                 return FIRST_DT+i;
00162             }
00163         int ret=list.size();
00164         list.push_back(t);
00165         return FIRST_DT+ret;
00166     }
00167     
00169     inline T *lookup(int l,const char *caller) const {
00170         check(l,caller);
00171         return list[l-FIRST_DT];
00172     }
00173     
00175     void destroy(int l,const char *caller) {
00176         check(l,caller);
00177         list[l-FIRST_DT].destroy();
00178     }
00179     
00181     void empty(void) {
00182         for (int i=0;i<list.size();i++) list[i].destroy();
00183     }
00184 };
00185 class FEM_Mesh_list : public FEM_T_List<FEM_Mesh> {
00186     typedef FEM_T_List<FEM_Mesh> super;
00187 public:
00188     FEM_Mesh_list() :super(FEM_MESH_FIRST) { }
00189     
00190     virtual void bad(int l,int bad_code,const char *caller) const;
00191 };
00192 
00193 #define CHK(p) do{if((p)==0)CkAbort("FEM>Memory Allocation failure.");}while(0)
00194 
00205 class FEMchunk 
00206 {
00207 public:
00208   FEM_Mesh_list meshes; 
00209   int default_read; 
00210   int default_write; 
00211   
00213   FEM_Comm_t defaultComm;
00214 
00216   int thisIndex;
00217 
00218 #if CMK_ERROR_CHECKING 
00219   void check(const char *where);
00220 #else  
00221   inline void check(const char *where) { }
00222 #endif
00223 
00224 private:
00225   CkVec<int> listTmp;
00226  
00227   void initFields(void);
00228 
00229  public:
00230   FEMchunk(FEM_Comm_t defaultComm_);
00231   FEMchunk(CkMigrateMessage *msg);
00232   void pup(PUP::er &p);
00233   ~FEMchunk();
00234   
00236   static FEMchunk *get(const char *caller);
00237   
00238   inline FEM_Mesh *lookup(int fem_mesh,const char *caller) {
00239      return meshes.lookup(fem_mesh,caller);
00240   }
00241 
00242   inline FEM_Mesh *getMesh(const char *caller) 
00243     {return meshes.lookup(default_read,caller);}
00244   inline FEM_Mesh *setMesh(const char *caller) 
00245     {return meshes.lookup(default_write,caller);}
00246 
00247   void print(int fem_mesh,int idxBase);
00248   int getPrimary(int nodeNo) { return getMesh("getPrimary")->node.getPrimary(nodeNo); }
00249   const FEM_Comm &getComm(void) {return getMesh("getComm")->node.shared;}
00250 
00251   
00252   void exchangeGhostLists(int elemType,int inLen,const int *inList,int idxbase);
00253   void recvList(int elemType,int fmChk,int nIdx,const int *idx);
00254   const CkVec<int> &getList(void) {return listTmp;}
00255   void emptyList(void) {listTmp.length()=0;}
00256   
00257   void reduce_field(int idxl_datatype, const void *nodes, void *outbuf, int op);
00258   void reduce(int idxl_datatype, const void *inbuf, void *outbuf, int op);
00259   void readField(int idxl_datatype, void *nodes, const char *fname);  
00260 };
00261 
00263 class FEM_Ghost_Layer : public CkNoncopyable {
00264 public:
00265     int nodesPerTuple; 
00266     bool addNodes; 
00267     class elemGhostInfo {
00268     public:
00269         bool add; 
00270         int tuplesPerElem; 
00271         intArrayPtr elem2tuple; 
00272         elemGhostInfo(void) {add=false;tuplesPerElem=0;}
00273         ~elemGhostInfo(void) {}
00274         void pup(PUP::er &p) {
00275         }
00276     };
00277     elemGhostInfo elem[FEM_MAX_ELTYPE];
00278     virtual void pup(PUP::er &p){
00279         p | nodesPerTuple;
00280         p | addNodes;
00281         for(int i=0;i<FEM_MAX_ELTYPE;i++){
00282             p | elem[i].add;
00283             p | elem[i].tuplesPerElem;
00284             if(elem[i].tuplesPerElem == 0){
00285                 continue;
00286             }
00287             int *arr;
00288             if(p.isUnpacking()){
00289                 arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
00290             }else{
00291                 arr = elem[i].elem2tuple;
00292             }
00293             p(arr,nodesPerTuple*elem[i].tuplesPerElem);
00294             if(p.isUnpacking()){
00295                 elem[i].elem2tuple = arr;
00296             }
00297         }
00298     }
00299 };
00300 
00303 class FEM_Ghost_Stencil {
00305     int elType;
00307     int n;
00309     bool addNodes;
00310     
00313     intArrayPtr ends;
00314     
00323     intArrayPtr adj;
00324 public:
00329     FEM_Ghost_Stencil(int elType_, int n_,bool addNodes_,
00330         const int *ends_,
00331         const int *adj_,
00332         int idxBase);
00333     
00335     void check(const FEM_Mesh &mesh) const;
00336     
00338     inline int getType(void) const {return elType;}
00339     
00346     inline const int *getNeighbor(int i,int j) const {
00347         int start=0;
00348         if (i>0) start=ends[i-1];
00349         if (j>=ends[i]-start) return 0;
00350         return &adj[2*(start+j)];
00351     }
00352     
00353     inline bool wantNodes(void) const {return addNodes;}
00354 };
00355 
00357 class FEM_Ghost_Region {
00358 public: 
00359     FEM_Ghost_Layer *layer;
00360     FEM_Ghost_Stencil *stencil;
00361     
00362     FEM_Ghost_Region() {layer=0; stencil=0;}
00363     FEM_Ghost_Region(FEM_Ghost_Layer *l) {layer=l; stencil=0;}
00364     FEM_Ghost_Region(FEM_Ghost_Stencil *s) {layer=0; stencil=s;}
00365 };
00366 
00367 
00368 
00369 class FEM_Initial_Symmetries; 
00370 
00372 class FEM_Partition : public CkNoncopyable {
00374     int *elem2chunk;
00375     
00377     CkVec<FEM_Ghost_Region> regions;
00378     FEM_Ghost_Layer *lastLayer;
00379     
00381     FEM_Initial_Symmetries *sym;
00382 public:
00383     FEM_Partition();
00384     ~FEM_Partition();
00385     
00386 
00387     void setPartition(const int *elem2chunk, int nElem, int idxBase);
00388     const int *getPartition(FEM_Mesh *src,int nChunks) const;
00389     
00390 
00391     FEM_Ghost_Layer *addLayer(void) {
00392         lastLayer=new FEM_Ghost_Layer();
00393         regions.push_back(lastLayer);
00394         return lastLayer;
00395     }
00396     FEM_Ghost_Layer *curLayer(void) {
00397         if (lastLayer==0) CkAbort("Must call FEM_Add_ghost_layer before FEM_Add_ghost_elem\n");
00398         return lastLayer;
00399     }
00400     
00401 
00402     void addGhostStencil(FEM_Ghost_Stencil *s) {
00403         regions.push_back(s);
00404         lastLayer=0;
00405     }
00406     void markGhostStencilLayer(void) {
00407         regions.push_back(FEM_Ghost_Region());
00408     }
00409     
00410 
00411     int getRegions(void) const {return regions.size();}
00412     const FEM_Ghost_Region &getRegion(int regNo) const {return regions[regNo];}
00413     
00414 
00415     void setSymmetries(int nNodes_,int *new_can,const int *sym_src);
00416     void addLinearPeriodic(int nFaces_,int nPer,
00417         const int *facesA,const int *facesB,int idxBase,
00418         int nNodes_,const CkVector3d *nodeLocs);
00419     const int *getCanon(void) const;
00420     const FEM_Symmetries_t *getSymmetries(void) const;
00421     const FEM_Sym_List &getSymList(void) const;
00422 
00423 
00424 };
00425 
00426 FEM_Partition &FEM_curPartition(void);
00427 
00428 
00429 #define FEMAPI(routineName) TCHARM_API_TRACE(routineName,"fem")
00430 
00431 
00432 
00433 
00434 
00435 
00436 void FEM_Mesh_partition(const FEM_Mesh *mesh,int nchunks,int *elem2chunk);
00437 
00438 
00439 
00440 
00441 
00442 class FEM_Mesh_Output {
00443  public:
00444     virtual ~FEM_Mesh_Output() {} 
00445     
00446     virtual void accept(int chunkNo,FEM_Mesh *msg) =0;
00447 };
00448 
00449 
00450 
00451 
00452 void FEM_Mesh_split(FEM_Mesh *mesh,int nchunks,
00453     const FEM_Partition &partition,FEM_Mesh_Output *out);
00454 
00455 
00456 
00457 int *CkCopyArray(const int *src,int len,int indexBase);
00458 
00459 
00460 
00461 
00462 
00463 class FEM_ElemAdj_Layer : public CkNoncopyable {
00464  public:
00465   int initialized;
00466   int nodesPerTuple; 
00467  
00468  class elemAdjInfo {
00469   public:
00470     
00471     int tuplesPerElem; 
00472     intArrayPtr elem2tuple; 
00473     elemAdjInfo(void) {tuplesPerElem=0;}
00474     ~elemAdjInfo(void) {}
00475     void pup(PUP::er &p) {
00476     }
00477   };
00478  
00479  elemAdjInfo elem[FEM_MAX_ELTYPE];
00480 
00481  FEM_ElemAdj_Layer() {initialized=0;}
00482 
00483   virtual void pup(PUP::er &p){
00484     p | nodesPerTuple;
00485     p | initialized;
00486     for(int i=0;i<FEM_MAX_ELTYPE;i++){
00487       p | elem[i].tuplesPerElem;
00488       if(elem[i].tuplesPerElem == 0){
00489     continue;
00490       }
00491       int *arr;
00492       if(p.isUnpacking()){
00493     arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
00494       }else{
00495     arr = elem[i].elem2tuple;
00496       }
00497       p(arr,nodesPerTuple*elem[i].tuplesPerElem);
00498       if(p.isUnpacking()){
00499     elem[i].elem2tuple = arr;
00500       }
00501     }
00502   }
00503 };
00504 
00505 
00506 
00507 
00508 #endif
00509 
00510