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 "msa/msa.h"
00042 #include "cklists.h"
00043 #include "pup.h"
00044 #include "ParFUM.h"
00045 #include "ElemList.h"
00046 #include "MsaHashtable.h"
00047
00048 #include <iosfwd>
00049
00050 #include "ParFUM_Adapt.decl.h"
00051
00052 #if defined(_WIN32)
00053 #include <iterator>
00054 #endif
00055
00056 #if ! CMK_HAS_STD_INSERTER
00057 #include <list>
00058 namespace std {
00059 template<class Container, class Iterator>
00060 insert_iterator<Container> inserter(
00061 Container& _Cont,
00062 Iterator _It
00063 );
00064 };
00065 #endif
00066
00067 #if defined(_WIN32) && defined(max)
00068 #undef max
00069 #endif
00070
00071
00072 extern CProxy_femMeshModify meshMod;
00073
00074 #define MAX_CHUNK 1000000000
00075
00076
00077 #define FEM_SILENT
00078
00079
00080 CtvExtern(FEM_Adapt_Algs *, _adaptAlgs);
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 typedef IDXL_Side FEM_Comm;
00094 typedef IDXL_List FEM_Comm_List;
00095 typedef IDXL_Rec FEM_Comm_Rec;
00096
00101 class FEM_Comm_Holder {
00102 IDXL comm;
00103 bool registered;
00104 IDXL_Comm_t idx;
00105 void registerIdx(IDXL_Chunk *c);
00106 public:
00107 FEM_Comm_Holder(FEM_Comm *sendComm, FEM_Comm *recvComm);
00108 void pup(PUP::er &p);
00109 ~FEM_Comm_Holder(void);
00110
00112 inline IDXL_Comm_t getIndex(IDXL_Chunk *c) {
00113 if (idx==-1) registerIdx(c);
00114 return idx;
00115 }
00116 };
00117
00118
00119
00123 typedef unsigned char FEM_Symmetries_t;
00124
00125
00127 class FEM_Sym_Desc : public PUP::able {
00128 public:
00129 virtual ~FEM_Sym_Desc();
00130
00132 virtual CkVector3d applyLoc(const CkVector3d &loc) const =0;
00133
00135 virtual CkVector3d applyVec(const CkVector3d &vec) const =0;
00136
00138 friend inline void operator|(PUP::er &p,FEM_Sym_Desc &a) {a.pup(p);}
00139 friend inline void operator|(PUP::er &p,FEM_Sym_Desc* &a) {
00140 PUP::able *pa=a; p(&pa); a=(FEM_Sym_Desc *)pa;
00141 }
00142 };
00143
00145 class FEM_Sym_Linear : public FEM_Sym_Desc {
00146 CkVector3d shift;
00147 public:
00148 FEM_Sym_Linear(const CkVector3d &shift_) :shift(shift_) {}
00149 FEM_Sym_Linear(CkMigrateMessage *m) {}
00150
00152 CkVector3d applyLoc(const CkVector3d &loc) const {return loc+shift;}
00153
00155 virtual CkVector3d applyVec(const CkVector3d &vec) const {return vec;}
00156
00157 virtual void pup(PUP::er &p);
00158 PUPable_decl(FEM_Sym_Linear);
00159 };
00160
00165 class FEM_Sym_List {
00166
00167 CkPupAblePtrVec<FEM_Sym_Desc> sym;
00168
00169 FEM_Sym_List(const FEM_Sym_List &src);
00170 public:
00171 FEM_Sym_List();
00172 void operator=(const FEM_Sym_List &src);
00173 ~FEM_Sym_List();
00174
00177 FEM_Symmetries_t add(FEM_Sym_Desc *desc);
00178
00180 void applyLoc(CkVector3d *loc,FEM_Symmetries_t sym) const;
00181
00183 void applyVec(CkVector3d *vec,FEM_Symmetries_t sym) const;
00184
00185 void pup(PUP::er &p);
00186 };
00187
00189 template <class T>
00190 class BasicTable2d : public CkNoncopyable {
00191 protected:
00192 int rows;
00193 int cols;
00194 T *table;
00195 public:
00196 BasicTable2d(T *src,int cols_,int rows_)
00197 :rows(rows_), cols(cols_), table(src) {}
00198
00200 inline int size(void) const {return rows;}
00202 inline int width(void) const {return cols;}
00203
00204 T *getData(void) {return table;}
00205 const T *getData(void) const {return table;}
00206
00207
00208 T operator() (int r,int c) const {return table[c+r*cols];}
00209 T &operator() (int r,int c) {return table[c+r*cols];}
00210
00211
00213 inline T *getRow(int r) {return &table[r*cols];}
00215 inline const T *getRow(int r) const {return &table[r*cols];}
00216 inline void getRow(int r,T *dest,T idxBase=0) const {
00217 const T *src=getRow(r);
00218 for (int c=0;c<cols;c++) dest[c]=src[c]+idxBase;
00219 }
00220 inline T *operator[](int r) {return getRow(r);}
00221 inline const T *operator[](int r) const {return getRow(r);}
00222 inline void setRow(int r,const T *src,T idxBase=0) {
00223 T *dest=getRow(r);
00224 for (int c=0;c<cols;c++) dest[c]=src[c]-idxBase;
00225 }
00226 inline void setRow(int r,T value) {
00227 T *dest=getRow(r);
00228 for (int c=0;c<cols;c++) dest[c]=value;
00229 }
00230
00231
00232 void set(const T *src,T idxBase=0) {
00233 for (int r=0;r<rows;r++)
00234 for (int c=0;c<cols;c++)
00235 table[c+r*cols]=src[c+r*cols]-idxBase;
00236 }
00237 void setTranspose(const T *srcT,int idxBase=0) {
00238 for (int r=0;r<rows;r++)
00239 for (int c=0;c<cols;c++)
00240 table[c+r*cols]=srcT[r+c*rows]-idxBase;
00241 }
00242 void get(T *dest,T idxBase=0) const {
00243 for (int r=0;r<rows;r++)
00244 for (int c=0;c<cols;c++)
00245 dest[c+r*cols]=table[c+r*cols]+idxBase;
00246 }
00247 void getTranspose(T *destT,int idxBase=0) const {
00248 for (int r=0;r<rows;r++)
00249 for (int c=0;c<cols;c++)
00250 destT[r+c*rows]=table[c+r*cols]+idxBase;
00251 }
00252 void set(T value) {
00253 for (int r=0;r<rows;r++) setRow(r,value);
00254 }
00255 void setRowLen(int rows_) {
00256 rows = rows_;
00257 }
00258 };
00259
00261
00264 template <class T>
00265 class AllocTable2d : public BasicTable2d<T> {
00267 int max;
00269 T fill;
00271 T *allocTable;
00272 public:
00274 AllocTable2d(int cols_=0,int rows_=0,T fill_=0)
00275 :BasicTable2d<T>(NULL,cols_,rows_), max(0), fill(fill_)
00276 {
00277 allocTable = NULL;
00278 if (this->rows>0) allocate(this->rows);
00279 }
00281 ~AllocTable2d() {delete[] allocTable;}
00283 void allocate(int rows_) {
00284 allocate(this->width(),rows_);
00285 }
00287 void allocate(int cols_,int rows_,int max_=0) {
00288 if (cols_==this->cols && rows_<max) {
00289
00290 this->rows=rows_;
00291 return;
00292 }
00293 if (max_==0) {
00294 if (rows_==this->rows+1)
00295 max_=10+rows_+(rows_>>2);
00296 else
00297 max_=rows_;
00298 }
00299
00300 if(max_ < 60000)
00301 max_ = 60000;
00302
00303 if(max_ > 60000 && max_ < 290000)
00304 max_ = 300000;
00305
00306 int oldRows=this->rows;
00307 this->cols=cols_;
00308 this->rows=rows_;
00309 this->max=max_;
00310 this->table=new T[max*this->cols];
00311
00312 int copyRows=0;
00313 if (allocTable!=NULL) {
00314 copyRows=oldRows;
00315 if (copyRows>max) copyRows=max;
00316 memcpy(this->table,allocTable,sizeof(T)*this->cols*copyRows);
00317 delete[] allocTable;
00318 }else{
00319 for (int r=copyRows;r<max;r++)
00320 this->setRow(r,fill);
00321 }
00322 allocTable = this->table;
00323 }
00324
00326 void pup(PUP::er &p) {
00327 p|this->rows; p|this->cols;
00328 if (this->table==NULL) allocate(this->rows);
00329 p(this->table,this->rows*this->cols);
00330 }
00332 void pupSingle(PUP::er &p, int pupindx) {
00333 int startIdx = this->cols*pupindx;
00334 for(int i=0; i<this->cols; i++) {
00335 p|this->table[startIdx+i];
00336 }
00337 }
00338
00339 friend void operator|(PUP::er &p,AllocTable2d<T> &t) {t.pup(p);}
00340
00342 T *push_back(void) {
00343 if (this->rows>=max)
00344 {
00345 int newMax=max+(max/4)+16;
00346 allocate(this->cols,this->rows,newMax);
00347 }
00348 this->rows++;
00349 return getRow(this->rows-1);
00350 }
00351
00355 void register_data(T *user,int len,int max){
00356 if(allocTable != NULL){
00357 delete [] allocTable;
00358 allocTable = NULL;
00359 }
00360 this->table = user;
00361 this->rows = len;
00362 this->max = max;
00363 }
00364 };
00365
00369 CLINKAGE const char *FEM_Get_entity_name(int entity,char *storage);
00370
00374 CLINKAGE const char *FEM_Get_attr_name(int attr,char *storage);
00375
00376
00378
00382 class FEM_Attribute {
00384 FEM_Entity *e;
00386 FEM_Attribute *ghost;
00388 int attr;
00390 int width;
00392 int datatype;
00394 bool allocated;
00395
00397
00398 void bad(const char *field,bool forRead,int cur,int next,const char *caller) const;
00399
00400 protected:
00406 virtual void allocate(int length,int width,int datatype) =0;
00407 public:
00408 FEM_Attribute(FEM_Entity *owner_,int myAttr_);
00409 virtual void pup(PUP::er &p);
00410 virtual void pupSingle(PUP::er &p, int pupindx);
00411 virtual ~FEM_Attribute();
00412
00414 inline void setGhost(FEM_Attribute *ghost_) { ghost=ghost_;}
00415
00417 inline bool isGhost(void) const { return ghost!=NULL; }
00418
00420 inline int getAttr(void) const {return attr;}
00421
00422 inline FEM_Entity *getEntity(void) {return e;}
00423
00426 int getLength(void) const;
00427 int getRealLength(void) const;
00428
00429 int getMax();
00430
00432 inline int getWidth(void) const { return width<0?0:width; }
00433 inline int getRealWidth(void) const { return width; }
00434
00436 inline int getDatatype(void) const { return datatype; }
00437
00443 void setLength(int l,const char *caller="");
00444
00449 void setWidth(int w,const char *caller="");
00450
00455 void setDatatype(int dt,const char *caller="");
00456
00462 virtual void copyShape(const FEM_Attribute &src);
00463
00466 void tryAllocate(void);
00467
00469 inline void reallocate(void) { allocated=false; tryAllocate(); }
00470
00472 inline bool isAllocated(void) const {return allocated;}
00473
00482 virtual void set(const void *src, int firstItem,int length,
00483 const IDXL_Layout &layout, const char *caller);
00484
00494 virtual void get(void *dest, int firstItem,int length,
00495 const IDXL_Layout &layout, const char *caller) const;
00496
00498 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity) =0;
00499
00503 virtual void register_data(void *dest, int length,int max,
00504 const IDXL_Layout &layout, const char *caller);
00505
00506 };
00507 PUPmarshall(FEM_Attribute)
00508
00509
00510
00514 class FEM_DataAttribute : public FEM_Attribute {
00515 typedef FEM_Attribute super;
00517 AllocTable2d<unsigned char> *char_data;
00519 AllocTable2d<int> *int_data;
00521 AllocTable2d<float> *float_data;
00523 AllocTable2d<double> *double_data;
00524 protected:
00525 virtual void allocate(int length,int width,int datatype);
00526 public:
00527 FEM_DataAttribute(FEM_Entity *owner,int myAttr);
00528 virtual void pup(PUP::er &p);
00529 virtual void pupSingle(PUP::er &p, int pupindx);
00530 ~FEM_DataAttribute();
00531
00532 AllocTable2d<unsigned char> &getChar(void) {return *char_data;}
00533 const AllocTable2d<unsigned char> &getChar(void) const {return *char_data;}
00534
00535 AllocTable2d<int> &getInt(void) {return *int_data;}
00536 const AllocTable2d<int> &getInt(void) const {return *int_data;}
00537
00538 AllocTable2d<double> &getDouble(void) {return *double_data;}
00539 const AllocTable2d<double> &getDouble(void) const {return *double_data;}
00540
00541 AllocTable2d<float> &getFloat(void) {return *float_data;}
00542 const AllocTable2d<float> &getFloat(void) const {return *float_data;}
00543
00544
00545 virtual void set(const void *src, int firstItem,int length,
00546 const IDXL_Layout &layout, const char *caller);
00547
00548 virtual void get(void *dest, int firstItem,int length,
00549 const IDXL_Layout &layout, const char *caller) const;
00550
00551 virtual void register_data(void *dest, int length,int max,
00552 const IDXL_Layout &layout, const char *caller);
00553
00554
00556 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00557
00559
00561 void interpolate(int A,int B,int D,double frac);
00563
00565 void interpolate(int *iNodes,int rNode,int k);
00566 };
00567 PUPmarshall(FEM_DataAttribute)
00568
00569
00570
00574 class FEM_IndexAttribute : public FEM_Attribute {
00575 public:
00577 class Checker {
00578 public:
00579 virtual ~Checker();
00580
00585 virtual void check(int row,const BasicTable2d<int> &table,
00586 const char *caller) const =0;
00587 };
00588 private:
00589 typedef FEM_Attribute super;
00590 AllocTable2d<int> idx;
00592 Checker *checker;
00593 protected:
00594 virtual void allocate(int length,int width,int datatype);
00595 public:
00596 FEM_IndexAttribute(FEM_Entity *owner,int myAttr, Checker *checker_=NULL);
00597 virtual void pup(PUP::er &p);
00598 virtual void pupSingle(PUP::er &p, int pupindx);
00599 ~FEM_IndexAttribute();
00600
00601 AllocTable2d<int> &get(void) {return idx;}
00602 const AllocTable2d<int> &get(void) const {return idx;}
00603
00604 virtual void set(const void *src, int firstItem,int length,
00605 const IDXL_Layout &layout, const char *caller);
00606
00607 virtual void get(void *dest, int firstItem,int length,
00608 const IDXL_Layout &layout, const char *caller) const;
00609
00610 virtual void register_data(void *dest, int length, int max,
00611 const IDXL_Layout &layout, const char *caller);
00612
00614 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00615 };
00616 PUPmarshall(FEM_IndexAttribute)
00617
00618
00619
00625 class FEM_VarIndexAttribute : public FEM_Attribute{
00626
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 private:
00675 typedef FEM_Attribute super;
00676 CkVec<CkVec<ElemID> > idx;
00677 int oldlength;
00678 protected:
00679 virtual void allocate(int _length,int _width,int _datatype){
00680 if(_length > oldlength){
00681 setWidth(1,"allocate");
00682 oldlength = _length*2;
00683 idx.reserve(oldlength);
00684 for(int i=idx.size();i<oldlength;i++){
00685 CkVec<ElemID> tempVec;
00686 idx.insert(i,tempVec);
00687 }
00688 }
00689 };
00690 public:
00691 FEM_VarIndexAttribute(FEM_Entity *owner,int myAttr);
00692 ~FEM_VarIndexAttribute(){};
00693 virtual void pup(PUP::er &p);
00694 virtual void pupSingle(PUP::er &p, int pupindx);
00695 CkVec<CkVec<ElemID> > &get(){return idx;};
00696 const CkVec<CkVec<ElemID> > &get() const {return idx;};
00697
00698 virtual void set(const void *src,int firstItem,int length,
00699 const IDXL_Layout &layout,const char *caller);
00700
00701 virtual void get(void *dest, int firstItem,int length,
00702 const IDXL_Layout &layout, const char *caller) const;
00703
00704 virtual void copyEntity(int dstEntity,const FEM_Attribute &src,int srcEntity);
00705
00706 int findInRow(int row,const ElemID &data);
00707
00708 void print();
00709 };
00710
00712
00717 class FEM_Entity {
00719 typedef CkVec<FEM_Symmetries_t> sym_t;
00721 int length;
00723 int max;
00725 FEM_Mesh_alloc_fn resize;
00727 void *args;
00728
00739 CkVec<FEM_Attribute *> attributes;
00740
00746 FEM_DataAttribute *coord;
00747 void allocateCoord(void);
00748
00755 FEM_DataAttribute *sym;
00756 void allocateSym(void);
00757
00762 FEM_IndexAttribute *globalno;
00763 void allocateGlobalno(void);
00764
00769 FEM_DataAttribute *boundary;
00770 void allocateBoundary();
00771
00773
00775 FEM_DataAttribute *meshSizing;
00776 void allocateMeshSizing(void);
00777
00784 FEM_DataAttribute *valid;
00785 int first_invalid, last_invalid;
00791 int* invalidList;
00793 int invalidListLen;
00795 int invalidListAllLen;
00796
00797 protected:
00811 virtual void create(int attr,const char *caller);
00812
00817 void add(FEM_Attribute *attribute);
00818 public:
00819
00820 FEM_Entity *ghost;
00821
00822 FEM_Comm ghostSend;
00823 FEM_Comm ghostRecv;
00824
00825 FEM_Comm_Holder ghostIDXL;
00826
00827 FEM_Entity(FEM_Entity *ghost_);
00828 void pup(PUP::er &p);
00829 virtual ~FEM_Entity();
00830
00832 bool isGhost(void) const {return ghost==NULL;}
00833
00835 FEM_Entity *getGhost(void) {return ghost;}
00836 const FEM_Entity *getGhost(void) const {return ghost;}
00837
00838
00839
00840 void clearGhost();
00841
00843 inline int size(void) const {return length==-1?0:length;}
00844 inline int realsize(void) const {return length;}
00845
00846
00847 inline int getMax() { if(max > 0) return max; else return length;}
00848
00850 virtual const char *getName(void) const =0;
00851
00853 void copyShape(const FEM_Entity &src);
00854
00859 void setLength(int newlen, bool f=false);
00860
00862 void reserveLength(int newlen);
00863
00869 void setMaxLength(int newLen,int newMaxLen,void *args,FEM_Mesh_alloc_fn fn);
00870
00873 void copyEntity(int dstEntity,const FEM_Entity &src,int srcEntity);
00874
00877 int push_back(const FEM_Entity &src,int srcEntity);
00878
00884 FEM_Attribute *lookup(int attr,const char *caller);
00885
00886
00890 int getAttrs(int *attrs) const {
00891 int len=attributes.size();
00892 for (int i=0;i<len;i++)
00893 attrs[i]=attributes[i]->getAttr();
00894 return len;
00895 }
00896
00900 void allocateValid();
00901 void set_valid(int idx, bool isNode=false);
00902 void set_invalid(int idx, bool isNode=false);
00903 int is_valid(int idx);
00904 int is_valid_any_idx(int idx);
00905 int is_valid_nonghost_idx(int idx);
00906
00907 int count_valid();
00908 int get_next_invalid(FEM_Mesh *m=NULL, bool isNode=false, bool isGhost=false);
00909 void set_all_invalid();
00910
00911 int isBoundary(int idx);
00912
00913 virtual bool hasConn(int idx)=0;
00917 void set_coord(int idx, double x, double y);
00918 void set_coord(int idx, double x, double y, double z);
00919
00920 void get_coord(int idx, double &x, double &y);
00921 void get_coord(int idx, double &x, double &y, double &z);
00922
00925 CkVec<FEM_Attribute *>* getAttrVec(){
00926 return &attributes;
00927 }
00928
00929
00930 inline FEM_DataAttribute *getCoord(void) {return coord;}
00931 inline const FEM_DataAttribute *getCoord(void) const {return coord;}
00932
00933
00934 const FEM_Symmetries_t *getSymmetries(void) const {
00935 if (sym==NULL) return NULL;
00936 else return (const FEM_Symmetries_t *)sym->getChar()[0];
00937 }
00938 FEM_Symmetries_t getSymmetries(int r) const {
00939 if (sym==NULL) return FEM_Symmetries_t(0);
00940 else return sym->getChar()(r,0);
00941 }
00942 void setSymmetries(int r,FEM_Symmetries_t s);
00943
00944
00945 bool hasGlobalno(void) const {return globalno!=0;}
00946 int getGlobalno(int r) const {
00947 if (globalno==0) return -1;
00948 return globalno->get()(r,0);
00949 }
00950 void setGlobalno(int r,int g);
00951 void setAscendingGlobalno(void);
00952 void setAscendingGlobalno(int base);
00953 void copyOldGlobalno(const FEM_Entity &e);
00954
00955
00956 bool hasMeshSizing(void) const {return meshSizing!=0;}
00957 double getMeshSizing(int r);
00958 void setMeshSizing(int r,double s);
00959 void setMeshSizing(double *sf);
00960
00961
00962 FEM_Comm &setGhostSend(void) { return ghostSend; }
00963 const FEM_Comm &getGhostSend(void) const { return ghostSend; }
00964 FEM_Comm &setGhostRecv(void) {
00965 if (ghost==NULL) return ghostRecv;
00966 else return ghost->ghostRecv;
00967 }
00968 const FEM_Comm &getGhostRecv(void) const { return ghost->ghostRecv; }
00969
00970 void addVarIndexAttribute(int code){
00971 FEM_VarIndexAttribute *varAttribute = new FEM_VarIndexAttribute(this,code);
00972 add(varAttribute);
00973 }
00974
00975 void print(const char *type,const IDXL_Print_Map &map);
00976 };
00977 PUPmarshall(FEM_Entity)
00978
00979
00980 inline int FEM_Attribute::getLength(void) const { return e->size(); }
00981 inline int FEM_Attribute::getRealLength(void) const { return e->realsize(); }
00982 inline int FEM_Attribute::getMax(){ return e->getMax();}
00983
00984
00986
00991 class FEM_Node : public FEM_Entity {
00992 typedef FEM_Entity super;
00993
00999 FEM_DataAttribute *primary;
01000 void allocatePrimary(void);
01001
01002 void allocateElemAdjacency();
01003 void allocateNodeAdjacency();
01004
01005 FEM_VarIndexAttribute *elemAdjacency;
01006
01007 FEM_VarIndexAttribute *nodeAdjacency;
01008
01009 typedef ElemID var_id;
01010 protected:
01011 virtual void create(int attr,const char *caller);
01012 public:
01013 FEM_Comm shared;
01014 FEM_Comm_Holder sharedIDXL;
01015
01016 FEM_Node(FEM_Node *ghost_);
01017 void pup(PUP::er &p);
01018 ~FEM_Node();
01019
01020 virtual const char *getName(void) const;
01021
01022 inline bool getPrimary(int nodeNo) const {
01023 if (primary==NULL) return true;
01024 else return primary->getChar()(nodeNo,0);
01025 }
01026 inline void setPrimary(int nodeNo,bool isPrimary) {
01027 if (primary==NULL) allocatePrimary();
01028 primary->getChar()(nodeNo,0)=isPrimary;
01029 }
01030 void fillElemAdjacencyTable(int type,const FEM_Elem &elem);
01031 void setElemAdjacency(int type,const FEM_Elem &elem);
01032 void fillNodeAdjacency(const FEM_Elem &elem);
01033 void setNodeAdjacency(const FEM_Elem &elem);
01034 void fillNodeAdjacencyForElement(int node,int nodesPerElem,const int *conn,FEM_VarIndexAttribute *adjacencyAttr);
01035 bool hasConn(int idx);
01036 void print(const char *type,const IDXL_Print_Map &map);
01037 };
01038 PUPmarshall(FEM_Node)
01039
01040
01041
01042
01047 class FEM_Elem:public FEM_Entity {
01048 typedef FEM_Entity super;
01049 protected:
01050 typedef AllocTable2d<int> conn_t;
01051
01052 int tuplesPerElem;
01053
01054
01055 FEM_IndexAttribute *conn;
01056 FEM_IndexAttribute *elemAdjacency;
01057 FEM_IndexAttribute *elemAdjacencyTypes;
01058
01059 public:
01060
01061 FEM_Elem(const FEM_Mesh &mesh_, FEM_Elem *ghost_);
01062 void pup(PUP::er &p);
01063 ~FEM_Elem();
01064
01065 virtual const char *getName(void) const;
01066
01067
01068 inline conn_t &setConn(void) {return conn->get();}
01069 inline const conn_t &getConn(void) const {return conn->get();}
01070
01071 void print(const char *type,const IDXL_Print_Map &map);
01072
01073 void create(int attr,const char *caller);
01074
01075 void allocateElemAdjacency();
01076
01077 FEM_IndexAttribute *getElemAdjacency(){return elemAdjacency;}
01078
01079
01080 int getConn(int elem,int nodeNo) const {return conn->get()(elem,nodeNo);}
01081 int getNodesPer(void) const {return conn->get().width();}
01082 int *connFor(int i) {return conn->get().getRow(i);}
01083 const int *connFor(int i) const {return conn->get().getRow(i);}
01084 void connIs(int i,const int *src) {conn->get().setRow(i,src);}
01085 bool hasConn(int idx);
01086 };
01087 PUPmarshall(FEM_Elem)
01088
01089
01090
01091
01092
01099 class FEM_Sparse : public FEM_Elem {
01100 typedef FEM_Elem super;
01101 typedef AllocTable2d<int> elem_t;
01102
01111 FEM_IndexAttribute *elem;
01112 void allocateElem(void);
01113 const FEM_Mesh &mesh;
01114 protected:
01115 virtual void create(int attr,const char *caller);
01116 public:
01117 FEM_Sparse(const FEM_Mesh &mesh_, FEM_Sparse *ghost_);
01118 void pup(PUP::er &p);
01119 virtual ~FEM_Sparse();
01120
01121 virtual const char *getName(void) const;
01122
01124 bool hasElements(void) const {return elem!=NULL;}
01125
01127 inline elem_t &setElem(void) {return elem->get();}
01128 inline const elem_t &getElem(void) const {return elem->get();}
01129 };
01130 PUPmarshall(FEM_Sparse)
01131
01132
01134 class FEM_Userdata_pupfn {
01135 FEM_Userdata_fn fn;
01136 void *data;
01137 public:
01138 FEM_Userdata_pupfn(FEM_Userdata_fn fn_,void *data_)
01139 :fn(fn_), data(data_) {}
01141 void pup(PUP::er &p) {
01142 (fn)((pup_er)&p,data);
01143 }
01144 };
01145
01147 class FEM_Userdata_item {
01148 CkVec<char> data;
01149 public:
01150 int tag;
01151 FEM_Userdata_item(int tag_=-1) {tag=tag_;}
01152
01154 bool hasStored(void) const {return data.size()!=0;}
01155
01157 void store(FEM_Userdata_pupfn &f) {
01158 data.resize(PUP::size(f));
01159 PUP::toMemBuf(f,&data[0],data.size());
01160 }
01162 void restore(FEM_Userdata_pupfn &f) {
01163 PUP::fromMemBuf(f,&data[0],data.size());
01164 }
01165
01167 void pup(PUP::er &p) {
01168 p|tag;
01169 p|data;
01170 }
01171 };
01172
01174 class FEM_Userdata_list {
01175 CkVec<FEM_Userdata_item> list;
01176 public:
01177 FEM_Userdata_item &find(int tag) {
01178 for (int i=0;i<list.size();i++)
01179 if (list[i].tag==tag)
01180 return list[i];
01181
01182 list.push_back(FEM_Userdata_item(tag));
01183 return list[list.size()-1];
01184 }
01185 int size(){
01186 return list.size();
01187 }
01188 void pup(PUP::er &p) {p|list;}
01189 };
01190
01191
01192 void FEM_Index_Check(const char *caller,const char *entityType,int type,int maxType);
01193 void FEM_Is_NULL(const char *caller,const char *entityType,int type);
01194
01207 template <class T>
01208 class FEM_Entity_Types {
01209 CkVec<T *> types;
01210 const FEM_Mesh &mesh;
01211 const char *name;
01212
01213 public:
01214 FEM_Entity_Types(const FEM_Mesh &mesh_,const char *name_)
01215 :mesh(mesh_), name(name_) {}
01216 void pup(PUP::er &p) {
01217
01218 int n=types.size();
01219 p|n;
01220 for (int i=0;i<n;i++) {
01221 int isNULL=0;
01222 if (!p.isUnpacking()) isNULL=(types[i]==NULL);
01223 p|isNULL;
01224 if (!isNULL) set(i,"pup").pup(p);
01225 }
01226 }
01227 ~FEM_Entity_Types() {
01228 for (int i=0;i<types.size();i++)
01229 if (types[i]) delete types[i];
01230 }
01231
01233 inline int size(void) const {return types.size();}
01234
01236 const T &get(int type,const char *caller="") const {
01237 FEM_Index_Check(caller,name,type,types.size());
01238 const T *ret=types[type];
01239 if (ret==NULL) FEM_Is_NULL(caller,name,type);
01240 return *ret;
01241 }
01242
01244 bool has(int type) const {
01245 return (type<types.size()) && (types[type]!=NULL);
01246 }
01247
01249 bool hasNonEmpty(int type) const {
01250 return (type<types.size()) && (types[type]!=NULL) && (types[type]->size()>0);
01251 }
01252
01254 T &set(int type,const char *caller="") {
01255 if (type<0) FEM_Index_Check(caller,name,type,types.size());
01256 while (types.size()<=type) types.push_back(NULL);
01257 if (types[type]==NULL) {
01258 T *ghost=new T(mesh,NULL);
01259 types[type]=new T(mesh,ghost);
01260 }
01261 return *types[type];
01262 }
01263
01265 inline T &operator[] (int type) { return set(type); }
01266 inline const T &operator[] (int type) const { return get(type); }
01267
01268 };
01269
01271 inline int zeroToMinusOne(int i) {
01272 if (i==0) return -1;
01273 return i;
01274 }
01275
01276
01277 class ParFUMShadowArray;
01278
01279
01281
01285 class FEM_Mesh : public CkNoncopyable {
01287 FEM_Sym_List symList;
01288 bool m_isSetting;
01289
01290 void checkElemType(int elType,const char *caller) const;
01291 void checkSparseType(int uniqueID,const char *caller) const;
01292
01293 public:
01294 femMeshModify *fmMM;
01295 ParFUMShadowArray *parfumSA;
01296 bool lastLayerSet;
01297 FEM_ElemAdj_Layer* lastElemAdjLayer;
01298 void setFemMeshModify(femMeshModify *m);
01299 void setParfumSA(ParFUMShadowArray *m);
01300
01301 FEM_Mesh();
01302 void pup(PUP::er &p);
01303 ~FEM_Mesh();
01304
01306 FEM_Node node;
01307
01309 FEM_Entity_Types<FEM_Elem> elem;
01310
01312 FEM_Entity_Types<FEM_Sparse> sparse;
01313
01315 FEM_Userdata_list udata;
01316
01318 void setSymList(const FEM_Sym_List &src) {symList=src;}
01319 const FEM_Sym_List &getSymList(void) const {return symList;}
01320
01323 void copyShape(const FEM_Mesh &src);
01324
01325
01326 femMeshModify *getfmMM();
01327
01328
01329 FEM_Entity &setCount(int elTypeOrMinusOne) {
01330 if (elTypeOrMinusOne==-1) return node;
01331 else return elem[chkET(elTypeOrMinusOne)];
01332 }
01333 const FEM_Entity &getCount(int elTypeOrMinusOne) const {
01334 if (elTypeOrMinusOne==-1) return node;
01335 else return elem[chkET(elTypeOrMinusOne)];
01336 }
01337 FEM_Elem &setElem(int elType) {return elem[chkET(elType)];}
01338 const FEM_Elem &getElem(int elType) const {return elem[chkET(elType)];}
01339 int chkET(int elType) const;
01340
01342 FEM_Entity *lookup(int entity,const char *caller);
01343 const FEM_Entity *lookup(int entity,const char *caller) const;
01344
01346 inline bool isSetting(void) const {return m_isSetting;}
01347 void becomeSetting(void) {m_isSetting=true;}
01348 void becomeGetting(void) {m_isSetting=false;}
01349
01350 int nElems() const
01351 {return nElems(elem.size());}
01353 int nElems(int t) const;
01355 int getGlobalElem(int elType,int elNo) const;
01357 void setAscendingGlobalno(void);
01359 void setAbsoluteGlobalno();
01360
01361 void copyOldGlobalno(const FEM_Mesh &m);
01362 void print(int idxBase);
01364 int getEntities(int *entites);
01365
01371 void clearSharedNodes();
01372 void clearGhostNodes();
01373 void clearGhostElems();
01374
01375
01376
01377
01378
01379
01380
01381 void createNodeElemAdj();
01382 void createNodeNodeAdj();
01383 void createElemElemAdj();
01384
01385 FEM_ElemAdj_Layer *getElemAdjLayer(void);
01386
01387
01388
01389
01392 void e2e_getAll(int e, int *neighborss, int etype=0);
01394 int e2e_getNbr(int e, short idx, int etype=0);
01397 int e2e_getIndex(int e, int nbr, int etype=0);
01399 ElemID e2e_getElem(int idx, int nbr, int etype=0);
01401 ElemID e2e_getElem(ElemID elem, int nbr);
01403 ElemID e2e_getElem(ElemID *elem, int nbr);
01406 void e2e_setAll(int e, int *neighbors, int etype=0);
01408 void e2e_setIndex(int e, short idx, int newElem, int etype=0);
01410 void e2e_replace(int e, int oldNbr, int newNbr, int etype=0);
01412 void e2e_replace(ElemID e, ElemID oldNbr, ElemID newNbr);
01413
01415 void e2e_removeAll(int e, int etype=0);
01416
01417 void e2e_printAll(ElemID e);
01418
01419
01420
01421
01424 void e2n_getAll(int e, int *adjnodes, int etype=0);
01426 int e2n_getNode(int e, short idx, int etype=0);
01429 short e2n_getIndex(int e, int n, int etype=0);
01432 void e2n_setAll(int e, int *adjnodes, int etype=0);
01434 void e2n_setIndex(int e, short idx, int newNode, int etype=0);
01436 void e2n_replace(int e, int oldNode, int newNode, int etype=0);
01437
01439 void e2n_removeAll(int e, int etype=0);
01440
01441
01442
01443 int n2n_getLength(int n);
01446 void n2n_getAll(int n, int *&adjnodes, int &sz);
01448 void n2n_add(int n, int newNode);
01450 void n2n_remove(int n, int oldNode);
01452 void n2n_replace(int n, int oldNode, int newNode);
01454 void n2n_removeAll(int n);
01456 int n2n_exists(int n, int queryNode);
01457
01458
01459 int n2e_getLength(int n);
01463 void n2e_getAll(int n, int *&adjelements, int &sz);
01464
01466 const CkVec<ElemID> & n2e_getAll(int n);
01467
01469 ElemID n2e_getElem(int n, int whichAdjElem);
01471 void n2e_add(int n, int newElem);
01473 void n2e_remove(int n, int oldElem);
01475 void n2e_replace(int n, int oldElem, int newElem);
01477 void n2e_removeAll(int n);
01478
01482 int getElementOnEdge(int n1, int n2);
01483
01485 void get2ElementsOnEdge(int n1, int n2, int *result_e1, int *result_e2) ;
01486
01488 void get2ElementsOnEdgeSorted(int n1, int n2, int *result_e1, int *result_e2) ;
01489
01490
01492 int countElementsOnEdge(int n1, int n2);
01493
01494
01495
01496
01497
01499 std::set<std::pair<int,int> > edgesOnBoundary;
01500
01502 std::set<int> verticesOnBoundary;
01503
01507 std::set<int> cornersOnBoundary;
01508
01514 void detectFeatures();
01515
01516 };
01517
01518 PUPmarshall(FEM_Mesh)
01519
01520 FEM_Mesh *FEM_Mesh_lookup(int fem_mesh,const char *caller);
01521 FEM_Entity *FEM_Entity_lookup(int fem_mesh,int entity,const char *caller);
01522 FEM_Attribute *FEM_Attribute_lookup(int fem_mesh,int entity,int attr,const char *caller);
01523
01524 void FEM_Mesh_data_layout(int fem_mesh,int entity,int attr,
01525 void *data, int firstItem,int length, const IDXL_Layout &layout);
01526
01527
01528 void FEM_Register_array_layout(int fem_mesh,int entity,int attr,void *data,int firstItem,const IDXL_Layout &layout);
01529 void FEM_Register_entity_impl(int fem_mesh,int entity,void *args,int len,int max,FEM_Mesh_alloc_fn fn);
01531 FEM_Mesh *FEM_Mesh_assemble(int nchunks,FEM_Mesh **chunks);
01532
01533 FILE *FEM_openMeshFile(const char *prefix,int chunkNo,int nchunks,bool forRead);
01534 FEM_Mesh *FEM_readMesh(const char *prefix,int chunkNo,int nChunks);
01535 void FEM_writeMesh(FEM_Mesh *m,const char *prefix,int chunkNo,int nChunks);
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551 #define FEM_MAX_ELTYPE 20
01552
01553
01554 void FEM_Abort(const char *msg);
01555 void FEM_Abort(const char *caller,const char *sprintf_msg,int int0=0,int int1=0,int int2=0);
01556
01557
01559
01560 class l2g_t {
01561 public:
01562
01563 virtual int el(int t,int localNo) const {return localNo;}
01564
01565 virtual int no(int localNo) const {return localNo;}
01566 };
01567
01569 template <class T>
01570 class NumberedVec {
01571 CkPupPtrVec<T, CkPupAlwaysAllocatePtr<T> > vec;
01572
01573 public:
01574
01575 void makeLonger(int toHaveElement)
01576 {
01577 int oldSize=vec.size(), newSize=toHaveElement+1;
01578 if (oldSize>=newSize) return;
01579 vec.resize(newSize);
01580 for (int j=oldSize;j<newSize;j++)
01581 vec[j]=new T;
01582 }
01583
01584 void reinit(int doomedEl) {
01585 vec[doomedEl].destroy();
01586 vec[doomedEl]=new T;
01587 }
01588
01589 int size(void) const {return vec.size();}
01590
01591
01592 T &operator[](int i) {
01593 if (i>=vec.size()) makeLonger(i);
01594 return *( vec[i] );
01595 }
01596 const T &operator[](int i) const {return *( vec[i] );}
01597
01598 void pup(PUP::er &p) {
01599 vec.pup(p);
01600 }
01601 friend void operator|(PUP::er &p,NumberedVec<T> &v) {v.pup(p);}
01602 };
01603
01604
01606 template <class T>
01607 class ArrayPtrT : public CkNoncopyable {
01608 T *sto;
01609 public:
01610 ArrayPtrT() {sto=NULL;}
01611 ArrayPtrT(int *src) {sto=src;}
01612 ~ArrayPtrT() {if (sto) delete[] sto;}
01613 void operator=(T *src) {
01614 if (sto) delete[] sto;
01615 sto=src;
01616 }
01617 operator T *(void) {return sto;}
01618 operator const T *(void) const {return sto;}
01619 T& operator[](int i) {return sto[i];}
01620 const T& operator[](int i) const {return sto[i];}
01621 };
01622 typedef ArrayPtrT<int> intArrayPtr;
01623
01624
01625
01627 template<class T>
01628 class marshallNewHeapCopy {
01629 T *cur;
01630 public:
01631
01632 marshallNewHeapCopy(T *readFrom) :cur(readFrom) {}
01633 marshallNewHeapCopy(const marshallNewHeapCopy &h) :cur(h.cur) {}
01634 marshallNewHeapCopy(void) {
01635 cur=new T;
01636 }
01637
01638 void pup(PUP::er &p) {
01639 cur->pup(p);
01640 }
01641 operator T *() {return cur;}
01642 friend void operator|(PUP::er &p,marshallNewHeapCopy<T> &h) {h.pup(p);}
01643 };
01644 typedef marshallNewHeapCopy<FEM_Mesh> marshallMeshChunk;
01645
01646
01648 template<class T>
01649 class FEM_T_List {
01650 CkPupPtrVec<T> list;
01651 protected:
01652 int FIRST_DT;
01653 int size(void) const {return list.size();}
01654
01656 inline void check(int l,const char *caller) const {
01657 if (l<FIRST_DT || l>=FIRST_DT+list.size() || list[l-FIRST_DT]==NULL)
01658 badIndex(l,caller);
01659 }
01660
01661 void badIndex(int l,const char *caller) const {
01662 if (l<FIRST_DT || l>FIRST_DT+list.size()) bad(l,0,caller);
01663 else bad(l,1,caller);
01664 }
01665 public:
01666 FEM_T_List(int FIRST_DT_) :FIRST_DT(FIRST_DT_) {}
01667 virtual ~FEM_T_List() {}
01668 void pup(PUP::er &p) { p|list; }
01669
01671 virtual void bad(int l,int bad_code,const char *caller) const =0;
01672
01674 int put(T *t) {
01675 for (int i=0;i<list.size();i++)
01676 if (list[i]==NULL) {
01677 list[i]=t;
01678 return FIRST_DT+i;
01679 }
01680 int ret=list.size();
01681 list.push_back(t);
01682 return FIRST_DT+ret;
01683 }
01684
01686 inline T *lookup(int l,const char *caller) const {
01687 check(l,caller);
01688 return list[l-FIRST_DT];
01689 }
01690
01692 void destroy(int l,const char *caller) {
01693 check(l,caller);
01694 list[l-FIRST_DT].destroy();
01695 }
01696
01698 void empty(void) {
01699 for (int i=0;i<list.size();i++) list[i].destroy();
01700 }
01701 };
01702 class FEM_Mesh_list : public FEM_T_List<FEM_Mesh> {
01703 typedef FEM_T_List<FEM_Mesh> super;
01704 public:
01705 FEM_Mesh_list() :super(FEM_MESH_FIRST) { }
01706
01707 virtual void bad(int l,int bad_code,const char *caller) const;
01708 };
01709
01710 #define CHK(p) do{if((p)==0)CkAbort("FEM>Memory Allocation failure.");}while(0)
01711
01712
01714
01724 class FEM_chunk
01725 {
01726 public:
01727 FEM_Mesh_list meshes;
01728 int default_read;
01729 int default_write;
01730
01732 FEM_Comm_t defaultComm;
01733
01735 int thisIndex;
01736
01737 #if CMK_ERROR_CHECKING
01738 void check(const char *where);
01739 #else
01740 inline void check(const char *where) { }
01741 #endif
01742
01743 private:
01744 CkVec<int> listTmp;
01745
01746 void initFields(void);
01747
01748 public:
01749 FEM_chunk(FEM_Comm_t defaultComm_);
01750 FEM_chunk(CkMigrateMessage *msg);
01751 void pup(PUP::er &p);
01752 ~FEM_chunk();
01753
01755 static FEM_chunk *get(const char *caller);
01756
01757 inline FEM_Mesh *lookup(int fem_mesh,const char *caller) {
01758 return meshes.lookup(fem_mesh,caller);
01759 }
01760
01761 inline FEM_Mesh *getMesh(const char *caller)
01762 {return meshes.lookup(default_read,caller);}
01763 inline FEM_Mesh *setMesh(const char *caller)
01764 {return meshes.lookup(default_write,caller);}
01765
01766 void print(int fem_mesh,int idxBase);
01767 int getPrimary(int nodeNo) { return getMesh("getPrimary")->node.getPrimary(nodeNo); }
01768 const FEM_Comm &getComm(void) {return getMesh("getComm")->node.shared;}
01769
01770
01771 void exchangeGhostLists(int elemType,int inLen,const int *inList,int idxbase);
01772 void recvList(int elemType,int fmChk,int nIdx,const int *idx);
01773 const CkVec<int> &getList(void) {return listTmp;}
01774 void emptyList(void) {listTmp.length()=0;}
01775
01776 void reduce_field(int idxl_datatype, const void *nodes, void *outbuf, int op);
01777 void reduce(int idxl_datatype, const void *inbuf, void *outbuf, int op);
01778 void readField(int idxl_datatype, void *nodes, const char *fname);
01779 };
01780
01782 class FEM_Ghost_Layer : public CkNoncopyable {
01783 public:
01784 int nodesPerTuple;
01785 bool addNodes;
01786 class elemGhostInfo {
01787 public:
01788 bool add;
01789 int tuplesPerElem;
01790 intArrayPtr elem2tuple;
01791 elemGhostInfo(void) {add=false;tuplesPerElem=0;}
01792 ~elemGhostInfo(void) {}
01793 void pup(PUP::er &p) {
01794 }
01795 };
01796 elemGhostInfo elem[FEM_MAX_ELTYPE];
01797 virtual void pup(PUP::er &p){
01798 p | nodesPerTuple;
01799 p | addNodes;
01800 for(int i=0;i<FEM_MAX_ELTYPE;i++){
01801 p | elem[i].add;
01802 p | elem[i].tuplesPerElem;
01803 if(elem[i].tuplesPerElem == 0){
01804 continue;
01805 }
01806 int *arr;
01807 if(p.isUnpacking()){
01808 arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
01809 }else{
01810 arr = elem[i].elem2tuple;
01811 }
01812 p(arr,nodesPerTuple*elem[i].tuplesPerElem);
01813 if(p.isUnpacking()){
01814 elem[i].elem2tuple = arr;
01815 }
01816 }
01817 }
01818 };
01819
01822 class FEM_Ghost_Stencil {
01824 int elType;
01826 int n;
01828 bool addNodes;
01829
01832 intArrayPtr ends;
01833
01842 intArrayPtr adj;
01843 public:
01848 FEM_Ghost_Stencil(int elType_, int n_,bool addNodes_,
01849 const int *ends_,
01850 const int *adj_,
01851 int idxBase);
01852
01854 void check(const FEM_Mesh &mesh) const;
01855
01857 inline int getType(void) const {return elType;}
01858
01865 inline const int *getNeighbor(int i,int j) const {
01866 int start=0;
01867 if (i>0) start=ends[i-1];
01868 if (j>=ends[i]-start) return 0;
01869 return &adj[2*(start+j)];
01870 }
01871
01872 inline bool wantNodes(void) const {return addNodes;}
01873 };
01874
01876 class FEM_Ghost_Region {
01877 public:
01878 FEM_Ghost_Layer *layer;
01879 FEM_Ghost_Stencil *stencil;
01880
01881 FEM_Ghost_Region() {layer=0; stencil=0;}
01882 FEM_Ghost_Region(FEM_Ghost_Layer *l) {layer=l; stencil=0;}
01883 FEM_Ghost_Region(FEM_Ghost_Stencil *s) {layer=0; stencil=s;}
01884 };
01885
01886
01887
01888 class FEM_Initial_Symmetries;
01889
01891 class FEM_Partition : public CkNoncopyable {
01893 int *elem2chunk;
01894
01896 CkVec<FEM_Ghost_Region> regions;
01897 FEM_Ghost_Layer *lastLayer;
01898
01900 FEM_Initial_Symmetries *sym;
01901 public:
01902 FEM_Partition();
01903 ~FEM_Partition();
01904
01905
01906 void setPartition(const int *elem2chunk, int nElem, int idxBase);
01907 const int *getPartition(FEM_Mesh *src,int nChunks) const;
01908
01909
01910 FEM_Ghost_Layer *addLayer(void) {
01911 lastLayer=new FEM_Ghost_Layer();
01912 regions.push_back(lastLayer);
01913 return lastLayer;
01914 }
01915 FEM_Ghost_Layer *curLayer(void) {
01916 if (lastLayer==0) CkAbort("Must call FEM_Add_ghost_layer before FEM_Add_ghost_elem\n");
01917 return lastLayer;
01918 }
01919
01920
01921 void addGhostStencil(FEM_Ghost_Stencil *s) {
01922 regions.push_back(s);
01923 lastLayer=0;
01924 }
01925 void markGhostStencilLayer(void) {
01926 regions.push_back(FEM_Ghost_Region());
01927 }
01928
01929
01930 int getRegions(void) const {return regions.size();}
01931 const FEM_Ghost_Region &getRegion(int regNo) const {return regions[regNo];}
01932
01933
01934 void setSymmetries(int nNodes_,int *new_can,const int *sym_src);
01935 void addLinearPeriodic(int nFaces_,int nPer,
01936 const int *facesA,const int *facesB,int idxBase,
01937 int nNodes_,const CkVector3d *nodeLocs);
01938 const int *getCanon(void) const;
01939 const FEM_Symmetries_t *getSymmetries(void) const;
01940 const FEM_Sym_List &getSymList(void) const;
01941
01942
01943 };
01944
01945 FEM_Partition &FEM_curPartition(void);
01946
01947
01948 #define FEMAPI(routineName) TCHARM_API_TRACE(routineName,"fem")
01949
01950
01951
01952
01953
01954
01955
01956
01957 void FEM_Mesh_partition(const FEM_Mesh *mesh,int nchunks,int *elem2chunk, bool faceGraph=false);
01958
01959
01960
01961
01962
01963 class FEM_Mesh_Output {
01964 public:
01965 virtual ~FEM_Mesh_Output() {}
01966
01967 virtual void accept(int chunkNo,FEM_Mesh *msg) =0;
01968 };
01969
01970
01971
01972
01973 void FEM_Mesh_split(FEM_Mesh *mesh,int nchunks,
01974 const FEM_Partition &partition,FEM_Mesh_Output *out);
01975
01976
01977
01978 int *CkCopyArray(const int *src,int len,int indexBase);
01979
01980
01991
01992 class FEM_ElemAdj_Layer : public CkNoncopyable {
01993 public:
01994 int initialized;
01995 int nodesPerTuple;
01996
01997 class elemAdjInfo {
01998 public:
01999
02000 int tuplesPerElem;
02001 intArrayPtr elem2tuple;
02002 elemAdjInfo(void) {tuplesPerElem=0;}
02003 ~elemAdjInfo(void) {}
02004 void pup(PUP::er &p) {
02005 }
02006 };
02007
02008 elemAdjInfo elem[FEM_MAX_ELTYPE];
02009
02010 FEM_ElemAdj_Layer() {initialized=0;}
02011
02012 virtual void pup(PUP::er &p){
02013 p | initialized;
02014 p | nodesPerTuple;
02015
02016 CkPrintf("Calling inefficient FEM_ElemAdj_Layer::pup method\n");
02017
02018 for(int i=0;i<FEM_MAX_ELTYPE;i++){
02019 p | elem[i].tuplesPerElem;
02020 if(elem[i].tuplesPerElem == 0){
02021 continue;
02022 }
02023 int *arr;
02024 if(p.isUnpacking()){
02025 arr = new int[nodesPerTuple*elem[i].tuplesPerElem];
02026 }else{
02027 arr = elem[i].elem2tuple;
02028 }
02029 p(arr,nodesPerTuple*elem[i].tuplesPerElem);
02030 if(p.isUnpacking()){
02031 elem[i].elem2tuple = arr;
02032 }
02033 }
02034 }
02035 };
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 #ifdef DEBUG
02056 #undef DEBUG
02057 #endif
02058 #ifdef PARALLEL_DEBUG
02059 #define DEBUG(x) x
02060 #else
02061 #define DEBUG(x)
02062 #endif
02063
02064 #define MESH_CHUNK_TAG 3000
02065 #define MAX_SHARED_PER_NODE 20
02066
02067 class NodeElem {
02068 public:
02069
02070 int global;
02071
02072
02073
02074
02075 int numShared;
02076
02077
02078
02079
02080 int shared[MAX_SHARED_PER_NODE];
02081
02082 NodeElem(){
02083 global = -1;
02084 numShared = 0;
02085
02086 }
02087 NodeElem(int g_,int num_){
02088 global = g_; numShared= num_;
02089
02090
02091
02092
02093
02094 if(numShared > MAX_SHARED_PER_NODE){
02095 CkAbort("In Parallel partition the max number of chunks per node exceeds limit\n");
02096 }
02097 }
02098 NodeElem(int g_){
02099 global = g_;
02100 numShared = 0;
02101
02102 }
02103 NodeElem(const NodeElem &rhs){
02104
02105 *this = rhs;
02106 }
02107 inline NodeElem& operator=(const NodeElem &rhs){
02108 global = rhs.global;
02109 numShared = rhs.numShared;
02110
02111
02112
02113
02114 memcpy(&shared[0],&((rhs.shared)[0]),numShared*sizeof(int));
02115 return *this;
02116 }
02117
02118 inline bool operator == (const NodeElem &rhs){
02119 if(global == rhs.global){
02120 return true;
02121 }else{
02122 return false;
02123 }
02124 }
02125 inline bool operator >=(const NodeElem &rhs){
02126 return (global >= rhs.global);
02127 }
02128
02129 inline bool operator <=(const NodeElem &rhs){
02130 return (global <= rhs.global);
02131 }
02132
02133 virtual void pup(PUP::er &p){
02134 p | global;
02135 p | numShared;
02136
02137
02138
02139
02140
02141
02142
02143 p(shared,numShared);
02144 }
02145 ~NodeElem(){
02146
02147
02148
02149 }
02150 };
02151
02159 class MeshElem{
02160 public:
02161 FEM_Mesh *m;
02162 CkVec<int> gedgechunk;
02163 MeshElem(){
02164 m = new FEM_Mesh;
02165 }
02166 MeshElem(int dummy){
02167 m = new FEM_Mesh;
02168 }
02169 ~MeshElem(){
02170 delete m;
02171 }
02172 MeshElem(const MeshElem &rhs){
02173 m = NULL;
02174 *this = rhs;
02175 }
02176 inline MeshElem& operator=(const MeshElem &rhs){
02177 if(m != NULL){
02178 delete m;
02179 }
02180 m = new FEM_Mesh;
02181 m->copyShape(*(rhs.m));
02182 (*this) += rhs;
02183
02184 return *this;
02185 }
02186 inline MeshElem& operator+=(const MeshElem &rhs){
02187 int oldel = m->nElems();
02188 m->copyShape(*(rhs.m));
02189 for(int i=0;i<rhs.m->node.size();i++){
02190 m->node.push_back((rhs.m)->node,i);
02191 }
02192 if((rhs.m)->elem.size()>0){
02193 for(int t=0;t<(rhs.m)->elem.size();t++){
02194 if((rhs.m)->elem.has(t)){
02195 for(int e=0;e<(rhs.m)->elem.get(t).size();e++){
02196 m->elem[t].push_back((rhs.m)->elem.get(t),e);
02197 }
02198 }
02199 }
02200 }
02201
02202 return *this;
02203 }
02204 virtual void pup(PUP::er &p){
02205 if(p.isUnpacking()){
02206 m = new FEM_Mesh;
02207 }
02208 m->pup(p);
02209 }
02210
02211 struct ElemInfo {
02212 FEM_Mesh* m;
02213 int index;
02214 int elemType;
02215 ElemInfo(FEM_Mesh* _m, int _index, int _elemType)
02216 : m(_m), index(_index), elemType(_elemType) {}
02217 };
02218
02219 MeshElem& operator+=(const ElemInfo& rhs) {
02220 m->elem[rhs.elemType].copyShape(rhs.m->elem[rhs.elemType]);
02221 m->elem[rhs.elemType].push_back(rhs.m->elem[rhs.elemType], rhs.index);
02222 return *this;
02223 }
02224
02225 struct NodeInfo {
02226 FEM_Mesh* m;
02227 int index;
02228 NodeInfo(FEM_Mesh* _m, int _index)
02229 : m(_m), index(_index) {}
02230 };
02231
02232 MeshElem& operator+=(const NodeInfo& rhs) {
02233 m->node.copyShape(rhs.m->node);
02234 m->node.push_back(rhs.m->node, rhs.index);
02235 return *this;
02236 }
02237 };
02238
02239
02240 typedef MSA::MSA2D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2DRM;
02241
02242 typedef MSA::MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINT;
02243
02244 typedef UniqElemList<int> IntList;
02245 typedef MSA::MSA1D<IntList, DefaultListEntry<IntList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DINTLIST;
02246
02247 typedef UniqElemList<NodeElem> NodeList;
02248 typedef MSA::MSA1D<NodeList, DefaultListEntry<NodeList,true>,MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1DNODELIST;
02249
02250 typedef MSA::MSA1D<MeshElem,DefaultEntry<MeshElem,true>,1> MSA1DFEMMESH;
02251
02252 #include "ParFUM.decl.h"
02253
02254
02255 struct conndata{
02256 int nelem;
02257 int nnode;
02258 MSA1DINT arr1;
02259 MSA1DINT arr2;
02260
02261 void pup(PUP::er &p){
02262 p|nelem;
02263 p|nnode;
02264 arr1.pup(p);
02265 arr2.pup(p);
02266 }
02267 };
02268
02273 struct partconndata{
02274 int nelem;
02275 int startindex;
02276 int *eptr,*eind;
02277 int *part;
02278 ~partconndata(){
02279 delete [] eptr;
02280 delete [] eind;
02281 delete [] part;
02282 };
02283 };
02284
02288 struct ghostdata{
02289 int numLayers;
02290 FEM_Ghost_Layer **layers;
02291 void pup(PUP::er &p){
02292 p | numLayers;
02293 if(p.isUnpacking()){
02294 layers = new FEM_Ghost_Layer *[numLayers];
02295 for(int i=0;i<numLayers;i++){
02296 layers[i] = new FEM_Ghost_Layer;
02297 }
02298
02299 }
02300 for(int i=0;i<numLayers;i++){
02301 layers[i]->pup(p);
02302 }
02303 }
02304 ~ghostdata(){
02305
02306 for(int i=0;i<numLayers;i++){
02307 delete layers[i];
02308 }
02309 delete [] layers;
02310 };
02311 };
02312
02313
02314
02315
02316 int FEM_master_parallel_part(int ,int ,FEM_Comm_t);
02317 int FEM_slave_parallel_part(int ,int ,FEM_Comm_t);
02318 struct partconndata* FEM_call_parmetis(int nelem, MSA1DINT::Read &rPtr, MSA1DINT::Read &rInd, FEM_Comm_t comm_context);
02319 void FEM_write_nodepart(MSA1DINTLIST::Accum &nodepart, struct partconndata *data, MPI_Comm comm_context);
02320 void FEM_write_part2node(MSA1DINTLIST::Read &nodepart, MSA1DNODELIST::Accum &part2node, struct partconndata *data, MPI_Comm comm_context);
02321 void FEM_write_part2elem(MSA1DINTLIST::Accum &part2elem, struct partconndata *data, MPI_Comm comm_context);
02322 FEM_Mesh * FEM_break_mesh(FEM_Mesh *m,int numElements,int numChunks);
02323 void sendBrokenMeshes(FEM_Mesh *mesh_array,FEM_Comm_t comm_context);
02324 void FEM_write_part2mesh(MSA1DFEMMESH::Accum &part2mesh, struct partconndata *partdata, struct conndata *data, MSA1DINTLIST::Read &nodepart, int numChunks, int myChunk, FEM_Mesh *mypiece);
02325 void addIDXLists(FEM_Mesh *m,NodeList &lnodes,int myChunk);
02326 struct ghostdata *gatherGhosts();
02327 void makeGhosts(FEM_Mesh *m,MPI_Comm comm,int masterRank,int numLayers,FEM_Ghost_Layer **layers);
02328 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);
02329 bool sharedWith(int lnode,int chunk,FEM_Mesh *m);
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344 static FEM_Symmetries_t noSymmetries=(FEM_Symmetries_t)0;
02345
02346
02347 CkHashCode CkHashFunction_ints(const void *keyData,size_t keyLen);
02348 int CkHashCompare_ints(const void *k1,const void *k2,size_t keyLen);
02349 extern "C" int ck_fem_map_compare_int(const void *a, const void *b);
02350
02351
02352
02353 class elemList {
02354 public:
02355 int chunk;
02356 int tupleNo;
02357 int localNo;
02358 int type;
02359 FEM_Symmetries_t sym;
02360 elemList *next;
02361
02362 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_)
02363 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_)
02364 { next=NULL; }
02365 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_,int tupleNo_)
02366 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_) , tupleNo(tupleNo_)
02367 { next=NULL; }
02368
02369 ~elemList() {if (next) delete next;}
02370 void setNext(elemList *n) {next=n;}
02371 };
02372
02373
02374
02375 class tupleTable : public CkHashtable {
02376 int tupleLen;
02377 CkHashtableIterator *it;
02378 static int roundUp(int val,int to) {
02379 return ((val+to-1)/to)*to;
02380 }
02381 static CkHashtableLayout makeLayout(int tupleLen) {
02382 int ks=tupleLen*sizeof(int);
02383 int oo=roundUp(ks+sizeof(char),sizeof(void *));
02384 int os=sizeof(elemList *);
02385 return CkHashtableLayout(ks,ks,oo,os,oo+os);
02386 }
02387
02388
02389
02390
02391 void canonicalize(const int *tuple,int *can)
02392 {
02393 switch(tupleLen) {
02394 case 1:
02395 can[0]=tuple[0]; break;
02396 case 2:
02397 if (tuple[0]<tuple[1])
02398 {can[0]=tuple[0]; can[1]=tuple[1];}
02399 else
02400 {can[0]=tuple[1]; can[1]=tuple[0];}
02401 break;
02402 default:
02403 memcpy(can,tuple,tupleLen*sizeof(int));
02404 qsort(can,tupleLen,sizeof(int),ck_fem_map_compare_int);
02405 };
02406 }
02407 public:
02408 enum {MAX_TUPLE=8};
02409
02410 tupleTable(int tupleLen_)
02411 :CkHashtable(makeLayout(tupleLen_),
02412 137,0.5,
02413 CkHashFunction_ints,
02414 CkHashCompare_ints)
02415 {
02416 tupleLen=tupleLen_;
02417 if (tupleLen>MAX_TUPLE) CkAbort("Cannot have that many shared nodes!\n");
02418 it=NULL;
02419 }
02420 ~tupleTable() {
02421 beginLookup();
02422 elemList *doomed;
02423 while (NULL!=(doomed=(elemList *)lookupNext()))
02424 delete doomed;
02425 }
02426
02427 elemList **lookupTuple(const int *tuple) {
02428 int can[MAX_TUPLE];
02429 canonicalize(tuple,can);
02430 return (elemList **)get(can);
02431 }
02432
02433
02434 void addTuple(const int *tuple,elemList *nu)
02435 {
02436 int can[MAX_TUPLE];
02437 canonicalize(tuple,can);
02438
02439 elemList **dest=(elemList **)get(can);
02440 if (dest!=NULL)
02441 {
02442 nu->setNext(*dest);
02443 } else {
02444 dest=(elemList **)put(can);
02445 }
02446 *dest=nu;
02447 }
02448
02449 void beginLookup(void) {
02450 it=iterator();
02451 }
02452 elemList *lookupNext(void) {
02453 void *ret=it->next();
02454 if (ret==NULL) {
02455 delete it;
02456 return NULL;
02457 }
02458 return *(elemList **)ret;
02459 }
02460 };
02461
02462
02463
02464
02465
02466
02467
02468
02469 class chunkList : public CkNoncopyable {
02470 public:
02471 int chunk;
02472 int localNo;
02473 FEM_Symmetries_t sym;
02474 int layerNo;
02475 chunkList *next;
02476 chunkList() {chunk=-1;next=NULL;}
02477 chunkList(int chunk_,int localNo_,FEM_Symmetries_t sym_,int ln_=-1) {
02478 chunk=chunk_;
02479 localNo=localNo_;
02480 sym=sym_;
02481 layerNo=ln_;
02482 next=NULL;
02483 }
02484 ~chunkList() {delete next;}
02485 void set(int c,int l,FEM_Symmetries_t s,int ln) {
02486 chunk=c; localNo=l; sym=s; layerNo=ln;
02487 }
02488
02489
02490 bool addchunk(int c,int l,FEM_Symmetries_t s,int ln) {
02491
02492
02493 if (chunk==c && sym==s) return false;
02494 if (chunk==-1) {set(c,l,s,ln);return true;}
02495 if (next==NULL) {next=new chunkList(c,l,s,ln);return true;}
02496 else return next->addchunk(c,l,s,ln);
02497 }
02498
02499 int localOnChunk(int c,FEM_Symmetries_t s) const {
02500 const chunkList *l=onChunk(c,s);
02501 if (l==NULL) return -1;
02502 else return l->localNo;
02503 }
02504 const chunkList *onChunk(int c,FEM_Symmetries_t s) const {
02505 if (chunk==c && sym==s) return this;
02506 else if (next==NULL) return NULL;
02507 else return next->onChunk(c,s);
02508 }
02509 int isEmpty(void) const
02510 {return (chunk==-1);}
02511 int isShared(void) const
02512 {return next!=NULL;}
02513 int isGhost(void) const
02514 {return FEM_Is_ghost_index(localNo); }
02515 int length(void) const {
02516 if (next==NULL) return isEmpty()?0:1;
02517 else return 1+next->length();
02518 }
02519 chunkList &operator[](int i) {
02520 if (i==0) return *this;
02521 else return (*next)[i-1];
02522 }
02523 };
02524
02525
02526
02527
02528
02529 #include "ParFUM_locking.h"
02530
02531
02532
02533
02534
02536 class FEM_MUtil {
02538 int idx;
02540 femMeshModify *mmod;
02542 class tuple {
02543 public:
02545 int oldIdx;
02547 int newIdx;
02549 tuple() {
02550 oldIdx = -1;
02551 newIdx = -1;
02552 }
02554 tuple(int o, int n) {
02555 oldIdx = o;
02556 newIdx = n;
02557 }
02558 };
02560 CkVec<tuple> outStandingMappings;
02561
02562 public:
02564 FEM_MUtil() {}
02566 FEM_MUtil(int i, femMeshModify *m);
02568 FEM_MUtil(femMeshModify *m);
02570 ~FEM_MUtil();
02572 void pup(PUP::er &p) {
02573 p|idx;
02574 }
02576 int getIdx() { return idx; }
02578 int getRemoteIdx(FEM_Mesh *m, int elementid, int elemtype);
02580 bool isShared(int index);
02582 int exists_in_IDXL(FEM_Mesh *m, int localIdx, int chk, int type, int elemType=0);
02584 int lookup_in_IDXL(FEM_Mesh *m, int sharedIdx, int fromChk, int type, int elemType=0);
02585
02587
02591 void getChunkNos(int entType, int entNo, int *numChunks, IDXL_Share ***chunks, int elemType=0);
02593 void buildChunkToNodeTable(int *nodetype, int sharedcount, int ghostcount, int localcount, int *conn, int connSize, CkVec<int> ***allShared, int *numSharedChunks, CkVec<int> **allChunks, int ***sharedConn);
02595 chunkListMsg *getChunksSharingGhostNodeRemote(FEM_Mesh *m, int chk, int sharedIdx);
02596
02598 void splitEntityAll(FEM_Mesh *m, int localIdx, int nBetween, int *between);
02600 void splitEntitySharing(FEM_Mesh *m, int localIdx, int nBetween, int *between, int numChunks, int *chunks);
02602 void splitEntityRemote(FEM_Mesh *m, int chk, int localIdx, int nBetween, int *between);
02603
02605 void removeNodeAll(FEM_Mesh *m, int localIdx);
02607 void removeNodeRemote(FEM_Mesh *m, int chk, int sharedIdx);
02609 void removeGhostNodeRemote(FEM_Mesh *m, int fromChk, int sharedIdx);
02610
02612 int addElemRemote(FEM_Mesh *m, int chk, int elemtype, int connSize, int *conn, int numGhostIndex, int *ghostIndices);
02614 void addGhostElementRemote(FEM_Mesh *m, int chk, int elemType, int *indices, int *typeOfIndex, int connSize);
02616 void removeElemRemote(FEM_Mesh *m, int chk, int elementid, int elemtype, int permanent, bool aggressive_node_removal=false);
02618 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);
02619
02621 int Replace_node_local(FEM_Mesh *m, int oldIdx, int newIdx);
02623 void addToSharedList(FEM_Mesh *m, int fromChk, int sharedIdx);
02625 int eatIntoElement(int localIdx, bool aggressive_node_removal=false);
02626
02628 bool knowsAbtNode(int chk, int nodeId);
02630 void UpdateGhostSend(int nodeId, int *chunkl, int numchunkl);
02632 void findGhostSend(int nodeId, int *&chunkl, int &numchunkl);
02633
02635 void copyElemData(int etype, int elemid, int newEl);
02637 void packEntData(char **data, int *size, int *cnt, int localIdx, bool isnode, int elemType);
02639 void updateAttrs(char *data, int size, int newIndex, bool isnode, int elemType);
02640
02642 int getLockOwner(int nodeId);
02643
02645 void idxllock(FEM_Mesh *m, int chk, int type);
02647 void idxlunlock(FEM_Mesh *m, int chk, int type);
02649 void idxllockLocal(FEM_Mesh *m, int toChk, int type);
02651 void idxlunlockLocal(FEM_Mesh *m, int toChk, int type);
02652
02654 void FEM_Print_n2n(FEM_Mesh *m, int nodeid);
02656 void FEM_Print_n2e(FEM_Mesh *m, int nodeid);
02658 void FEM_Print_e2n(FEM_Mesh *m, int eid);
02660 void FEM_Print_e2e(FEM_Mesh *m, int eid);
02662 void FEM_Print_coords(FEM_Mesh *m, int nodeid);
02663
02665 void StructureTest(FEM_Mesh *m);
02667 int AreaTest(FEM_Mesh *m);
02669 int IdxlListTest(FEM_Mesh *m);
02671 void verifyIdxlListRemote(FEM_Mesh *m, int fromChk, int fsize, int type);
02673 int residualLockTest(FEM_Mesh *m);
02675 void unlockAll(FEM_Mesh* m);
02676 };
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687 #include "ParFUM_Mesh_Modify.h"
02688
02689 #include "ParFUM_Adapt_Algs.h"
02690
02691 #include "ParFUM_Adapt.h"
02692
02693 #include "ParFUM_Interpolate.h"
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711 #ifndef __OSL_VECTOR_2D_H
02712 #define __OSL_VECTOR_2D_H
02713
02714 #include <math.h>
02715
02716 typedef double Real;
02717
02718
02719 class vector2d {
02720 public:
02721 Real x,y;
02722 vector2d(void) {}
02723
02724 explicit vector2d(const Real init) {x=y=init;}
02725
02726 explicit vector2d(int init) {x=y=init;}
02727
02728 vector2d(const Real Nx,const Real Ny) {x=Nx;y=Ny;}
02729
02730 vector2d(const vector2d ©) {x=copy.x;y=copy.y;}
02731
02732
02733 operator Real *() {return &x;}
02734 operator const Real *() const {return &x;}
02735
02736
02737
02738
02739
02740
02741
02742
02743 vector2d &operator=(const vector2d &b) {x=b.x;y=b.y;return *this;}
02744 int operator==(const vector2d &b) const {return (x==b.x)&&(y==b.y);}
02745 int operator!=(const vector2d &b) const {return (x!=b.x)||(y!=b.y);}
02746 vector2d operator+(const vector2d &b) const {return vector2d(x+b.x,y+b.y);}
02747 vector2d operator-(const vector2d &b) const {return vector2d(x-b.x,y-b.y);}
02748 vector2d operator*(const Real scale) const
02749 {return vector2d(x*scale,y*scale);}
02750 friend vector2d operator*(const Real scale,const vector2d &v)
02751 {return vector2d(v.x*scale,v.y*scale);}
02752 vector2d operator/(const Real &div) const
02753 {Real scale=1.0/div;return vector2d(x*scale,y*scale);}
02754 vector2d operator-(void) const {return vector2d(-x,-y);}
02755 void operator+=(const vector2d &b) {x+=b.x;y+=b.y;}
02756 void operator-=(const vector2d &b) {x-=b.x;y-=b.y;}
02757 void operator*=(const Real scale) {x*=scale;y*=scale;}
02758 void operator/=(const Real div) {Real scale=1.0/div;x*=scale;y*=scale;}
02759
02760
02761
02762 Real magSqr(void) const {return x*x+y*y;}
02763
02764 Real mag(void) const {return sqrt(magSqr());}
02765
02766
02767 Real distSqr(const vector2d &b) const
02768 {return (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y);}
02769
02770 Real dist(const vector2d &b) const {return sqrt(distSqr(b));}
02771
02772
02773 Real dot(const vector2d &b) const {return x*b.x+y*b.y;}
02774
02775 Real cosAng(const vector2d &b) const {return dot(b)/(mag()*b.mag());}
02776
02777
02778 vector2d dir(void) const {return (*this)/mag();}
02779
02780
02781 vector2d perp(void) const {return vector2d(-y,x);}
02782
02783
02784 vector2d &scale(const vector2d &b) {x*=b.x;y*=b.y;return *this;}
02785
02786
02787 Real max(void) {return (x>y)?x:y;}
02788
02789
02790 void enlarge(const vector2d &by)
02791 {if (by.x>x) x=by.x; if (by.y>y) y=by.y;}
02792 };
02793
02794 #endif //__OSL_VECTOR2D_H
02795
02796
02797
02798
02799
02800
02801 #ifndef CMK_THRESHOLD_TIMER
02802 #define CMK_THRESHOLD_TIMER
02803
02828 class CkThresholdTimer {
02829 double threshold;
02830 double lastStart;
02831 const char *lastWhat;
02832
02833 void start_(const char *what) {
02834 lastStart=CmiWallTimer();
02835 lastWhat=what;
02836 }
02837 void done_(void) {
02838 double elapsed=CmiWallTimer()-lastStart;
02839 if (elapsed>threshold) {
02840 CmiPrintf("%s took %.2f s\n",lastWhat,elapsed);
02841 }
02842 }
02843 public:
02844 CkThresholdTimer(const char *what,double thresh=0.001)
02845 :threshold(thresh) { start_(what); }
02846 void start(const char *what) { done_(); start_(what); }
02847 ~CkThresholdTimer() {done_();}
02848 };
02849
02850 #endif
02851
02852
02853 #include "adapt_adj.h"
02854
02855 #endif
02856
02857