00001 #include "ckvector3d.h"
00002 #include "charm-api.h"
00003 #include "refine.h"
00004 #include "fem.h"
00005 #include "fem_mesh.h"
00006 #include "femrefine.h"
00007 
00008 class intdual{
00009     private:
00010         int x,y;
00011     public:
00012         intdual(int _x,int _y){
00013             if(_x <= _y){
00014                 x = _x; y=_y;
00015             }else{
00016                 x = _y; y= _x;
00017             }
00018         }
00019         int getx(){return x;};
00020         int gety(){return y;};
00021         inline CkHashCode hash() const {
00022             return (CkHashCode)(x+y);
00023         }
00024         static CkHashCode staticHash(const void *k,size_t){
00025             return ((intdual *)k)->hash();
00026         }
00027         inline int compare(intdual &t) const{
00028             return (t.getx() == x && t.gety() == y);
00029         }
00030         static int staticCompare(const void *a,const void *b,size_t){
00031             return ((intdual *)a)->compare((*(intdual *)b));
00032         }
00033 };
00034 
00035 void FEM_REFINE2D_Init(){
00036   REFINE2D_Init();  
00037 }
00038 
00039 FLINKAGE void FTN_NAME(FEM_REFINE2D_INIT,fem_refine2d_init)(void)
00040 {
00041   FEM_REFINE2D_Init();
00042 }
00043 
00044 
00045 
00046 
00047 void FEM_REFINE2D_Newmesh(int meshID,int nodeID,int elemID){
00048     int nelems = FEM_Mesh_get_length(meshID,elemID);
00049     int nghost = FEM_Mesh_get_length(meshID,elemID+FEM_GHOST);
00050     int total = nghost + nelems;
00051     int *tempMesh = new int[3*total];
00052     FEM_Mesh_data(meshID,elemID,FEM_CONN,&tempMesh[0],0,nelems,FEM_INDEX_0,3);
00053     FEM_Mesh_data(meshID,elemID+FEM_GHOST,FEM_CONN,&tempMesh[3*nelems],0,nghost,FEM_INDEX_0,3);
00054 
00055     for(int t=nelems;t<total;t++){
00056         for(int j=0;j<3;j++){
00057             if(FEM_Is_ghost_index(tempMesh[3*t+j])){
00058                 tempMesh[3*t+j] += nelems;
00059             }
00060         }   
00061     }
00062     int maxnode=0,maxid=0;
00063     for(int i=0;i<3*total;i++){
00064         if(tempMesh[i] > maxnode){
00065             maxnode = tempMesh[i];
00066             maxid=i;
00067         }
00068     }
00069   
00070     int myID = FEM_My_partition();
00071   int *gid=new int[2*total];
00072   for (int i=0;i<nelems;i++) {
00073     gid[2*i+0]=myID; 
00074     gid[2*i+1]=i; 
00075   }
00076   int gid_fid=FEM_Create_field(FEM_INT,2,0,2*sizeof(int));
00077   FEM_Update_ghost_field(gid_fid,0,gid);
00078     
00079   
00080   printf("NewMesh %d %d %d maxid %d \n",nelems,total,maxnode,maxid);
00081   REFINE2D_NewMesh(nelems,total,(int *)tempMesh,gid);
00082     delete [] gid;
00083     delete [] tempMesh;
00084 }
00085 
00086 FLINKAGE void FTN_NAME(FEM_REFINE2D_NEWMESH,fem_refine2d_newmesh)(int *meshID,int *nodeID,int *elemID){
00087     FEM_REFINE2D_Newmesh(*meshID,*nodeID,*elemID);
00088 }
00089 
00090 
00091 
00092 void FEM_REFINE2D_Split(int meshID,int nodeID,double *coord,int elemID,double *desiredAreas,int sparseID){
00093     int nnodes = FEM_Mesh_get_length(meshID,nodeID);
00094     int nelems = FEM_Mesh_get_length(meshID,elemID);
00095 
00096     printf("%d %d \n",nnodes,nelems);   
00097     for(int k=0;k<nnodes;k++){
00098         printf(" node %d ( %.6f %.6f )\n",k,coord[2*k+0],coord[2*k+1]);
00099     }
00100     REFINE2D_Split(nnodes,coord,nelems,desiredAreas);
00101     int nSplits=REFINE2D_Get_Split_Length();
00102     printf("called REFINE2D_Split nSplits %d\n",nSplits);
00103     
00104   
00105     if(nSplits == 0){
00106         return;
00107     }
00108 
00109     
00110 
00111 
00112 
00113 
00114     CkVec<double> coordVec;
00115     for(int i=0;i<nnodes*2;i++){
00116         coordVec.push_back(coord[i]);
00117     }
00118     
00119     
00120 
00121     FEM_Entity *e=FEM_Entity_lookup(meshID,nodeID,"REFINE2D_Mesh");
00122     CkVec<FEM_Attribute *> *attrs = e->getAttrVec();
00123     
00124     
00125 
00126 
00127     FEM_Entity *elem = FEM_Entity_lookup(meshID,elemID,"REFIN2D_Mesh_elem");
00128     CkVec<FEM_Attribute *> *elemattrs = elem->getAttrVec();
00129     FEM_Attribute *connAttr = elem->lookup(FEM_CONN,"REFINE2D_Mesh");
00130     if(connAttr == NULL){
00131         CkAbort("Grrrr element without connectivity \n");
00132     }
00133     AllocTable2d<int> &connTable = ((FEM_IndexAttribute *)connAttr)->get();
00134 
00135     
00136 
00137 
00138 
00139 
00140     FEM_Entity *sparse;
00141     CkVec<FEM_Attribute *> *sparseattrs;
00142     FEM_Attribute *sparseConnAttr, *sparseBoundaryAttr;
00143     AllocTable2d<int> *sparseConnTable, *sparseBoundaryTable;
00144     CkHashtableT<intdual,int> nodes2sparse;
00145     if(sparseID != -1){
00146         sparse = FEM_Entity_lookup(meshID,sparseID,"REFINE2D_Mesh_sparse");
00147         sparseattrs = sparse->getAttrVec();
00148         sparseConnAttr = sparse->lookup(FEM_CONN,"REFINE2D_Mesh_sparse");
00149         sparseConnTable = &(((FEM_IndexAttribute *)sparseConnAttr)->get());
00150         sparseBoundaryAttr = sparse->lookup(FEM_BOUNDARY,"REFINE2D_Mesh_sparse");
00151         if(sparseBoundaryAttr == NULL){
00152              CkAbort("Specified sparse elements without boundary conditions");
00153         }
00154         
00155 
00156 
00157 
00158 
00159 
00160 
00161         for(int j=0;j<sparse->size();j++){
00162             int *cdata = (*sparseConnTable)[j];
00163     
00164             nodes2sparse.put(intdual(cdata[0],cdata[1])) = j+1;
00165         }
00166     }
00167     
00168   for (int splitNo=0;splitNo<nSplits;splitNo++){
00169     int tri,A,B,C,D;
00170     double frac;
00171         
00172         int cur_nodes = FEM_Mesh_get_length(meshID,nodeID);
00173         int *connData = connTable.getData();
00174         int flags;
00175 
00176 
00177         REFINE2D_Get_Split(splitNo,(int *)(connData),&tri,&A,&B,&C,&frac,&flags);
00178         if((flags & 0x1) || (flags & 0x2)){         
00179             
00180             D = cur_nodes;
00181       CkPrintf("---- Adding node %d\n",D);                  
00182         
00183 
00184 
00185       if (A>=cur_nodes) CkAbort("Calculated A is invalid!");
00186       if (B>=cur_nodes) CkAbort("Calculated B is invalid!");
00187                 CmiMemoryCheck();
00188             
00189 
00190 
00191             printf("new node added %d between %d (%.6f,%.6f) %d (%.6f,%.6f)\n",D,A,coordVec[2*A],coordVec[2*A+1],B,coordVec[2*B],coordVec[2*B+1]);                      
00192             e->setLength(cur_nodes+1);
00193             for(int i=0;i<attrs->size();i++){
00194                 FEM_Attribute *a = (FEM_Attribute *)(*attrs)[i];
00195                 if(a->getAttr()<FEM_ATTRIB_TAG_MAX){
00196                     FEM_DataAttribute *d = (FEM_DataAttribute *)a;
00197                     d->interpolate(A,B,D,frac);
00198                 }else{
00199                         
00200 
00201 
00202                         if(a->getAttr() == FEM_BOUNDARY){
00203                             if(sparseID != -1){
00204                                 int sidx = nodes2sparse.get(intdual(A,B))-1;
00205                                 if(sidx == -1){
00206                                     CkAbort("no sparse element between these 2 nodes, are they really connected ??");
00207                                 }
00208                                 sparseBoundaryTable = &(((FEM_DataAttribute *)sparseBoundaryAttr)->getInt());
00209                                 int boundaryVal = ((*sparseBoundaryTable)[sidx])[0];
00210                                 (((FEM_DataAttribute *)a)->getInt()[D])[0] = boundaryVal;
00211                             }else{
00212                                 
00213 
00214 
00215 
00216                                 FEM_DataAttribute *d = (FEM_DataAttribute *)a;
00217                                 d->interpolate(A,B,D,frac);
00218                             }
00219                         }
00220                 }   
00221             }
00222             int AandB[2];
00223       AandB[0]=A;
00224           AandB[1]=B;
00225       
00226           IDXL_Add_entity(FEM_Comm_shared(meshID,nodeID),D,2,AandB);
00227             double Dx = coord[2*A]*(1-frac)+frac*coord[2*B];
00228             double Dy = coord[2*A+1]*(1-frac)+frac*coord[2*B+1];                
00229             coordVec.push_back(Dx);
00230             coordVec.push_back(Dy);
00231             
00232 
00233 
00234 
00235             if(sparseID != -1){
00236                 int oldsidx = nodes2sparse.get(intdual(A,B))-1;
00237                 int newsidx = sparse->size();
00238                 sparse->setLength(newsidx+1);
00239                 for(int satt = 0;satt<sparseattrs->size();satt++){
00240                     if((*sparseattrs)[satt]->getAttr() == FEM_CONN){
00241                         
00242 
00243 
00244 
00245                         sparseConnTable = &(((FEM_IndexAttribute *)sparseConnAttr)->get());
00246                         int *oldconn = (*sparseConnTable)[oldsidx];
00247                         int *newconn = (*sparseConnTable)[newsidx];
00248                         oldconn[0] = A;
00249                         oldconn[1] = D;
00250                         
00251                         newconn[0] = D;
00252                         newconn[1] = B;
00253                         
00254 
00255                     }else{
00256                         
00257 
00258 
00259                         FEM_Attribute *attr = (FEM_Attribute *)(*sparseattrs)[satt];
00260                         attr->copyEntity(newsidx,*attr,oldsidx);
00261                     }
00262                 }
00263                 
00264 
00265 
00266 
00267                 nodes2sparse.remove(intdual(A,B));
00268                 nodes2sparse.put(intdual(A,D)) = oldsidx+1;
00269                 nodes2sparse.put(intdual(D,B)) = newsidx+1;
00270             }
00271             
00272         }
00273         
00274         
00275         
00276         
00277         
00278         int newTri =  FEM_Mesh_get_length(meshID,elemID);
00279     CkPrintf("---- Adding triangle %d after splitting %d \n",newTri,tri);
00280         elem->setLength(newTri+1);
00281         for(int j=0;j<elemattrs->size();j++){
00282             if((*elemattrs)[j]->getAttr() == FEM_CONN){
00283                 CkPrintf("elem attr conn code %d \n",(*elemattrs)[j]->getAttr());
00284                 
00285                 FEM_IndexAttribute *connAttr = (FEM_IndexAttribute *)(*elemattrs)[j];
00286                 AllocTable2d<int> &table = connAttr->get();
00287                 CkPrintf("Table of connectivity attribute starts at %p width %d \n",table[0],connAttr->getWidth());
00288                 int *oldRow = table[tri];
00289                 int *newRow = table[newTri];
00290                 for (int i=0;i<3;i++){
00291               if (oldRow[i]==A){
00292                         oldRow[i]=D;    
00293                         CkPrintf("In triangle %d %d replaced by %d \n",tri,A,D);
00294                     }   
00295                 }   
00296                 for (int i=0; i<3; i++) {
00297               if (oldRow[i] == B){
00298                         newRow[i] = D;
00299                     }   
00300             else if (oldRow[i] == C){
00301                         newRow[i] = C;
00302                     }   
00303               else if (oldRow[i] == D){
00304                         newRow[i] = A;
00305                     }   
00306             }
00307                 CkPrintf("New Triangle %d  (%d %d %d) conn %p\n",newTri,newRow[0],newRow[1],newRow[2],newRow);
00308             }else{
00309                 FEM_Attribute *elattr = (FEM_Attribute *)(*elemattrs)[j];
00310                 if(elattr->getAttr() < FEM_ATTRIB_FIRST){ 
00311                     elattr->copyEntity(newTri,*elattr,tri);
00312                 }   
00313             }
00314         }
00315         if(sparseID != -1){
00316             
00317 
00318 
00319             int cdidx = sparse->size();
00320             sparse->setLength(cdidx+1);
00321             for(int satt = 0; satt < sparseattrs->size();satt++){
00322                     if((*sparseattrs)[satt]->getAttr() == FEM_CONN){
00323                         sparseConnTable = &(((FEM_IndexAttribute *)sparseConnAttr)->get());
00324                         int *cdconn = (*sparseConnTable)[cdidx];
00325                         cdconn[0]=C;
00326                         cdconn[1]=D;
00327                     }
00328                     if((*sparseattrs)[satt]->getAttr() == FEM_BOUNDARY){
00329                         
00330 
00331 
00332                         sparseBoundaryTable = &(((FEM_DataAttribute *)sparseBoundaryAttr)->getInt());
00333                         ((*sparseBoundaryTable)[cdidx])[0] = 0;
00334                     }
00335             }
00336             nodes2sparse.put(intdual(C,D)) = cdidx+1;
00337         }
00338         
00339     }
00340     printf("Cordinate list length %d \n",coordVec.size()/2);
00341     IDXL_Sort_2d(FEM_Comm_shared(meshID,nodeID),coordVec.getVec());
00342     
00343 }
00344 
00345 FLINKAGE void FTN_NAME(FEM_REFINE2D_SPLIT,fem_refine2d_split)(int *meshID,int *nodeID,double *coord,int *elemID,double *desiredAreas){
00346     FEM_REFINE2D_Split(*meshID,*nodeID,coord,*elemID,desiredAreas);
00347 }