00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <assert.h>
00013 #include "fem_impl.h"
00014 #include "fem.h"
00015 #include "fem_mesh.h"
00016 #include "cktimer.h"
00017
00018 #ifndef __FEM_MAP_H___
00019 #define __FEM_MAP_H___
00020
00021 static FEM_Symmetries_t noSymmetries=(FEM_Symmetries_t)0;
00022
00023
00024 CkHashCode CkHashFunction_ints(const void *keyData,size_t keyLen);
00025 int CkHashCompare_ints(const void *k1,const void *k2,size_t keyLen);
00026 extern "C" int ck_fem_map_compare_int(const void *a, const void *b);
00027
00028
00029
00030 class elemList {
00031 public:
00032 int chunk;
00033 int tupleNo;
00034 int localNo;
00035 int type;
00036 FEM_Symmetries_t sym;
00037 elemList *next;
00038
00039 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_)
00040 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_)
00041 { next=NULL; }
00042 elemList(int chunk_,int localNo_,int type_,FEM_Symmetries_t sym_,int tupleNo_)
00043 :chunk(chunk_),localNo(localNo_),type(type_), sym(sym_) , tupleNo(tupleNo_)
00044 { next=NULL; }
00045
00046 ~elemList() {if (next) delete next;}
00047 void setNext(elemList *n) {next=n;}
00048 };
00049
00050
00051
00052 class tupleTable : public CkHashtable {
00053 int tupleLen;
00054 CkHashtableIterator *it;
00055 static int roundUp(int val,int to) {
00056 return ((val+to-1)/to)*to;
00057 }
00058 static CkHashtableLayout makeLayout(int tupleLen) {
00059 int ks=tupleLen*sizeof(int);
00060 int oo=roundUp(ks+sizeof(char),sizeof(void *));
00061 int os=sizeof(elemList *);
00062 return CkHashtableLayout(ks,ks,oo,os,oo+os);
00063 }
00064
00065
00066
00067
00068 void canonicalize(const int *tuple,int *can)
00069 {
00070 switch(tupleLen) {
00071 case 1:
00072 can[0]=tuple[0]; break;
00073 case 2:
00074 if (tuple[0]<tuple[1])
00075 {can[0]=tuple[0]; can[1]=tuple[1];}
00076 else
00077 {can[0]=tuple[1]; can[1]=tuple[0];}
00078 break;
00079 default:
00080 memcpy(can,tuple,tupleLen*sizeof(int));
00081 qsort(can,tupleLen,sizeof(int),ck_fem_map_compare_int);
00082 };
00083 }
00084 public:
00085 enum {MAX_TUPLE=8};
00086
00087 tupleTable(int tupleLen_)
00088 :CkHashtable(makeLayout(tupleLen_),
00089 137,0.5,
00090 CkHashFunction_ints,
00091 CkHashCompare_ints)
00092 {
00093 tupleLen=tupleLen_;
00094 if (tupleLen>MAX_TUPLE) CkAbort("Cannot have that many shared nodes!\n");
00095 it=NULL;
00096 }
00097 ~tupleTable() {
00098 beginLookup();
00099 elemList *doomed;
00100 while (NULL!=(doomed=(elemList *)lookupNext()))
00101 delete doomed;
00102 }
00103
00104 elemList **lookupTuple(const int *tuple) {
00105 int can[MAX_TUPLE];
00106 canonicalize(tuple,can);
00107 return (elemList **)get(can);
00108 }
00109
00110
00111 void addTuple(const int *tuple,elemList *nu)
00112 {
00113 int can[MAX_TUPLE];
00114 canonicalize(tuple,can);
00115
00116 elemList **dest=(elemList **)get(can);
00117 if (dest!=NULL)
00118 {
00119 nu->setNext(*dest);
00120 } else {
00121 dest=(elemList **)put(can);
00122 }
00123 *dest=nu;
00124 }
00125
00126 void beginLookup(void) {
00127 it=iterator();
00128 }
00129 elemList *lookupNext(void) {
00130 void *ret=it->next();
00131 if (ret==NULL) {
00132 delete it;
00133 return NULL;
00134 }
00135 return *(elemList **)ret;
00136 }
00137 };
00138
00139
00140
00141
00142
00143
00144
00145
00146 class chunkList : public CkNoncopyable {
00147 public:
00148 int chunk;
00149 int localNo;
00150 FEM_Symmetries_t sym;
00151 int layerNo;
00152 chunkList *next;
00153 chunkList() {chunk=-1;next=NULL;}
00154 chunkList(int chunk_,int localNo_,FEM_Symmetries_t sym_,int ln_=-1) {
00155 chunk=chunk_;
00156 localNo=localNo_;
00157 sym=sym_;
00158 layerNo=ln_;
00159 next=NULL;
00160 }
00161 ~chunkList() {delete next;}
00162 void set(int c,int l,FEM_Symmetries_t s,int ln) {
00163 chunk=c; localNo=l; sym=s; layerNo=ln;
00164 }
00165
00166
00167 bool addchunk(int c,int l,FEM_Symmetries_t s,int ln) {
00168
00169
00170 if (chunk==c && sym==s) return false;
00171 if (chunk==-1) {set(c,l,s,ln);return true;}
00172 if (next==NULL) {next=new chunkList(c,l,s,ln);return true;}
00173 else return next->addchunk(c,l,s,ln);
00174 }
00175
00176 int localOnChunk(int c,FEM_Symmetries_t s) const {
00177 const chunkList *l=onChunk(c,s);
00178 if (l==NULL) return -1;
00179 else return l->localNo;
00180 }
00181 const chunkList *onChunk(int c,FEM_Symmetries_t s) const {
00182 if (chunk==c && sym==s) return this;
00183 else if (next==NULL) return NULL;
00184 else return next->onChunk(c,s);
00185 }
00186 int isEmpty(void) const
00187 {return (chunk==-1);}
00188 int isShared(void) const
00189 {return next!=NULL;}
00190 int isGhost(void) const
00191 {return FEM_Is_ghost_index(localNo); }
00192 int length(void) const {
00193 if (next==NULL) return isEmpty()?0:1;
00194 else return 1+next->length();
00195 }
00196 chunkList &operator[](int i) {
00197 if (i==0) return *this;
00198 else return (*next)[i-1];
00199 }
00200 };
00201
00202
00203 #endif // end of map.h header file