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