00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __PARFUM_INTERNALS_H
00019 #define __PARFUM_INTERNALS_H
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <assert.h>
00024 #include <vector>
00025 #include <set>
00026
00027 #include "charm-api.h"
00028 #include "ckvector3d.h"
00029 #include "tcharm.h"
00030 #include "charm++.h"
00031 #include "converse.h"
00032 #include "cklists.h"
00033 #include "mpi.h"
00034 #include "pup_mpi.h"
00035 #define checkMPI pup_checkMPI
00036
00037 #include "idxl_layout.h"
00038 #include "idxl.h"
00039 #include "idxl_comm.h"
00040
00041 #include "ParFUM.decl.h"
00042 #include "msa/msa.h"
00043 #include "cklists.h"
00044 #include "pup.h"
00045
00046 #include "ParFUM.h"
00047
00048
00049 #include <iosfwd>
00050
00051 #include "ParFUM_Adapt.decl.h"
00052
00053 #if defined(WIN32)
00054 #include <iterator>
00055 #endif
00056
00057 #if ! CMK_HAS_STD_INSERTER
00058 #include <list>
00059 namespace std {
00060 template<class Container, class Iterator>
00061 insert_iterator<Container> inserter(
00062 Container& _Cont,
00063 Iterator _It
00064 );
00065 };
00066 #endif
00067
00068 #if defined(WIN32) && defined(max)
00069 #undef max
00070 #endif
00071
00072
00073 extern CProxy_femMeshModify meshMod;
00074
00075 #define MAX_CHUNK 1000000000
00076
00077
00078 #define FEM_SILENT
00079
00080
00081 CtvExtern(FEM_Adapt_Algs *, _adaptAlgs);
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 typedef IDXL_Side FEM_Comm;
00095 typedef IDXL_List FEM_Comm_List;
00096 typedef IDXL_Rec FEM_Comm_Rec;
00097
00102 class FEM_Comm_Holder {
00103 IDXL comm;
00104 bool registered;
00105 IDXL_Comm_t idx;
00106 void registerIdx(IDXL_Chunk *c);
00107 public:
00108 FEM_Comm_Holder(FEM_Comm *sendComm, FEM_Comm *recvComm);
00109 void pup(PUP::er &p);
00110 ~FEM_Comm_Holder(void);
00111
00113 inline IDXL_Comm_t getIndex(IDXL_Chunk *c) {
00114 if (idx==-1) registerIdx(c);
00115 return idx;
00116 }
00117 };
00118
00119
00120
00124 typedef unsigned char FEM_Symmetries_t;
00125
00126
00128 class FEM_Sym_Desc : public PUP::able {
00129 public:
00130 virtual ~FEM_Sym_Desc();
00131
00133 virtual CkVector3d applyLoc(const CkVector3d &loc) const =0;
00134
00136 virtual CkVector3d applyVec(const CkVector3d &vec) const =0;
00137
00139 friend inline void operator|(PUP::er &p,FEM_Sym_Desc &a) {a.pup(p);}
00140 friend inline void operator|(PUP::er &p,FEM_Sym_Desc* &a) {
00141 PUP::able *pa=a; p(&pa); a=(FEM_Sym_Desc *)pa;
00142 }
00143 };
00144
00146 class FEM_Sym_Linear : public FEM_Sym_Desc {
00147 CkVector3d shift;
00148 public:
00149 FEM_Sym_Linear(const CkVector3d &shift_) :shift(shift_) {}
00150 FEM_Sym_Linear(CkMigrateMessage *m) {}
00151
00153 CkVector3d applyLoc(const CkVector3d &loc) const {return loc+shift;}
00154
00156 virtual CkVector3d applyVec(const CkVector3d &vec) const {return vec;}
00157
00158 virtual void pup(PUP::er &p);
00159 PUPable_decl(FEM_Sym_Linear);
00160 };
00161
00166 class FEM_Sym_List {
00167
00168 CkPupAblePtrVec<FEM_Sym_Desc> sym;
00169
00170 FEM_Sym_List(const FEM_Sym_List &src);
00171 public:
00172 FEM_Sym_List();
00173 void operator=(const FEM_Sym_List &src);
00174 ~FEM_Sym_List();
00175
00178 FEM_Symmetries_t add(FEM_Sym_Desc *desc);
00179
00181 void applyLoc(CkVector3d *loc,FEM_Symmetries_t sym) const;
00182
00184 void applyVec(CkVector3d *vec,FEM_Symmetries_t sym) const;
00185
00186 void pup(PUP::er &p);
00187 };
00188
00190 template <class T>
00191 class BasicTable2d : public CkNoncopyable {
00192 protected:
00193 int rows;
00194 int cols;
00195 T *table;
00196 public:
00197 BasicTable2d(T *src,int cols_,int rows_)
00198 :rows(rows_), cols(cols_), table(src) {}
00199
00201 inline int size(void) const {return rows;}
00203 inline int width(void) const {return cols;}
00204
00205 T *getData(void) {return table;}
00206 const T *getData(void) const {return table;}
00207
00208
00209 T operator() (int r,int c) const {return table[c+r*cols];}
00210 T &operator() (int r,int c) {return table[c+r*cols];}
00211
00212
00214 inline T *getRow(int r) {return &table[r*cols];}
00216 inline const T *getRow(int r) const {return &table[r*cols];}
00217 inline void getRow(int r,T *dest,T idxBase=0) const {
00218 const T *src=getRow(r);
00219 for (int c=0;c<cols;c++) dest[c]=src[c]+idxBase;
00220 }
00221 inline T *operator[](int r) {return getRow(r);}
00222 inline const T *operator[](int r) const {return getRow(r);}
00223 inline void setRow(int r,const T *src,T idxBase=0) {
00224 T *dest=getRow(r);
00225 for (int c=0;c<cols;c++) dest[c]=src[c]-idxBase;
00226 }
00227 inline void setRow(int r,T value) {
00228 T *dest=getRow(r);
00229 for (int c=0;c<cols;c++) dest[c]=value;
00230 }
00231
00232
00233 void set(const T *src,T idxBase=0) {
00234 for (int r=0;r<rows;r++)
00235 for (int c=0;c<cols;c++)
00236 table[c+r*cols]=src[c+r*cols]-idxBase;
00237 }
00238 void setTranspose(const T *srcT,int idxBase=0) {
00239 for (int r=0;r<rows;r++)
00240 for (int c=0;c<cols;c++)
00241 table[c+r*cols]=srcT[r+c*rows]-idxBase;
00242 }
00243 void get(T *dest,T idxBase=0) const {
00244 for (int r=0;r<rows;r++)
00245 for (int c=0;c<cols;c++)
00246 dest[c+r*cols]=table[c+r*cols]+idxBase;
00247 }
00248 void getTranspose(T *destT,int idxBase=0) const {
00249 for (int r=0;r<rows;r++)
00250 for (int c=0;c<cols;c++)
00251 destT[r+c*rows]=table[c+r*cols]+idxBase;
00252 }
00253 void set(T value) {
00254 for (int r=0;r<rows;r++) setRow(r,value);
00255 }
00256 void setRowLen(int rows_) {
00257 rows = rows_;
00258 }
00259 };
00260
00262
00265 template <class T>
00266 class AllocTable2d : public BasicTable2d<T> {
00268 int max;
00270 T fill;
00272 T *allocTable;
00273 public:
00275 AllocTable2d(int cols_=0,int rows_=0,T fill_=0)
00276 :BasicTable2d<T>(NULL,cols_,rows_), max(0), fill(fill_)
00277 {
00278 allocTable = NULL;
00279 if (this->rows>0) allocate(this->rows);
00280 }
00282 ~AllocTable2d() {delete[] allocTable;}
00284 void allocate(int rows_) {
00285 allocate(this->width(),rows_);
00286 }
00288 void allocate(int cols_,int rows_,int max_=0) {
00289 if (cols_==this->cols && rows_<max) {
00290
00291 this->rows=rows_;
00292 return;
00293 }
00294 if (max_==0) {
00295 if (rows_==this->rows+1)
00296 max_=10+rows_+(rows_>>2);
00297 else
00298 max_=rows_;
00299 }
00300
00301 if(max_ < 60000)
00302 max_ = 60000;
00303
00304 if(max_ > 60000 && max_ < 290000)
00305 max_ = 300000;
00306
00307 int oldRows=this->rows;
00308 this->cols=cols_;
00309 this->rows=rows_;
00310 this->max=max_;
00311 this->table=new T[max*this->cols];
00312
00313 int copyRows=0;
00314 if (allocTable!=NULL) {
00315 copyRows=oldRows;
00316 if (copyRows>max) copyRows=max;
00317 memcpy(this->table,allocTable,sizeof(T)*this->cols*copyRows);
00318 delete[] allocTable;
00319 }else{
00320 for (int r=copyRows;r<max;r++)
00321 this->setRow(r,fill);
00322 }
00323 allocTable = this->table;
00324 }
00325
00327 void pup(PUP::er &p) {
00328 p|this->rows; p|this->cols;
00329 if (this->table==NULL) allocate(this->rows);
00330 p(this->table,this->rows*this->cols);
00331 }
00333 void pupSingle(PUP::er &p, int pupindx) {
00334 int startIdx = this->cols*pupindx;
00335 for(int i=0; i<this->cols; i++) {
00336 p|this->table[startIdx+i];
00337 }
00338 }
00339
00340 friend void operator|(PUP::er &p,AllocTable2d<T> &t) {t.pup(p);}
00341
00343 T *push_back(void) {
00344 if (this->rows>=max)
00345 {
00346 int newMax=max+(max/4)+16;
00347 allocate(this->cols,this->rows,newMax);
00348 }
00349 this->rows++;
00350 return getRow(this->rows-1);
00351 }
00352
00356 void register_data(T *user,int len,int max){
00357 if(allocTable != NULL){
00358 delete [] allocTable;
00359 allocTable = NULL;
00360 }
00361 this->table = user;
00362 this->rows = len;
00363 this->max = max;
00364 }
00365 };
00366
00370 CDECL const char *FEM_Get_entity_name(int entity,char *storage);
00371
00375 CDECL const char *FEM_Get_attr_name(int attr,char *storage);
00376
00377
00379
00383 class FEM_Attribute {
00385 FEM_Entity *e;
00387 FEM_Attribute *ghost;
00389 int attr;
00391 int width;
00393 int datatype;
00395 bool allocated;
00396
00398
00399 void bad(const char *field,bool forRead,int cur,int next,const char *caller) const;
00400
00401 protected:
00407 virtual void allocate(int length,int width,int datatype) =0;
00408 public:
00409 FEM_Attribute(FEM_Entity *owner_,int myAttr_);
00410 virtual void pup(PUP::er &p);
00411 virtual void pupSingle(PUP::er &p, int pupindx);
00412 virtual ~FEM_Attribute();
00413
00415 inline void setGhost(FEM_Attribute *ghost_) { ghost=ghost_;}
00416
00418 inline bool isGhost(void) const { return ghost!=NULL; }
00419
00421 inline int getAttr(void) const {return attr;}
00422
00423 inline FEM_Entity *getEntity(void) {return e;}
00424
00427 int getLength(void) const;
00428 int getRealLength(void) const;
00429
00430 int getMax();
00431
00433 inline int getWidth(void) const { return width<0?0:width; }
00434 inline int getRealWidth(void) const { return width; }
00435
00437 inline int getDatatype(void) const { return datatype; }
00438
00444 void setLength(int l,const char *caller="");
00445
00450 void setWidth(int w,const char *caller="");
00451
00456 void setDatatype(int dt,const char *caller="");
00457
00463 virtual void copyShape(const FEM_Attribute &src);
00464
00467 void tryAllocate(void);
00468
00470 inline void reallocate(void) { allocated=false; tryAllocate(); }
00471
00473 inline bool isAllocated(void) const {return allocated;}
00474
00483 virtual void set(const void *src, int firstItem,int length,
00484 const IDXL_Layout &layout, const char *caller);
00485
00495 virtual void get(void *dest, int firstItem,int length,
00496 const IDXL_Layout &layout, const char *caller) const;
00497
00499 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity) =0;
00500
00504 virtual void register_data(void *dest, int length,int max,
00505 const IDXL_Layout &layout, const char *caller);
00506
00507 };
00508 PUPmarshall(FEM_Attribute)
00509
00510
00511
00515 class FEM_DataAttribute : public FEM_Attribute {
00516 typedef FEM_Attribute super;
00518 AllocTable2d<unsigned char> *char_data;
00520 AllocTable2d<int> *int_data;
00522 AllocTable2d<float> *float_data;
00524 AllocTable2d<double> *double_data;
00525 protected:
00526 virtual void allocate(int length,int width,int datatype);
00527 public:
00528 FEM_DataAttribute(FEM_Entity *owner,int myAttr);
00529 virtual void pup(PUP::er &p);
00530 virtual void pupSingle(PUP::er &p, int pupindx);
00531 ~FEM_DataAttribute();
00532
00533 AllocTable2d<unsigned char> &getChar(void) {return *char_data;}
00534 const AllocTable2d<unsigned char> &getChar(void) const {return *char_data;}
00535
00536 AllocTable2d<int> &getInt(void) {return *int_data;}
00537 const AllocTable2d<int> &getInt(void) const {return *int_data;}
00538
00539 AllocTable2d<double> &getDouble(void) {return *double_data;}
00540 const AllocTable2d<double> &getDouble(void) const {return *double_data;}
00541
00542 AllocTable2d<float> &getFloat(void) {return *float_data;}
00543 const AllocTable2d<float> &getFloat(void) const {return *float_data;}
00544
00545
00546 virtual void set(const void *src, int firstItem,int length,
00547 const IDXL_Layout &layout, const char *caller);
00548
00549 virtual void get(void *dest, int firstItem,int length,
00550 const IDXL_Layout &layout, const char *caller) const;
00551
00552 virtual void register_data(void *dest, int length,int max,
00553 const IDXL_Layout &layout, const char *caller);
00554
00555
00557 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00558
00560
00562 void interpolate(int A,int B,int D,double frac);
00564
00566 void interpolate(int *iNodes,int rNode,int k);
00567 };
00568 PUPmarshall(FEM_DataAttribute)
00569
00570
00571
00575 class FEM_IndexAttribute : public FEM_Attribute {
00576 public:
00578 class Checker {
00579 public:
00580 virtual ~Checker();
00581
00586 virtual void check(int row,const BasicTable2d<int> &table,
00587 const char *caller) const =0;
00588 };
00589 private:
00590 typedef FEM_Attribute super;
00591 AllocTable2d<int> idx;
00593 Checker *checker;
00594 protected:
00595 virtual void allocate(int length,int width,int datatype);
00596 public:
00597 FEM_IndexAttribute(FEM_Entity *owner,int myAttr, Checker *checker_=NULL);
00598 virtual void pup(PUP::er &p);
00599 virtual void pupSingle(PUP::er &p, int pupindx);
00600 ~FEM_IndexAttribute();
00601
00602 AllocTable2d<int> &get(void) {return idx;}
00603 const AllocTable2d<int> &get(void) const {return idx;}
00604
00605 virtual void set(const void *src, int firstItem,int length,
00606 const IDXL_Layout &layout, const char *caller);
00607
00608 virtual void get(void *dest, int firstItem,int length,
00609 const IDXL_Layout &layout, const char *caller) const;
00610
00611 virtual void register_data(void *dest, int length, int max,
00612 const IDXL_Layout &layout, const char *caller);
00613
00615 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00616 };
00617 PUPmarshall(FEM_IndexAttribute)
00618
00619
00620
00626 class FEM_VarIndexAttribute : public FEM_Attribute{
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 private:
00676 typedef FEM_Attribute super;
00677 CkVec<CkVec<ElemID> > idx;
00678 int oldlength;
00679 protected:
00680 virtual void allocate(int _length,int _width,int _datatype){
00681 if(_length > oldlength){
00682 setWidth(1,"allocate");
00683 oldlength = _length*2;
00684 idx.reserve(oldlength);
00685 for(int i=idx.size();i<oldlength;i++){
00686 CkVec<ElemID> tempVec;
00687 idx.insert(i,tempVec);
00688 }
00689 }
00690 };
00691 public:
00692 FEM_VarIndexAttribute(FEM_Entity *owner,int myAttr);
00693 ~FEM_VarIndexAttribute(){};
00694 virtual void pup(PUP::er &p);
00695 virtual void pupSingle(PUP::er &p, int pupindx);
00696 CkVec<CkVec<ElemID> > &get(){return idx;};
00697 const CkVec<CkVec<ElemID> > &get() const {return idx;};
00698
00699 virtual void set(const void *src,int firstItem,int length,
00700 const IDXL_Layout &layout,const char *caller);
00701
00702 virtual void get(void *dest, int firstItem,int length,
00703 const IDXL_Layout &layout, const char *caller) const;
00704
00705 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00706
00707 int findInRow(int row,const ElemID &data);
00708
00709 void print();
00710 };
00711
00713
00718 class FEM_Entity {
00720 typedef CkVec<FEM_Symmetries_t> sym_t;
00722 int length;
00724 int max;
00726 FEM_Mesh_alloc_fn resize;
00728 void *args;
00729
00740 CkVec<FEM_Attribute *> attributes;
00741
00747 FEM_DataAttribute *coord;
00748 void allocateCoord(void);
00749
00756 FEM_DataAttribute *sym;
00757 void allocateSym(void);
00758
00763 FEM_IndexAttribute *globalno;
00764 void allocateGlobalno(void);
00765
00770 FEM_DataAttribute *boundary;
00771 void allocateBoundary();
00772
00774
00776 FEM_DataAttribute *meshSizing;
00777 void allocateMeshSizing(void);
00778
00785 FEM_DataAttribute *valid;
00786 int first_invalid, last_invalid;
00792 int* invalidList;
00794 int invalidListLen;
00796 int invalidListAllLen;
00797
00798 protected:
00812 virtual void create(int attr,const char *caller);
00813
00818 void add(FEM_Attribute *attribute);
00819 public:
00820
00821 FEM_Entity *ghost;
00822
00823 FEM_Comm ghostSend;
00824 FEM_Comm ghostRecv;
00825
00826 FEM_Comm_Holder ghostIDXL;
00827
00828 FEM_Entity(FEM_Entity *ghost_);
00829 void pup(PUP::er &p);
00830 virtual ~FEM_Entity();
00831
00833 bool isGhost(void) const {return ghost==NULL;}
00834
00836 FEM_Entity *getGhost(void) {return ghost;}
00837 const FEM_Entity *getGhost(void) const {return ghost;}
00838
00839
00840
00841 void clearGhost();
00842
00844 inline int size(void) const {return length==-1?0:length;}
00845 inline int realsize(void) const {return length;}
00846
00847
00848 inline int getMax() { if(max > 0) return max; else return length;}
00849
00851 virtual const char *getName(void) const =0;
00852
00854 void copyShape(const FEM_Entity &src);
00855
00860 void setLength(int newlen, bool f=false);
00861
00863 void reserveLength(int newlen);
00864
00870 void setMaxLength(int newLen,int newMaxLen,void *args,FEM_Mesh_alloc_fn fn);
00871
00874 void copyEntity(int dstEntity,const FEM_Entity &src,int srcEntity);
00875
00878 int push_back(const FEM_Entity &src,int srcEntity);
00879
00885 FEM_Attribute *lookup(int attr,const char *caller);
00886
00887
00891 int getAttrs(int *attrs) const {
00892 int len=attributes.size();
00893 for (int i=0;i<len;i++)
00894 attrs[i]=attributes[i]->getAttr();
00895 return len;
00896 }
00897
00901 void allocateValid();
00902 void set_valid(int idx, bool isNode=false);
00903 void set_invalid(int idx, bool isNode=false);
00904 int is_valid(int idx);
00905 int is_valid_any_idx(int idx);
00906 int is_valid_nonghost_idx(int idx);
00907
00908 int count_valid();
00909 int get_next_invalid(FEM_Mesh *m=NULL, bool isNode=false, bool isGhost=false);
00910 void set_all_invalid();
00911
00912 int isBoundary(int idx);
00913
00914 virtual bool hasConn(int idx)=0;
00918 void set_coord(int idx, double x, double y);
00919 void set_coord(int idx, double x, double y, double z);
00920
00921 void get_coord(int idx, double &x, double &y);
00922 void get_coord(int idx, double &x, double &y, double &z);
00923
00926 CkVec<FEM_Attribute *>* getAttrVec(){
00927 return &attributes;
00928 }
00929
00930
00931 inline FEM_DataAttribute *getCoord(void) {return coord;}
00932 inline const FEM_DataAttribute *getCoord(void) const {return coord;}
00933
00934
00935 const FEM_Symmetries_t *getSymmetries(void) const {
00936 if (sym==NULL) return NULL;
00937 else return (const FEM_Symmetries_t *)sym->getChar()[0];
00938 }
00939 FEM_Symmetries_t getSymmetries(int r) const {
00940 if (sym==NULL) return FEM_Symmetries_t(0);
00941 else return sym->getChar()(r,0);
00942 }
00943 void setSymmetries(int r,FEM_Symmetries_t s);
00944
00945
00946 bool hasGlobalno(void) const {return globalno!=0;}
00947 int getGlobalno(int r) const {
00948 if (globalno==0) return -1;
00949 return globalno->get()(r,0);
00950 }
00951 void setGlobalno(int r,int g);
00952 void setAscendingGlobalno(void);
00953 void setAscendingGlobalno(int base);
00954 void copyOldGlobalno(const FEM_Entity &e);
00955
00956
00957 bool hasMeshSizing(void) const {return meshSizing!=0;}
00958 double getMeshSizing(int r);
00959 void setMeshSizing(int r,double s);
00960 void setMeshSizing(double *sf);
00961
00962
00963 FEM_Comm &setGhostSend(void) { return ghostSend; }
00964 const FEM_Comm &getGhostSend(void) const { return ghostSend; }
00965 FEM_Comm &setGhostRecv(void) {
00966 if (ghost==NULL) return ghostRecv;
00967 else return ghost->ghostRecv;
00968 }
00969 const FEM_Comm &getGhostRecv(void) const { return ghost->ghostRecv; }
00970
00971 void addVarIndexAttribute(int code){
00972 FEM_VarIndexAttribute *varAttribute = new FEM_VarIndexAttribute(this,code);
00973 add(varAttribute);
00974 }
00975
00976 void print(const char *type,const IDXL_Print_Map &map);
00977 };
00978 PUPmarshall(FEM_Entity)
00979
00980
00981 inline int FEM_Attribute::getLength(void) const { return e->size(); }
00982 inline int FEM_Attribute::getRealLength(void) const { return e->realsize(); }
00983 inline int FEM_Attribute::getMax(){ return e->getMax();}
00984
00985
00987
00992 class FEM_Node : public FEM_Entity {
00993 typedef FEM_Entity super;
00994
01000 FEM_DataAttribute *primary;
01001 void allocatePrimary(void);
01002
01003 void allocateElemAdjacency();
01004 void allocateNodeAdjacency();
01005
01006 FEM_VarIndexAttribute *elemAdjacency;
01007
01008 FEM_VarIndexAttribute *nodeAdjacency;
01009
01010 typedef ElemID var_id;
01011 protected:
01012 virtual void create(int attr,const char *caller);
01013 public:
01014 FEM_Comm shared;
01015 FEM_Comm_Holder sharedIDXL;
01016
01017 FEM_Node(FEM_Node *ghost_);
01018 void pup(PUP::er &p);
01019 ~FEM_Node();
01020
01021 virtual const char *getName(void) const;
01022
01023 inline bool getPrimary(int nodeNo) const {
01024 if (primary==NULL) return true;
01025 else return primary->getChar()(nodeNo,0);
01026 }
01027 inline void setPrimary(int nodeNo,bool isPrimary) {
01028 if (primary==NULL) allocatePrimary();
01029 primary->getChar()(nodeNo,0)=isPrimary;
01030 }
01031 void fillElemAdjacencyTable(int type,const FEM_Elem &elem);
01032 void setElemAdjacency(int type,const FEM_Elem &elem);
01033 void fillNodeAdjacency(const FEM_Elem &elem);
01034 void setNodeAdjacency(const FEM_Elem &elem);
01035 void fillNodeAdjacencyForElement(int node,int nodesPerElem,const int *conn,FEM_VarIndexAttribute *adjacencyAttr);
01036 bool hasConn(int idx);
01037 void print(const char *type,const IDXL_Print_Map &map);
01038 };
01039 PUPmarshall(FEM_Node)
01040
01041
01042
01043
01048 class FEM_Elem:public FEM_Entity {
01049 typedef FEM_Entity super;
01050 protected:
01051 typedef AllocTable2d<int> conn_t;
01052
01053 int tuplesPerElem;
01054
01055
01056 FEM_IndexAttribute *conn;
01057 FEM_IndexAttribute *elemAdjacency;
01058 FEM_IndexAttribute *elemAdjacencyTypes;
01059
01060 public:
01061
01062 FEM_Elem(const FEM_Mesh &mesh_, FEM_Elem *ghost_);
01063 void pup(PUP::er &p);
01064 ~FEM_Elem();
01065
01066 virtual const char *getName(void) const;
01067
01068
01069 inline conn_t &setConn(void) {return conn->get();}
01070 inline const conn_t &getConn(void) const {return conn->get();}
01071
01072 void print(const char *type,const IDXL_Print_Map &map);
01073
01074 void create(int attr,const char *caller);
01075
01076 void allocateElemAdjacency();
01077
01078 FEM_IndexAttribute *getElemAdjacency(){return elemAdjacency;}
01079
01080
01081 int getConn(int elem,int nodeNo) const {return conn->get()(elem,nodeNo);}
01082 int getNodesPer(void) const {return conn->get().width();}
01083 int *connFor(int i) {return conn->get().getRow(i);}
01084 const int *connFor(int i) const {return conn->get().getRow(i);}
01085 void connIs(int i,const int *src) {conn->get().setRow(i,src);}
01086 bool hasConn(int idx);
01087 };
01088 PUPmarshall(FEM_Elem)
01089
01090
01091
01092
01093
01100 class FEM_Sparse : public FEM_Elem {
01101 typedef FEM_Elem super;
01102 typedef AllocTable2d<int> elem_t;
01103
01112 FEM_IndexAttribute *elem;
01113 void allocateElem(void);
01114 const FEM_Mesh &mesh;
01115 protected:
01116 virtual void create(int attr,const char *caller);
01117 public:
01118 FEM_Sparse(const FEM_Mesh &mesh_, FEM_Sparse *ghost_);
01119 void pup(PUP::er &p);
01120 virtual ~FEM_Sparse();
01121
01122 virtual const char *getName(void) const;
01123
01125 bool hasElements(void) const {return elem!=NULL;}
01126
01128 inline elem_t &setElem(void) {return elem->get();}
01129 inline const elem_t &getElem(void) const {return elem->get();}
01130 };
01131 PUPmarshall(FEM_Sparse)
01132
01133
01135 class FEM_Userdata_pupfn {
01136 FEM_Userdata_fn fn;
01137 void *data;
01138 public:
01139 FEM_Userdata_pupfn(FEM_Userdata_fn fn_,void *data_)
01140 :fn(fn_), data(data_) {}
01142 void pup(PUP::er &p) {
01143 (fn)((pup_er)&p,data);
01144 }
01145 };
01146
01148 class FEM_Userdata_item {
01149 CkVec<char> data;
01150 public:
01151 int tag;
01152 FEM_Userdata_item(int tag_=-1) {tag=tag_;}
01153
01155 bool hasStored(void) const {return data.size()!=0;}
01156
01158 void store(FEM_Userdata_pupfn &f) {
01159 data.resize(PUP::size(f));
01160 PUP::toMemBuf(f,&data[0],data.size());
01161 }
01163 void restore(FEM_Userdata_pupfn &f) {
01164 PUP::fromMemBuf(f,&data[0],data.size());
01165 }
01166
01168 void pup(PUP::er &p) {
01169 p|tag;
01170 p|data;
01171 }
01172 };
01173
01175 class FEM_Userdata_list {
01176 CkVec<FEM_Userdata_item> list;
01177 public:
01178 FEM_Userdata_item &find(int tag) {
01179 for (int i=0;i<list.size();i++)
01180 if (list[i].tag==tag)
01181 return list[i];
01182
01183 list.push_back(FEM_Userdata_item(tag));
01184 return list[list.size()-1];
01185 }
01186 int size(){
01187 return list.size();
01188 }
01189 void pup(PUP::er &p) {p|list;}
01190 };
01191
01192
01193 void FEM_Index_Check(const char *caller,const char *entityType,int type,int maxType);
01194 void FEM_Is_NULL(const char *caller,const char *entityType,int type);
01195
01208 template <class T>
01209 class FEM_Entity_Types {
01210 CkVec<T *> types;
01211 const FEM_Mesh &mesh;
01212 const char *name;
01213
01214 public:
01215 FEM_Entity_Types(const FEM_Mesh &mesh_,const char *name_)
01216 :mesh(mesh_), name(name_) {}
01217 void pup(PUP::er &p) {
01218
01219 int n=types.size();
01220 p|n;
01221 for (int i=0;i<n;i++) {
01222 int isNULL=0;
01223 if (!p.isUnpacking()) isNULL=(types[i]==NULL);
01224 p|isNULL;
01225 if (!isNULL) set(i,"pup").pup(p);
01226 }
01227 }
01228 ~FEM_Entity_Types() {
01229 for (int i=0;i<types.size();i++)
01230 if (types[i]) delete types[i];
01231 }
01232
01234 inline int size(void) const {return types.size();}
01235
01237 const T &get(int type,const char *caller="") const {
01238 FEM_Index_Check(caller,name,type,types.size());
01239 const T *ret=types[type];
01240 if (ret==NULL) FEM_Is_NULL(caller,name,type);
01241 return *ret;
01242 }
01243
01245 bool has(int type) const {
01246 return (type<types.size()) && (types[type]!=NULL);
01247 }
01248
01250 bool hasNonEmpty(int type) const {
01251 return (type<types.size()) && (types[type]!=NULL) && (types[type]->size()>0);
01252 }
01253
01255 T &set(int type,const char *caller="") {
01256 if (type<0) FEM_Index_Check(caller,name,type,types.size());
01257 while (types.size()<=type) types.push_back(NULL);
01258 if (types[type]==NULL) {
01259 T *ghost=new T(mesh,NULL);
01260 types[type]=new T(mesh,ghost);
01261 }
01262 return *types[type];
01263 }
01264
01266 inline T &operator[] (int type) { return set(type); }
01267 inline const T &operator[] (int type) const { return get(type); }
01268
01269 };
01270
01272 inline int zeroToMinusOne(int i) {
01273 if (i==0) return -1;
01274 return i;
01275 }
01276
01277
01278 class ParFUMShadowArray;
01279
01280
01282
01286 class FEM_Mesh : public CkNoncopyable {
01288 FEM_Sym_List symList;
01289 bool m_isSetting;
01290
01291 void checkElemType(int elType,const char *caller) const;
01292 void checkSparseType(int uniqueID,const char *caller) const;
01293
01294 public:
01295 femMeshModify *fmMM;
01296 ParFUMShadowArray *parfumSA;
01297 bool lastLayerSet;
01298 FEM_ElemAdj_Layer* lastElemAdjLayer;
01299 void setFemMeshModify(femMeshModify *m);
01300 void setParfumSA(ParFUMShadowArray *m);
01301
01302 FEM_Mesh();
01303 void pup(PUP::er &p);
01304 ~FEM_Mesh();
01305
01307 FEM_Node node;
01308
01310 FEM_Entity_Types<FEM_Elem> elem;
01311
01313 FEM_Entity_Types<FEM_Sparse> sparse;
01314
01316 FEM_Userdata_list udata;
01317
01319 void setSymList(const FEM_Sym_List &src) {symList=src;}
01320 const FEM_Sym_List &getSymList(void) const {return symList;}
01321
01324 void copyShape(const FEM_Mesh &src);
01325
01326
01327 femMeshModify *getfmMM();
01328
01329
01330 FEM_Entity &setCount(int elTypeOrMinusOne) {
01331 if (elTypeOrMinusOne==-1) return node;
01332 else return elem[chkET(elTypeOrMinusOne)];
01333 }
01334 const FEM_Entity &getCount(int elTypeOrMinusOne) const {
01335 if (elTypeOrMinusOne==-1) return node;
01336 else return elem[chkET(elTypeOrMinusOne)];
01337 }
01338 FEM_Elem &setElem(int elType) {return elem[chkET(elType)];}
01339 const FEM_Elem &getElem(int elType) const {return elem[chkET(elType)];}
01340 int chkET(int elType) const;
01341
01343 FEM_Entity *lookup(int entity,const char *caller);
01344 const FEM_Entity *lookup(int entity,const char *caller) const;
01345
01347 inline bool isSetting(void) const {return m_isSetting;}
01348 void becomeSetting(void) {m_isSetting=true;}
01349 void becomeGetting(void) {m_isSetting=false;}
01350
01351 int nElems() const
01352 {return nElems(elem.size());}
01354 int nElems(int t) const;
01356 int getGlobalElem(int elType,int elNo) const;
01358 void setAscendingGlobalno(void);
01360 void setAbsoluteGlobalno();
01361
01362 void copyOldGlobalno(const FEM_Mesh &m);
01363 void print(int idxBase);
01365 int getEntities(int *entites);
01366
01372 void clearSharedNodes();
01373 void clearGhostNodes();
01374 void clearGhostElems();
01375
01376
01377
01378
01379
01380
01381
01382 void createNodeElemAdj();
01383 void createNodeNodeAdj();
01384 void createElemElemAdj();
01385
01386 FEM_ElemAdj_Layer *getElemAdjLayer(void);
01387
01388
01389
01390
01393 void e2e_getAll(int e, int *neighborss, int etype=0);
01395 int e2e_getNbr(int e, short idx, int etype=0);
01398 int e2e_getIndex(int e, int nbr, int etype=0);
01400 ElemID e2e_getElem(int idx, int nbr, int etype=0);
01402 ElemID e2e_getElem(ElemID elem, int nbr);
01404 ElemID e2e_getElem(ElemID *elem, int nbr);
01407 void e2e_setAll(int e, int *neighbors, int etype=0);
01409 void e2e_setIndex(int e, short idx, int newElem, int etype=0);
01411 void e2e_replace(int e, int oldNbr, int newNbr, int etype=0);
01413 void e2e_replace(ElemID e, ElemID oldNbr, ElemID newNbr);
01414
01416 void e2e_removeAll(int e, int etype=0);
01417
01418 void e2e_printAll(ElemID e);
01419
01420
01421
01422
01425 void e2n_getAll(int e, int *adjnodes, int etype=0);
01427 int e2n_getNode(int e, short idx, int etype=0);
01430 short e2n_getIndex(int e, int n, int etype=0);
01433 void e2n_setAll(int e, int *adjnodes, int etype=0);
01435 void e2n_setIndex(int e, short idx, int newNode, int etype=0);
01437 void e2n_replace(int e, int oldNode, int newNode, int etype=0);
01438
01440 void e2n_removeAll(int e, int etype=0);
01441
01442
01443
01444 int n2n_getLength(int n);
01447 void n2n_getAll(int n, int *&adjnodes, int &sz);
01449 void n2n_add(int n, int newNode);
01451 void n2n_remove(int n, int oldNode);
01453 void n2n_replace(int n, int oldNode, int newNode);
01455 void n2n_removeAll(int n);
01457 int n2n_exists(int n, int queryNode);
01458
01459
01460 int n2e_getLength(int n);
01464 void n2e_getAll(int n, int *&adjelements, int &sz);
01465
01467 const CkVec<ElemID> & n2e_getAll(int n);
01468
01470 ElemID n2e_getElem(int n, int whichAdjElem);
01472 void n2e_add(int n, int newElem);
01474 void n2e_remove(int n, int oldElem);
01476 void n2e_replace(int n, int oldElem, int newElem);
01478 void n2e_removeAll(int n);
01479
01483 int getElementOnEdge(int n1, int n2);
01484
01486 void get2ElementsOnEdge(int n1, int n2, int *result_e1, int *result_e2) ;
01487
01489 void get2ElementsOnEdgeSorted(int n1, int n2, int *result_e1, int *result_e2) ;
01490
01491
01493 int countElementsOnEdge(int n1, int n2);
01494
01495
01496
01497
01498
01500 std::set<std::pair<int,int> > edgesOnBoundary;
01501
01503 std::set<int> verticesOnBoundary;
01504
01508 std::set<int> cornersOnBoundary;
01509
01515 void detectFeatures();
01516
01517 };
01518
01519 PUPmarshall(FEM_Mesh)
01520
01521 FEM_Mesh *FEM_Mesh_lookup(int fem_mesh,const char *caller);
01522 FEM_Entity *FEM_Entity_lookup(int fem_mesh,int entity,const char *caller);
01523 FEM_Attribute *FEM_Attribute_lookup(int fem_mesh,int entity,int attr,const char *caller);
01524
01525 void FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
01526 void *data, int firstItem,int length, const IDXL_Layout &layout);
01527
01528
01529 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,void *data,int firstItem,const IDXL_Layout &layout);
01530 void FEM_Register_entity_impl(int fem_mesh,int entity,void *args,int len,int max,FEM_Mesh_alloc_fn fn);
01532 FEM_Mesh *FEM_Mesh_assemble(int nchunks,FEM_Mesh **chunks);
01533
01534 FILE *FEM_openMeshFile(const char *prefix,int chunkNo,int nchunks,bool forRead);
01535 FEM_Mesh *FEM_readMesh(const char *prefix,int chunkNo,int nChunks);
01536 void FEM_writeMesh(FEM_Mesh *m,const char *prefix,int chunkNo,int nChunks);
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 #define FEM_MAX_ELTYPE 20
01553
01554
01555 void FEM_Abort(const char *msg);
01556 void FEM_Abort(const char *caller,const char *sprintf_msg,int int0=0,int int1=0,int int2=0);
01557
01558
01560
01561 class l2g_t {
01562 public:
01563
01564 virtual int el(int t,int localNo) const {return localNo;}
01565
01566 virtual int no(int localNo) const {return localNo;}
01567 };
01568
01570 template <class T>
01571 class NumberedVec {
01572 CkPupPtrVec<T, CkPupAlwaysAllocatePtr<T> > vec;
01573
01574 public:
01575
01576 void makeLonger(int toHaveElement)
01577 {
01578 int oldSize=vec.size(), newSize=toHaveElement+1;
01579 if (oldSize>=newSize) return;
01580 vec.resize(newSize);
01581 for (int j=oldSize;j<newSize;j++)
01582 vec[j]=new T;
01583 }
01584
01585 void reinit(int doomedEl) {
01586 vec[doomedEl].destroy();
01587 vec[doomedEl]=new T;
01588 }
01589
01590 int size(void) const {return vec.size();}
01591
01592
01593 T &operator[](int i) {
01594 if (i>=vec.size()) makeLonger(i);
01595 return *( vec[i] );
01596 }
01597 const T &operator[](int i) const {return *( vec[i] );}
01598
01599 void pup(PUP::er &p) {
01600 vec.pup(p);
01601 }
01602 friend void operator|(PUP::er &p,NumberedVec<T> &v) {v.pup(p);}
01603 };
01604
01605
01607 template <class T>
01608 class ArrayPtrT : public CkNoncopyable {
01609 T *sto;
01610 public:
01611 ArrayPtrT() {sto=NULL;}
01612 ArrayPtrT(int *src) {sto=src;}
01613 ~ArrayPtrT() {if (sto) delete[] sto;}
01614 void operator=(T *src) {
01615 if (sto) delete[] sto;
01616 sto=src;
01617 }
01618 operator T *(void) {return sto;}
01619 operator const T *(void) const {return sto;}
01620 T& operator[](int i) {return sto[i];}
01621 const T& operator[](int i) const {return sto[i];}
01622 };
01623 typedef ArrayPtrT<int> intArrayPtr;
01624
01625
01626
01628 template<class T>
01629 class marshallNewHeapCopy {
01630 T *cur;
01631 public:
01632
01633 marshallNewHeapCopy(T *readFrom) :cur(readFrom) {}
01634 marshallNewHeapCopy(const marshallNewHeapCopy &h) :cur(h.cur) {}
01635 marshallNewHeapCopy(void) {
01636 cur=new T;
01637 }
01638
01639 void pup(PUP::er &p) {
01640 cur->pup(p);
01641 }
01642 operator T *() {return cur;}
01643 friend void operator|(PUP::er &p,marshallNewHeapCopy<T> &h) {h.pup(p);}
01644 };
01645 typedef marshallNewHeapCopy<FEM_Mesh> marshallMeshChunk;
01646
01647
01649 template<class T>
01650 class FEM_T_List {
01651 CkPupPtrVec<T> list;
01652 protected:
01653 int FIRST_DT;
01654 int size(void) const {return list.size();}
01655
01657 inline void check(int l,const char *caller) const {
01658 if (l<FIRST_DT || l>=FIRST_DT+list.size() || list[l-FIRST_DT]==NULL)
01659 badIndex(l,caller);
01660 }
01661
01662 void badIndex(int l,const char *caller) const {
01663 if (l<FIRST_DT || l>FIRST_DT+list.size()) bad(l,0,caller);
01664 else bad(l,1,caller);
01665 }
01666 public:
01667 FEM_T_List(int FIRST_DT_) :FIRST_DT(FIRST_DT_) {}
01668 virtual ~FEM_T_List() {}
01669 void pup(PUP::er &p) { p|list; }
01670
01672 virtual void bad(int l,int bad_code,const char *caller) const =0;
01673
01675 int put(T *t) {
01676 for (int i=0;i<list.size();i++)
01677 if (list[i]==NULL) {
01678 list[i]=t;
01679 return FIRST_DT+i;
01680 }
01681 int ret=list.size();
01682 list.push_back(t);
01683 return FIRST_DT+ret;
01684 }
01685
01687 inline T *lookup(int l,const char *caller) const {
01688 check(l,caller);
01689 return list[l-FIRST_DT];
01690 }
01691
01693 void destroy(int l,const char *caller) {
01694 check(l,caller);
01695 list[l-FIRST_DT].destroy();
01696 }
01697
01699 void empty(void) {
01700 for (int i=0;i<list.size();i++) list[i].destroy();
01701 }
01702 };
01703 class FEM_Mesh_list : public FEM_T_List<FEM_Mesh> {
01704 typedef FEM_T_List<FEM_Mesh> super;
01705 public:
01706 FEM_Mesh_list() :super(FEM_MESH_FIRST) { }
01707
01708 virtual void bad(int l,int bad_code,const char *caller) const;
01709 };
01710
01711 #define CHK(p) do{if((p)==0)CkAbort("FEM>Memory Allocation failure.");}while(0)
01712
01713
01715
01725 class FEM_chunk
01726 {
01727 public:
01728 FEM_Mesh_list meshes;
01729 int default_read;
01730 int default_write;
01731
01733 FEM_Comm_t defaultComm;
01734
01736 int thisIndex;
01737
01738 #ifdef CMK_OPTIMIZE
01739 inline void check(const char *where) { }
01740 #else
01741 void check(const char *where);
01742 #endif
01743
01744 private:
01745 CkVec<int> listTmp;
01746
01747 void initFields(void);
01748
01749 public:
01750 FEM_chunk(FEM_Comm_t defaultComm_);
01751 FEM_chunk(CkMigrateMessage *msg);
01752 void pup(PUP::er &p);
01753 ~FEM_chunk();
01754
01756 static FEM_chunk *get(const char *caller);
01757
01758 inline FEM_Mesh *lookup(int fem_mesh,const char *caller) {
01759 return meshes.lookup(fem_mesh,caller);
01760 }
01761
01762 inline FEM_Mesh *getMesh(const char *caller)
01763 {return meshes.lookup(default_read,caller);}
01764 inline FEM_Mesh *setMesh(const char *caller)
01765 {return meshes.lookup(default_write,caller);}
01766
01767 void print(int fem_mesh,int idxBase);
01768 int getPrimary(int nodeNo) { return getMesh("getPrimary")->node.getPrimary(nodeNo); }
01769 const FEM_Comm &getComm(void) {return getMesh("getComm")->node.shared;}
01770
01771
01772 void exchangeGhostLists(int elemType,int inLen,const int *inList,int idxbase);
01773 void recvList(int elemType,int fmChk,int nIdx,const int *idx);
01774 const CkVec<int> &getList(void) {return listTmp;}
01775 void emptyList(void) {listTmp.length()=0;}
01776
01777 void reduce_field(int idxl_datatype, const void *nodes, void *outbuf, int op);
01778 void reduce(int idxl_datatype, const void *inbuf, void *outbuf, int op);
01779 void readField(int idxl_datatype, void *nodes, const char *fname);
01780 };
01781
01783 class FEM_Ghost_Layer : public CkNoncopyable {
01784 public:
01785 int nodesPerTuple;
01786 bool addNodes;
01787 class elemGhostInfo {
01788 public:
01789 bool add;
01790 int tuplesPerElem;
01791 intArrayPtr elem2tuple;
01792 elemGhostInfo(void) {add=false;tuplesPerElem=0;}
01793 ~elemGhostInfo(void) {}
01794 void pup(PUP::er &p) {
01795 }
01796 };
01797 elemGhostInfo elem[FEM_MAX_ELTYPE];
01798 virtual void pup(PUP::er &p){
01799 p | nodesPerTuple;
01800 p | addNodes;
01801 for(int i=0;i<FEM_MAX_ELTYPE;i++){
01802 p | elem[i].add;
01803 p | elem[i].tuplesPerElem;
01804 if(elem[i].tuplesPerElem == 0){
01805 continue;
01806 }
01807 int *arr;
01808 if(p.isUnpacking()){
01809 arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
01810 }else{
01811 arr = elem[i].elem2tuple;
01812 }
01813 p(arr,nodesPerTuple*elem[i].tuplesPerElem);
01814 if(p.isUnpacking()){
01815 elem[i].elem2tuple = arr;
01816 }
01817 }
01818 }
01819 };
01820
01823 class FEM_Ghost_Stencil {
01825 int elType;
01827 int n;
01829 bool addNodes;
01830
01833 intArrayPtr ends;
01834
01843 intArrayPtr adj;
01844 public:
01849 FEM_Ghost_Stencil(int elType_, int n_,bool addNodes_,
01850 const int *ends_,
01851 const int *adj_,
01852 int idxBase);
01853
01855 void check(const FEM_Mesh &mesh) const;
01856
01858 inline int getType(void) const {return elType;}
01859
01866 inline const int *getNeighbor(int i,int j) const {
01867 int start=0;
01868 if (i>0) start=ends[i-1];
01869 if (j>=ends[i]-start) return 0;
01870 return &adj[2*(start+j)];
01871 }
01872
01873 inline bool wantNodes(void) const {return addNodes;}
01874 };
01875
01877 class FEM_Ghost_Region {
01878 public:
01879 FEM_Ghost_Layer *layer;
01880 FEM_Ghost_Stencil *stencil;
01881
01882 FEM_Ghost_Region() {layer=0; stencil=0;}
01883 FEM_Ghost_Region(FEM_Ghost_Layer *l) {layer=l; stencil=0;}
01884 FEM_Ghost_Region(FEM_Ghost_Stencil *s) {layer=0; stencil=s;}
01885 };
01886
01887
01888
01889 class FEM_Initial_Symmetries;
01890
01892 class FEM_Partition : public CkNoncopyable {
01894 int *elem2chunk;
01895
01897 CkVec<FEM_Ghost_Region> regions;
01898 FEM_Ghost_Layer *lastLayer;
01899
01901 FEM_Initial_Symmetries *sym;
01902 public:
01903 FEM_Partition();
01904 ~FEM_Partition();
01905
01906
01907 void setPartition(const int *elem2chunk, int nElem, int idxBase);
01908 const int *getPartition(FEM_Mesh *src,int nChunks) const;
01909
01910
01911 FEM_Ghost_Layer *addLayer(void) {
01912 lastLayer=new FEM_Ghost_Layer();
01913 regions.push_back(lastLayer);
01914 return lastLayer;
01915 }
01916 FEM_Ghost_Layer *curLayer(void) {
01917 if (lastLayer==0) CkAbort("Must call FEM_Add_ghost_layer before FEM_Add_ghost_elem\n");
01918 return lastLayer;
01919 }
01920
01921
01922 void addGhostStencil(FEM_Ghost_Stencil *s) {
01923 regions.push_back(s);
01924 lastLayer=0;
01925 }
01926 void markGhostStencilLayer(void) {
01927 regions.push_back(FEM_Ghost_Region());
01928 }
01929
01930
01931 int getRegions(void) const {return regions.size();}
01932 const FEM_Ghost_Region &getRegion(int regNo) const {return regions[regNo];}
01933
01934
01935 void setSymmetries(int nNodes_,int *new_can,const int *sym_src);
01936 void addLinearPeriodic(int nFaces_,int nPer,
01937 const int *facesA,const int *facesB,int idxBase,
01938 int nNodes_,const CkVector3d *nodeLocs);
01939 const int *getCanon(void) const;
01940 const FEM_Symmetries_t *getSymmetries(void) const;
01941 const FEM_Sym_List &getSymList(void) const;
01942
01943
01944 };
01945
01946 FEM_Partition &FEM_curPartition(void);
01947
01948
01949 #define FEMAPI(routineName) TCHARM_API_TRACE(routineName,"fem")
01950
01951
01952
01953
01954
01955
01956
01957
01958 void FEM_Mesh_partition(const FEM_Mesh *mesh,int nchunks,int *elem2chunk, bool faceGraph=false);
01959
01960
01961
01962
01963
01964 class FEM_Mesh_Output {
01965 public:
01966 virtual ~FEM_Mesh_Output() {}
01967
01968 virtual void accept(int chunkNo,FEM_Mesh *msg) =0;
01969 };
01970
01971
01972
01973
01974 void FEM_Mesh_split(FEM_Mesh *mesh,int nchunks,
01975 const FEM_Partition &partition,FEM_Mesh_Output *out);
01976
01977
01978
01979 int *CkCopyArray(const int *src,int len,int indexBase);
01980
01981
01992
01993 class FEM_ElemAdj_Layer : public CkNoncopyable {
01994 public:
01995 int initialized;
01996 int nodesPerTuple;
01997
01998 class elemAdjInfo {
01999 public:
02000
02001 int tuplesPerElem;
02002 intArrayPtr elem2tuple;
02003 elemAdjInfo(void) {tuplesPerElem=0;}
02004 ~elemAdjInfo(void) {}
02005 void pup(PUP::er &p) {
02006 }
02007 };
02008
02009 elemAdjInfo elem[FEM_MAX_ELTYPE];
02010
02011 FEM_ElemAdj_Layer() {initialized=0;}
02012
02013 virtual void pup(PUP::er &p){
02014 p | initialized;
02015 p | nodesPerTuple;
02016
02017 CkPrintf("Calling inefficient FEM_ElemAdj_Layer::pup method\n");
02018
02019 for(int i=0;i<FEM_MAX_ELTYPE;i++){
02020 p | elem[i].tuplesPerElem;
02021 if(elem[i].tuplesPerElem == 0){
02022 continue;
02023 }
02024 int *arr;
02025 if(p.isUnpacking()){
02026 arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
02027 }else{
02028 arr = elem[i].elem2tuple;
02029 }
02030 p(arr,nodesPerTuple*elem[i].tuplesPerElem);
02031 if(p.isUnpacking()){
02032 elem[i].elem2tuple = arr;
02033 }
02034 }
02035 }
02036 };
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056 #ifdef DEBUG
02057 #undef DEBUG
02058 #endif
02059 #ifdef PARALLEL_DEBUG
02060 #define DEBUG(x) x
02061 #else
02062 #define DEBUG(x)
02063 #endif
02064
02065 #define MESH_CHUNK_TAG 3000
02066 #define MAX_SHARED_PER_NODE 20
02067
02068 template <class T, bool PUP_EVERY_ELEMENT=true >
02069 class DefaultListEntry {
02070 public:
02071 template<typename U>
02072 static inline void accumulate(T& a, const U& b) { a += b; }
02073
02074 static inline T getIdentity() { return T(); }
02075 static inline bool pupEveryElement(){ return PUP_EVERY_ELEMENT; }
02076 };
02077
02078 extern double elemlistaccTime;
02079
02080 template <class T>
02081 class ElemList{
02082 public:
02083 CkVec<T> *vec;
02084 ElemList(){
02085 vec = new CkVec<T>();
02086 }
02087 ~ElemList(){
02088 delete vec;
02089 }
02090 ElemList(const ElemList &rhs){
02091 vec = new CkVec<T>();
02092 *this=rhs;
02093 }
02094 inline ElemList& operator=(const ElemList& rhs){
02095
02096 *vec = *(rhs.vec);
02097 return *this;
02098 }
02099 inline ElemList& operator+=(const ElemList& rhs){
02100
02101
02102
02103 double _start = CkWallTimer();
02104 for(int i=0;i<rhs.vec->length();i++){
02105 vec->push_back((*(rhs.vec))[i]);
02106 }
02107
02108 elemlistaccTime += (CkWallTimer() - _start);
02109 return *this;
02110 }
02111 ElemList(const T &val){
02112 vec =new CkVec<T>();
02113 vec->push_back(val);
02114 };
02115 inline virtual void pup(PUP::er &p){
02116 if(p.isUnpacking()){
02117 vec = new CkVec<T>();
02118 }
02119 pupCkVec(p,*vec);
02120 }
02121 };
02122 template <class T>
02123 class UniqElemList: public ElemList<T>{
02124 public:
02125 UniqElemList(const T &val):ElemList<T>(val){};
02126 UniqElemList():ElemList<T>(){};
02127 inline void uniquify(){
02128 CkVec<T> *lvec = this->vec;
02129 lvec->quickSort(8);
02130 if(lvec->length() != 0){
02131 int count=0;
02132 for(int i=1;i<lvec->length();i++){
02133 if((*lvec)[count] == (*lvec)[i]){
02134 }else{
02135 count++;
02136 if(i != count){
02137 (*lvec)[count] = (*lvec)[i];
02138 }
02139 }
02140 }
02141 lvec->resize(count+1);
02142 }
02143 }
02144 };
02145
02146 class NodeElem {
02147 public:
02148
02149 int global;
02150
02151
02152
02153
02154 int numShared;
02155
02156
02157
02158
02159 int shared[MAX_SHARED_PER_NODE];
02160
02161 NodeElem(){
02162 global = -1;
02163 numShared = 0;
02164
02165 }
02166 NodeElem(int g_,int num_){
02167 global = g_; numShared= num_;
02168
02169
02170
02171
02172
02173 if(numShared > MAX_SHARED_PER_NODE){
02174 CkAbort("In Parallel partition the max number of chunks per node exceeds limit\n");
02175 }
02176 }
02177 NodeElem(int g_){
02178 global = g_;
02179 numShared = 0;
02180
02181 }
02182 NodeElem(const NodeElem &rhs){
02183
02184 *this = rhs;
02185 }
02186 inline NodeElem& operator=(const NodeElem &rhs){
02187 global = rhs.global;
02188 numShared = rhs.numShared;
02189
02190
02191
02192
02193 memcpy(&shared[0],&((rhs.shared)[0]),numShared*sizeof(int));
02194 return *this;
02195 }
02196
02197 inline bool operator == (const NodeElem &rhs){
02198 if(global == rhs.global){
02199 return true;
02200 }else{
02201 return false;
02202 }
02203 }
02204 inline bool operator >=(const NodeElem &rhs){
02205 return (global >= rhs.global);
02206 }
02207
02208 inline bool operator <=(const NodeElem &rhs){
02209 return (global <= rhs.global);
02210 }
02211
02212 virtual void pup(PUP::er &p){
02213 p | global;
02214 p | numShared;
02215
02216
02217
02218
02219
02220
02221
02222 p(shared,numShared);
02223 }
02224 ~NodeElem(){
02225
02226
02227
02228 }
02229 };
02230
02238 class MeshElem{
02239 public:
02240 FEM_Mesh *m;
02241 CkVec<int> gedgechunk;
02242 MeshElem(){
02243 m = new FEM_Mesh;
02244 }
02245 MeshElem(int dummy){
02246 m = new FEM_Mesh;
02247 }
02248 ~MeshElem(){
02249 delete m;
02250 }
02251 MeshElem(const MeshElem &rhs){
02252 m = NULL;
02253 *this = rhs;
02254 }
02255 inline MeshElem& operator=(const MeshElem &rhs){
02256 if(m != NULL){
02257 delete m;
02258 }
02259 m = new FEM_Mesh;
02260 m->copyShape(*(rhs.m));
02261 (*this) += rhs;
02262
02263 return *this;
02264 }
02265 inline MeshElem& operator+=(const MeshElem &rhs){
02266 int oldel = m->nElems();
02267 m->copyShape(*(rhs.m));
02268 for(int i=0;i<rhs.m->node.size();i++){
02269 m->node.push_back((rhs.m)->node,i);
02270 }
02271 if((rhs.m)->elem.size()>0){
02272 for(int t=0;t<(rhs.m)->elem.size();t++){
02273 if((rhs.m)->elem.has(t)){
02274 for(int e=0;e<(rhs.m)->elem.get(t).size();e++){
02275 m->elem[t].push_back((rhs.m)->elem.get(t),e);
02276 }
02277 }
02278 }
02279 }
02280
02281 return *this;
02282 }
02283 virtual void pup(PUP::er &p){
02284 if(p.isUnpacking()){
02285 m = new FEM_Mesh;
02286 }
02287 m->pup(p);
02288 }
02289
02290 struct ElemInfo {
02291 FEM_Mesh* m;
02292 int index;
02293 int elemType;
02294 ElemInfo(FEM_Mesh* _m, int _index, int _elemType)
02295 : m(_m), index(_index), elemType(_elemType) {}
02296 };
02297
02298 MeshElem& operator+=(const ElemInfo& rhs) {
02299 m->elem[rhs.elemType].copyShape(rhs.m->elem[rhs.elemType]);
02300 m->elem[rhs.elemType].push_back(rhs.m->elem[rhs.elemType], rhs.index);
02301 return *this;
02302 }
02303
02304 struct NodeInfo {
02305 FEM_Mesh* m;
02306 int index;
02307 NodeInfo(FEM_Mesh* _m, int _index)
02308 : m(_m), index(_index) {}
02309 };
02310
02311 MeshElem& operator+=(const NodeInfo& rhs) {
02312 m->node.copyShape(rhs.m->node);
02313 m->node.push_back(rhs.m->node, rhs.index);
02314 return *this;
02315 }
02316 };
02317
02318
02319 class Hashnode{
02320 public:
02321 class tupledata{
02322 public:
02323 enum {MAX_TUPLE = 8};
02324 int nodes[MAX_TUPLE];
02325 tupledata(int _nodes[MAX_TUPLE]){
02326 memcpy(nodes,_nodes,sizeof(int)*MAX_TUPLE);
02327 }
02328 tupledata(tupledata &rhs){
02329 memcpy(nodes,rhs.nodes,sizeof(int)*MAX_TUPLE);
02330 }
02331 tupledata(const tupledata &rhs){
02332 memcpy(nodes,rhs.nodes,sizeof(int)*MAX_TUPLE);
02333 }
02334 tupledata(){};
02335
02336 char *toString(int numnodes,char *str){
02337 str[0]='\0';
02338 for(int i=0;i<numnodes;i++){
02339 sprintf(&str[strlen(str)],"%d ",nodes[i]);
02340 }
02341 return str;
02342 }
02343 inline int &operator[](int i){
02344 return nodes[i];
02345 }
02346 inline const int &operator[](int i) const {
02347 return nodes[i];
02348 }
02349 virtual void pup(PUP::er &p){
02350 p(nodes,MAX_TUPLE);
02351 }
02352 };
02353 int numnodes;
02354
02355 tupledata nodes;
02356 int chunk;
02357 int elementNo;
02358 Hashnode(){
02359 numnodes=0;
02360 };
02361 Hashnode(int _num,int _chunk,int _elNo,int _nodes[tupledata::MAX_TUPLE]): nodes(_nodes){
02362 numnodes = _num;
02363 chunk = _chunk;
02364 elementNo = _elNo;
02365 }
02366 Hashnode(const Hashnode &rhs){
02367 *this = rhs;
02368 }
02369 inline Hashnode &operator=(const Hashnode &rhs){
02370 numnodes = rhs.numnodes;
02371 for(int i=0;i<numnodes;i++){
02372 nodes[i] = rhs.nodes[i];
02373 }
02374 chunk = rhs.chunk;
02375 elementNo = rhs.elementNo;
02376 return *this;
02377 }
02378 inline bool operator==(const Hashnode &rhs){
02379 if(numnodes != rhs.numnodes){
02380 return false;
02381 }
02382 for(int i=0;i<numnodes;i++){
02383 if(nodes[i] != rhs.nodes[i]){
02384 return false;
02385 }
02386 }
02387 if(chunk != rhs.chunk){
02388 return false;
02389 }
02390 if(elementNo != rhs.elementNo){
02391 return false;
02392 }
02393 return true;
02394 }
02395 inline bool operator>=(const Hashnode &rhs){
02396 if(numnodes < rhs.numnodes){
02397 return false;
02398 };
02399 if(numnodes > rhs.numnodes){
02400 return true;
02401 }
02402
02403 for(int i=0;i<numnodes;i++){
02404 if(nodes[i] < rhs.nodes[i]){
02405 return false;
02406 }
02407 if(nodes[i] > rhs.nodes[i]){
02408 return true;
02409 }
02410 }
02411 if(chunk < rhs.chunk){
02412 return false;
02413 }
02414 if(chunk > rhs.chunk){
02415 return true;
02416 }
02417 if(elementNo < rhs.elementNo){
02418 return false;
02419 }
02420 if(elementNo > rhs.elementNo){
02421 return true;
02422 }
02423 return true;
02424 }
02425
02426 inline bool operator<=(const Hashnode &rhs){
02427 if(numnodes < rhs.numnodes){
02428 return true;
02429 };
02430 if(numnodes > rhs.numnodes){
02431 return false;
02432 }
02433
02434 for(int i=0;i<numnodes;i++){
02435 if(nodes[i] < rhs.nodes[i]){
02436 return true;
02437 }
02438 if(nodes[i] > rhs.nodes[i]){
02439 return false;
02440 }
02441 }
02442 if(chunk < rhs.chunk){
02443 return true;
02444 }
02445 if(chunk > rhs.chunk){
02446 return false;
02447 }
02448 if(elementNo < rhs.elementNo){
02449 return true;
02450 }
02451 if(elementNo > rhs.elementNo){
02452 return false;
02453 }
02454 return true;
02455 }
02456
02457 inline bool equals(tupledata &tuple){
02458 for(int i=0;i<numnodes;i++){
02459 if(tuple.nodes[i] != nodes[i]){
02460 return false;
02461 }
02462 }
02463 return true;
02464 }
02465 virtual void pup(PUP::er &p){
02466 p | numnodes;
02467 p | nodes;
02468 p | chunk;
02469 p | elementNo;
02470 }
02471 };
02472
02473 typedef MSA::MSA2D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
02474
02475 typedef MSA::MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINT;
02476
02477 typedef UniqElemList<int> IntList;
02478 typedef MSA::MSA1D<IntList, DefaultListEntry<IntList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINTLIST;
02479
02480 typedef UniqElemList<NodeElem> NodeList;
02481 typedef MSA::MSA1D<NodeList, DefaultListEntry<NodeList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DNODELIST;
02482
02483 typedef MSA::MSA1D<MeshElem,DefaultEntry<MeshElem,true>,1> MSA1DFEMMESH;
02484
02485
02486
02487 struct conndata{
02488 int nelem;
02489 int nnode;
02490 MSA1DINT arr1;
02491 MSA1DINT arr2;
02492
02493 void pup(PUP::er &p){
02494 p|nelem;
02495 p|nnode;
02496 arr1.pup(p);
02497 arr2.pup(p);
02498 }
02499 };
02500
02505 struct partconndata{
02506 int nelem;
02507 int startindex;
02508 int *eptr,*eind;
02509 int *part;
02510 ~partconndata(){
02511 delete [] eptr;
02512 delete [] eind;
02513 delete [] part;
02514 };
02515 };
02516
02520 struct ghostdata{
02521 int numLayers;
02522 FEM_Ghost_Layer **layers;
02523 void pup(PUP::er &p){
02524 p | numLayers;
02525 if(p.isUnpacking()){
02526 layers = new FEM_Ghost_Layer *[numLayers];
02527 for(int i=0;i<numLayers;i++){
02528 layers[i] = new FEM_Ghost_Layer;
02529 }
02530
02531 }
02532 for(int i=0;i<numLayers;i++){
02533 layers[i]->pup(p);
02534 }
02535 }
02536 ~ghostdata(){
02537
02538 for(int i=0;i<numLayers;i++){
02539 delete layers[i];
02540 }
02541 delete [] layers;
02542 };
02543 };
02544
02545
02546
02547
02548 int FEM_master_parallel_part(int ,int ,FEM_Comm_t);
02549 int FEM_slave_parallel_part(int ,int ,FEM_Comm_t);
02550 struct partconndata* FEM_call_parmetis(int nelem, MSA1DINT::Read &rPtr, MSA1DINT::Read &rInd, FEM_Comm_t comm_context);
02551 void FEM_write_nodepart(MSA1DINTLIST::Accum &nodepart, struct partconndata *data, MPI_Comm comm_context);
02552 void FEM_write_part2node(MSA1DINTLIST::Read &nodepart, MSA1DNODELIST::Accum &part2node, struct partconndata *data, MPI_Comm comm_context);
02553 void FEM_write_part2elem(MSA1DINTLIST::Accum &part2elem, struct partconndata *data, MPI_Comm comm_context);
02554 FEM_Mesh * FEM_break_mesh(FEM_Mesh *m,int numElements,int numChunks);
02555 void sendBrokenMeshes(FEM_Mesh *mesh_array,FEM_Comm_t comm_context);
02556 void FEM_write_part2mesh(MSA1DFEMMESH::Accum &part2mesh, struct partconndata *partdata, struct conndata *data, MSA1DINTLIST::Read &nodepart, int numChunks, int myChunk, FEM_Mesh *mypiece);
02557 void addIDXLists(FEM_Mesh *m,NodeList &lnodes,int myChunk);
02558 struct ghostdata *gatherGhosts();
02559 void makeGhosts(FEM_Mesh *m,MPI_Comm comm,int masterRank,int numLayers,FEM_Ghost_Layer **layers);
02560 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);
02561 bool sharedWith(int lnode,int chunk,FEM_Mesh *m);
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576 static FEM_Symmetries_t noSymmetries=(FEM_Symmetries_t)0;
02577
02578
02579 CkHashCode CkHashFunction_ints(const void *keyData,size_t keyLen);
02580 int CkHashCompare_ints(const void *k1,const void *k2,size_t keyLen);
02581 extern "C" int ck_fem_map_compare_int(const void *a, const void *b);
02582
02583
02584
02585 class elemList {
02586 public:
02587 int chunk;
02588 int tupleNo;
02589 int localNo;
02590 int type;
02591 FEM_Symmetries_t sym;
02592 elemList *next;
02593
02594 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_)
02595 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_)
02596 { next=NULL; }
02597 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_,int tupleNo_)
02598 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_) , tupleNo(tupleNo_)
02599 { next=NULL; }
02600
02601 ~elemList() {if (next) delete next;}
02602 void setNext(elemList *n) {next=n;}
02603 };
02604
02605
02606
02607 class tupleTable : public CkHashtable {
02608 int tupleLen;
02609 CkHashtableIterator *it;
02610 static int roundUp(int val,int to) {
02611 return ((val+to-1)/to)*to;
02612 }
02613 static CkHashtableLayout makeLayout(int tupleLen) {
02614 int ks=tupleLen*sizeof(int);
02615 int oo=roundUp(ks+sizeof(char),sizeof(void *));
02616 int os=sizeof(elemList *);
02617 return CkHashtableLayout(ks,ks,oo,os,oo+os);
02618 }
02619
02620
02621
02622
02623 void canonicalize(const int *tuple,int *can)
02624 {
02625 switch(tupleLen) {
02626 case 1:
02627 can[0]=tuple[0]; break;
02628 case 2:
02629 if (tuple[0]<tuple[1])
02630 {can[0]=tuple[0]; can[1]=tuple[1];}
02631 else
02632 {can[0]=tuple[1]; can[1]=tuple[0];}
02633 break;
02634 default:
02635 memcpy(can,tuple,tupleLen*sizeof(int));
02636 qsort(can,tupleLen,sizeof(int),ck_fem_map_compare_int);
02637 };
02638 }
02639 public:
02640 enum {MAX_TUPLE=8};
02641
02642 tupleTable(int tupleLen_)
02643 :CkHashtable(makeLayout(tupleLen_),
02644 137,0.5,
02645 CkHashFunction_ints,
02646 CkHashCompare_ints)
02647 {
02648 tupleLen=tupleLen_;
02649 if (tupleLen>MAX_TUPLE) CkAbort("Cannot have that many shared nodes!\n");
02650 it=NULL;
02651 }
02652 ~tupleTable() {
02653 beginLookup();
02654 elemList *doomed;
02655 while (NULL!=(doomed=(elemList *)lookupNext()))
02656 delete doomed;
02657 }
02658
02659 elemList **lookupTuple(const int *tuple) {
02660 int can[MAX_TUPLE];
02661 canonicalize(tuple,can);
02662 return (elemList **)get(can);
02663 }
02664
02665
02666 void addTuple(const int *tuple,elemList *nu)
02667 {
02668 int can[MAX_TUPLE];
02669 canonicalize(tuple,can);
02670
02671 elemList **dest=(elemList **)get(can);
02672 if (dest!=NULL)
02673 {
02674 nu->setNext(*dest);
02675 } else {
02676 dest=(elemList **)put(can);
02677 }
02678 *dest=nu;
02679 }
02680
02681 void beginLookup(void) {
02682 it=iterator();
02683 }
02684 elemList *lookupNext(void) {
02685 void *ret=it->next();
02686 if (ret==NULL) {
02687 delete it;
02688 return NULL;
02689 }
02690 return *(elemList **)ret;
02691 }
02692 };
02693
02694
02695
02696
02697
02698
02699
02700
02701 class chunkList : public CkNoncopyable {
02702 public:
02703 int chunk;
02704 int localNo;
02705 FEM_Symmetries_t sym;
02706 int layerNo;
02707 chunkList *next;
02708 chunkList() {chunk=-1;next=NULL;}
02709 chunkList(int chunk_,int localNo_,FEM_Symmetries_t sym_,int ln_=-1) {
02710 chunk=chunk_;
02711 localNo=localNo_;
02712 sym=sym_;
02713 layerNo=ln_;
02714 next=NULL;
02715 }
02716 ~chunkList() {delete next;}
02717 void set(int c,int l,FEM_Symmetries_t s,int ln) {
02718 chunk=c; localNo=l; sym=s; layerNo=ln;
02719 }
02720
02721
02722 bool addchunk(int c,int l,FEM_Symmetries_t s,int ln) {
02723
02724
02725 if (chunk==c && sym==s) return false;
02726 if (chunk==-1) {set(c,l,s,ln);return true;}
02727 if (next==NULL) {next=new chunkList(c,l,s,ln);return true;}
02728 else return next->addchunk(c,l,s,ln);
02729 }
02730
02731 int localOnChunk(int c,FEM_Symmetries_t s) const {
02732 const chunkList *l=onChunk(c,s);
02733 if (l==NULL) return -1;
02734 else return l->localNo;
02735 }
02736 const chunkList *onChunk(int c,FEM_Symmetries_t s) const {
02737 if (chunk==c && sym==s) return this;
02738 else if (next==NULL) return NULL;
02739 else return next->onChunk(c,s);
02740 }
02741 int isEmpty(void) const
02742 {return (chunk==-1);}
02743 int isShared(void) const
02744 {return next!=NULL;}
02745 int isGhost(void) const
02746 {return FEM_Is_ghost_index(localNo); }
02747 int length(void) const {
02748 if (next==NULL) return isEmpty()?0:1;
02749 else return 1+next->length();
02750 }
02751 chunkList &operator[](int i) {
02752 if (i==0) return *this;
02753 else return (*next)[i-1];
02754 }
02755 };
02756
02757
02758
02759
02760
02761 #include "ParFUM_locking.h"
02762
02763
02764
02765
02766
02768 class FEM_MUtil {
02770 int idx;
02772 femMeshModify *mmod;
02774 class tuple {
02775 public:
02777 int oldIdx;
02779 int newIdx;
02781 tuple() {
02782 oldIdx = -1;
02783 newIdx = -1;
02784 }
02786 tuple(int o, int n) {
02787 oldIdx = o;
02788 newIdx = n;
02789 }
02790 };
02792 CkVec<tuple> outStandingMappings;
02793
02794 public:
02796 FEM_MUtil() {}
02798 FEM_MUtil(int i, femMeshModify *m);
02800 FEM_MUtil(femMeshModify *m);
02802 ~FEM_MUtil();
02804 void pup(PUP::er &p) {
02805 p|idx;
02806 }
02808 int getIdx() { return idx; }
02810 int getRemoteIdx(FEM_Mesh *m, int elementid, int elemtype);
02812 bool isShared(int index);
02814 int exists_in_IDXL(FEM_Mesh *m, int localIdx, int chk, int type, int elemType=0);
02816 int lookup_in_IDXL(FEM_Mesh *m, int sharedIdx, int fromChk, int type, int elemType=0);
02817
02819
02823 void getChunkNos(int entType, int entNo, int *numChunks, IDXL_Share ***chunks, int elemType=0);
02825 void buildChunkToNodeTable(int *nodetype, int sharedcount, int ghostcount, int localcount, int *conn, int connSize, CkVec<int> ***allShared, int *numSharedChunks, CkVec<int> **allChunks, int ***sharedConn);
02827 chunkListMsg *getChunksSharingGhostNodeRemote(FEM_Mesh *m, int chk, int sharedIdx);
02828
02830 void splitEntityAll(FEM_Mesh *m, int localIdx, int nBetween, int *between);
02832 void splitEntitySharing(FEM_Mesh *m, int localIdx, int nBetween, int *between, int numChunks, int *chunks);
02834 void splitEntityRemote(FEM_Mesh *m, int chk, int localIdx, int nBetween, int *between);
02835
02837 void removeNodeAll(FEM_Mesh *m, int localIdx);
02839 void removeNodeRemote(FEM_Mesh *m, int chk, int sharedIdx);
02841 void removeGhostNodeRemote(FEM_Mesh *m, int fromChk, int sharedIdx);
02842
02844 int addElemRemote(FEM_Mesh *m, int chk, int elemtype, int connSize, int *conn, int numGhostIndex, int *ghostIndices);
02846 void addGhostElementRemote(FEM_Mesh *m, int chk, int elemType, int *indices, int *typeOfIndex, int connSize);
02848 void removeElemRemote(FEM_Mesh *m, int chk, int elementid, int elemtype, int permanent, bool aggressive_node_removal=false);
02850 void removeGhostElementRemote(FEM_Mesh *m, int chk, int elementid, int elemtype, int numGhostIndex, int *ghostIndices, int numGhostRNIndex, int *ghostRNIndices, int numGhostREIndex, int *ghostREIndices, int numSharedIndex, int *sharedIndices);
02851
02853 int Replace_node_local(FEM_Mesh *m, int oldIdx, int newIdx);
02855 void addToSharedList(FEM_Mesh *m, int fromChk, int sharedIdx);
02857 int eatIntoElement(int localIdx, bool aggressive_node_removal=false);
02858
02860 bool knowsAbtNode(int chk, int nodeId);
02862 void UpdateGhostSend(int nodeId, int *chunkl, int numchunkl);
02864 void findGhostSend(int nodeId, int *&chunkl, int &numchunkl);
02865
02867 void copyElemData(int etype, int elemid, int newEl);
02869 void packEntData(char **data, int *size, int *cnt, int localIdx, bool isnode, int elemType);
02871 void updateAttrs(char *data, int size, int newIndex, bool isnode, int elemType);
02872
02874 int getLockOwner(int nodeId);
02875
02877 void idxllock(FEM_Mesh *m, int chk, int type);
02879 void idxlunlock(FEM_Mesh *m, int chk, int type);
02881 void idxllockLocal(FEM_Mesh *m, int toChk, int type);
02883 void idxlunlockLocal(FEM_Mesh *m, int toChk, int type);
02884
02886 void FEM_Print_n2n(FEM_Mesh *m, int nodeid);
02888 void FEM_Print_n2e(FEM_Mesh *m, int nodeid);
02890 void FEM_Print_e2n(FEM_Mesh *m, int eid);
02892 void FEM_Print_e2e(FEM_Mesh *m, int eid);
02894 void FEM_Print_coords(FEM_Mesh *m, int nodeid);
02895
02897 void StructureTest(FEM_Mesh *m);
02899 int AreaTest(FEM_Mesh *m);
02901 int IdxlListTest(FEM_Mesh *m);
02903 void verifyIdxlListRemote(FEM_Mesh *m, int fromChk, int fsize, int type);
02905 int residualLockTest(FEM_Mesh *m);
02907 void unlockAll(FEM_Mesh* m);
02908 };
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919 #include "ParFUM_Mesh_Modify.h"
02920
02921 #include "ParFUM_Adapt_Algs.h"
02922
02923 #include "ParFUM_Adapt.h"
02924
02925 #include "ParFUM_Interpolate.h"
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943 #ifndef __OSL_VECTOR_2D_H
02944 #define __OSL_VECTOR_2D_H
02945
02946 #include <math.h>
02947
02948 typedef double Real;
02949
02950
02951 class vector2d {
02952 public:
02953 Real x,y;
02954 vector2d(void) {}
02955
02956 explicit vector2d(const Real init) {x=y=init;}
02957
02958 explicit vector2d(int init) {x=y=init;}
02959
02960 vector2d(const Real Nx,const Real Ny) {x=Nx;y=Ny;}
02961
02962 vector2d(const vector2d ©) {x=copy.x;y=copy.y;}
02963
02964
02965 operator Real *() {return &x;}
02966 operator const Real *() const {return &x;}
02967
02968
02969
02970
02971
02972
02973
02974
02975 vector2d &operator=(const vector2d &b) {x=b.x;y=b.y;return *this;}
02976 int operator==(const vector2d &b) const {return (x==b.x)&&(y==b.y);}
02977 int operator!=(const vector2d &b) const {return (x!=b.x)||(y!=b.y);}
02978 vector2d operator+(const vector2d &b) const {return vector2d(x+b.x,y+b.y);}
02979 vector2d operator-(const vector2d &b) const {return vector2d(x-b.x,y-b.y);}
02980 vector2d operator*(const Real scale) const
02981 {return vector2d(x*scale,y*scale);}
02982 friend vector2d operator*(const Real scale,const vector2d &v)
02983 {return vector2d(v.x*scale,v.y*scale);}
02984 vector2d operator/(const Real &div) const
02985 {Real scale=1.0/div;return vector2d(x*scale,y*scale);}
02986 vector2d operator-(void) const {return vector2d(-x,-y);}
02987 void operator+=(const vector2d &b) {x+=b.x;y+=b.y;}
02988 void operator-=(const vector2d &b) {x-=b.x;y-=b.y;}
02989 void operator*=(const Real scale) {x*=scale;y*=scale;}
02990 void operator/=(const Real div) {Real scale=1.0/div;x*=scale;y*=scale;}
02991
02992
02993
02994 Real magSqr(void) const {return x*x+y*y;}
02995
02996 Real mag(void) const {return sqrt(magSqr());}
02997
02998
02999 Real distSqr(const vector2d &b) const
03000 {return (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y);}
03001
03002 Real dist(const vector2d &b) const {return sqrt(distSqr(b));}
03003
03004
03005 Real dot(const vector2d &b) const {return x*b.x+y*b.y;}
03006
03007 Real cosAng(const vector2d &b) const {return dot(b)/(mag()*b.mag());}
03008
03009
03010 vector2d dir(void) const {return (*this)/mag();}
03011
03012
03013 vector2d perp(void) const {return vector2d(-y,x);}
03014
03015
03016 vector2d &scale(const vector2d &b) {x*=b.x;y*=b.y;return *this;}
03017
03018
03019 Real max(void) {return (x>y)?x:y;}
03020
03021
03022 void enlarge(const vector2d &by)
03023 {if (by.x>x) x=by.x; if (by.y>y) y=by.y;}
03024 };
03025
03026 #endif //__OSL_VECTOR2D_H
03027
03028
03029
03030
03031
03032
03033 #ifndef CMK_THRESHOLD_TIMER
03034 #define CMK_THRESHOLD_TIMER
03035
03060 class CkThresholdTimer {
03061 double threshold;
03062 double lastStart;
03063 const char *lastWhat;
03064
03065 void start_(const char *what) {
03066 lastStart=CmiWallTimer();
03067 lastWhat=what;
03068 }
03069 void done_(void) {
03070 double elapsed=CmiWallTimer()-lastStart;
03071 if (elapsed>threshold) {
03072 CmiPrintf("%s took %.2f s\n",lastWhat,elapsed);
03073 }
03074 }
03075 public:
03076 CkThresholdTimer(const char *what,double thresh=0.001)
03077 :threshold(thresh) { start_(what); }
03078 void start(const char *what) { done_(); start_(what); }
03079 ~CkThresholdTimer() {done_();}
03080 };
03081
03082 #endif
03083
03084
03085 #include "adapt_adj.h"
03086
03087 #endif
03088
03089