00001 
00002 
00003 
00004 
00005 
00006 
00007 #include "fem_util.h"
00008 #include "fem_mesh_modify.h"
00009 #include <vector>
00010 
00011 extern void splitEntity(IDXL_Side &c, int localIdx, int nBetween, int *between, int idxbase);
00012 
00013 FEM_MUtil::FEM_MUtil(int i, femMeshModify *m) {
00014   idx = i;
00015   mmod = m;
00016 }
00017 
00018 FEM_MUtil::~FEM_MUtil() {
00019 }
00020 
00021 void FEM_MUtil::getChunkNos(int entType, int entNo, int *numChunks, IDXL_Share ***chunks, int elemType) {
00022   int type = 0; 
00023 
00024 #ifdef DEBUG 
00025   CmiMemoryCheck(); 
00026 #endif
00027   if(entType == 0) { 
00028     
00029     if(FEM_Is_ghost_index(entNo)) type = 2;
00030     else if(isShared(entNo)) type = 1;
00031     else type = 0;
00032 
00033     if(type == 2) {
00034       int ghostid = FEM_To_ghost_index(entNo);
00035       int noShared = 0;
00036       const IDXL_Rec *irec = mmod->fmMesh->node.ghost->ghostRecv.getRec(ghostid);
00037       if(irec) {
00038     noShared = irec->getShared(); 
00039     
00040     *numChunks = noShared;
00041     *chunks = (IDXL_Share**)malloc((*numChunks)*sizeof(IDXL_Share*));
00042     int i=0;
00043     for(i=0; i<*numChunks; i++) {
00044       int chk = irec->getChk(i); 
00045       int index = -1; 
00046       (*chunks)[i] = new IDXL_Share(chk, index);
00047     }
00048     
00049       }
00050       else { 
00051     *numChunks = 0;
00052       }
00053     }
00054     else if(type == 1) {
00055       const IDXL_Rec *irec = mmod->fmMesh->node.shared.getRec(entNo);
00056       if(irec) {
00057     *numChunks = irec->getShared() + 1; 
00058     *chunks = (IDXL_Share**)malloc((*numChunks)*sizeof(IDXL_Share*));
00059     int i=0;
00060     for(i=0; i<*numChunks-1; i++) {
00061       int chk = irec->getChk(i);
00062       int index = irec->getIdx(i);
00063       (*chunks)[i] = new IDXL_Share(chk, index);
00064     }
00065     (*chunks)[i] = new IDXL_Share(idx, -1);
00066       }
00067       else { 
00068     *numChunks = 0;
00069       }
00070     }
00071     else if(type == 0) {
00072       *numChunks = 0;
00073       *chunks = (IDXL_Share**)malloc((*numChunks)*sizeof(IDXL_Share*));
00074       for(int i=0; i<*numChunks; i++) {
00075     int chk = idx; 
00076     int index = entNo;
00077     (*chunks)[i] = new IDXL_Share(chk, index);
00078       }
00079     }
00080   }
00081   else if(entType == 1) { 
00082     
00083     if(FEM_Is_ghost_index(entNo)) type = 2;
00084     else type = 0;
00085 
00086     if(type == 2) {
00087       int ghostid = FEM_To_ghost_index(entNo);
00088       const IDXL_Rec *irec = mmod->fmMesh->elem[elemType].ghost->ghostRecv.getRec(ghostid);
00089       if(irec) {
00090     *numChunks = irec->getShared(); 
00091     *chunks = (IDXL_Share**)malloc((*numChunks)*sizeof(IDXL_Share*));
00092     for(int i=0; i<*numChunks; i++) {
00093       int chk = irec->getChk(i);
00094       int index = irec->getIdx(i);
00095       (*chunks)[i] = new IDXL_Share(chk, index);
00096     }
00097       }
00098       else { 
00099     *numChunks = 0;
00100       }
00101     }
00102     else if(type == 0) {
00103       *numChunks = 0;
00104       *chunks = (IDXL_Share**)malloc((*numChunks)*sizeof(IDXL_Share*));
00105       for(int i=0; i<*numChunks; i++) {
00106     int chk = idx; 
00107     int index = entNo;
00108     (*chunks)[i] = new IDXL_Share(chk, index);
00109       }
00110     }
00111   }
00112 #ifdef DEBUG 
00113   CmiMemoryCheck(); 
00114 #endif
00115   return;
00116 }
00117 
00118 bool FEM_MUtil::isShared(int index) {
00119   
00120   
00121   const IDXL_Rec *irec = mmod->fmMesh->node.shared.getRec(index);
00122 #ifdef DEBUG 
00123   CmiMemoryCheck(); 
00124 #endif
00125   
00126   if(irec != NULL) return true;
00127   return false;
00128 }
00129 
00130 
00131 
00132 
00133 void FEM_MUtil::splitEntityAll(FEM_Mesh *m, int localIdx, int nBetween, int *between)
00134 {
00135   
00136   IDXL_Side *c = &(m->node.shared);
00137   const IDXL_Rec **tween = (const IDXL_Rec **)malloc(nBetween*sizeof(IDXL_Rec *));
00138   
00139   
00140   
00141   tween[0] = c->getRec(between[0]);
00142   for (int zs=tween[0]->getShared()-1; zs>=0; zs--) {
00143     for (int w1=0; w1<nBetween; w1++) {
00144       tween[w1] = c->getRec(between[w1]);
00145     }
00146     int chk = tween[0]->getChk(zs);
00147 #ifdef DEBUG 
00148     CmiMemoryCheck(); 
00149 #endif
00150 
00151     
00152     int w = 0;
00153     for (w=0; w<nBetween; w++) {
00154       if (!tween[w]->hasChk(chk)) {
00155     break;
00156       }
00157     }
00158 
00159     if (w == nBetween) {
00160       
00161       idxllock(m,chk,0); 
00162       c->addNode(localIdx,chk); 
00163 
00164       
00165       int *sharedIndices = (int *)malloc(nBetween*sizeof(int));
00166       const IDXL_List ll = m->node.shared.addList(chk);
00167       for(int w1=0; w1<nBetween; w1++) {
00168     for(int w2=0; w2<ll.size(); w2++) {
00169       if(ll[w2] == between[w1]) {
00170         sharedIndices[w1] = w2;
00171         break;
00172       }
00173     }
00174       }
00175       sharedNodeMsg *fm = new (nBetween, 0) sharedNodeMsg;
00176       fm->chk = mmod->idx;
00177       fm->nBetween = nBetween;
00178       for(int j=0; j<nBetween; j++) {
00179     fm->between[j] = sharedIndices[j];
00180       }
00181       meshMod[chk].addSharedNodeRemote(fm);
00182       idxlunlock(m,chk,0); 
00183       free(sharedIndices);
00184     }
00185   }
00186   free(tween);
00187   return;
00188 }
00189 
00190 
00191 void FEM_MUtil::splitEntitySharing(FEM_Mesh *m, int localIdx, int nBetween, int *between, int numChunks, int *chunks)
00192 {
00193   for(int i=0; i<numChunks; i++) {
00194     int chk = chunks[i];
00195     if(chk==idx) continue;
00196     sharedNodeMsg *fm = new (nBetween, 0) sharedNodeMsg;
00197     fm->chk = idx;
00198     fm->nBetween = nBetween;
00199     for(int j=0; j<nBetween; j++) {
00200       fm->between[j] = exists_in_IDXL(m,between[j],chk,0);
00201       CkAssert(fm->between[j]!=-1);
00202     }
00203     idxllock(m,chk,0); 
00204     m->node.shared.addNode(localIdx,chk); 
00205     meshMod[chk].addSharedNodeRemote(fm);
00206     idxlunlock(m,chk,0); 
00207   }
00208   return;
00209 }
00210 
00211 void FEM_MUtil::splitEntityRemote(FEM_Mesh *m, int chk, int localIdx, int nBetween, int *between)
00212 {
00213   
00214   int *localIndices = (int *)malloc(nBetween*sizeof(int));
00215   const IDXL_List ll = m->node.shared.addList(chk);
00216   for(int i=0; i<nBetween; i++) {
00217     localIndices[i] = ll[between[i]];
00218   }
00219 
00220 #ifdef DEBUG 
00221   CmiMemoryCheck(); 
00222 #endif
00223   FEM_Interpolate *inp = m->getfmMM()->getfmInp();
00224   FEM_Interpolate::NodalArgs nm;
00225   nm.n = localIdx;
00226   for(int i=0; i<nBetween; i++) {
00227     nm.nodes[i] = localIndices[i];
00228   }
00229   nm.frac = 0.5;
00230   nm.addNode = true;
00231   inp->FEM_InterpolateNodeOnEdge(nm);
00232 
00233   m->node.shared.addNode(localIdx,chk);
00234   free(localIndices);
00235   return;
00236 }
00237 
00238 void FEM_MUtil::removeNodeAll(FEM_Mesh *m, int localIdx)
00239 {
00240   IDXL_Side *c = &(m->node.shared);
00241   const IDXL_Rec *tween = c->getRec(localIdx);
00242   int size = 0;
00243   if(tween) 
00244     size = tween->getShared();
00245   if(size>0) {
00246     int *schunks = (int*)malloc(size*sizeof(int));
00247     int *sidx = (int*)malloc(size*sizeof(int));
00248     for(int i=0; i<size; i++) {
00249       schunks[i] = tween->getChk(i);
00250       sidx[i] = tween->getIdx(i);
00251     }
00252     for(int i=0; i<size; i++) {
00253       removeSharedNodeMsg *fm = new removeSharedNodeMsg;
00254       fm->chk = mmod->idx;
00255       fm->index = sidx[i];
00256       meshMod[schunks[i]].removeSharedNodeRemote(fm);
00257       m->node.shared.removeNode(localIdx, schunks[i]);      
00258 #ifdef DEBUG 
00259       CmiMemoryCheck(); 
00260 #endif
00261     }
00262     free(schunks);
00263     free(sidx);
00264   }
00265   
00266   FEM_remove_node_local(m,localIdx);
00267   return;
00268 }
00269 
00270 
00271 int FEM_MUtil::exists_in_IDXL(FEM_Mesh *m, int localIdx, int chk, int type, int elemType) {
00272   int exists  = -1;
00273   IDXL_List ll;
00274   if(type == 0) { 
00275     ll = m->node.shared.addList(chk);
00276   }
00277   else if(type == 1) { 
00278     ll = m->node.ghostSend.addList(chk);
00279   }
00280   else if(type == 2) { 
00281     ll = m->node.ghost->ghostRecv.addList(chk);
00282     localIdx = FEM_To_ghost_index(localIdx);
00283   }
00284   else if(type == 3) { 
00285     ll = m->elem[elemType].ghostSend.addList(chk);
00286   }
00287   else if(type == 4) { 
00288     ll = m->elem[elemType].ghost->ghostRecv.addList(chk);
00289     localIdx = FEM_To_ghost_index(localIdx);
00290   }
00291 #ifdef DEBUG 
00292   CmiMemoryCheck();
00293 #endif
00294   for(int w2=0; w2<ll.size(); w2++) {
00295     if(ll[w2] == localIdx) {
00296       exists = w2;
00297       break;
00298     }
00299   }
00300   return exists;
00301 }
00302 
00303 void FEM_MUtil::removeNodeRemote(FEM_Mesh *m, int chk, int sharedIdx) {
00304   int localIdx;
00305   const IDXL_List ll = m->node.shared.addList(chk);
00306   localIdx = ll[sharedIdx];
00307   m->node.shared.removeNode(localIdx, chk);
00308 #ifdef DEBUG 
00309   CmiMemoryCheck(); 
00310 #endif
00311   FEM_remove_node_local(m,localIdx);
00312   return;
00313 }
00314 
00315 void FEM_MUtil::removeGhostNodeRemote(FEM_Mesh *m, int fromChk, int sharedIdx) {
00316   int localIdx = lookup_in_IDXL(m,sharedIdx,fromChk,2); 
00317   if(localIdx >= 0) {
00318     m->node.ghost->ghostRecv.removeNode(localIdx, fromChk);
00319     if(m->node.ghost->ghostRecv.getRec(localIdx)==NULL) {
00320       int ghostid = FEM_To_ghost_index(localIdx);
00321       int numAdjNodes, numAdjElts;
00322       int *adjNodes, *adjElts;
00323       m->n2n_getAll(ghostid, &adjNodes, &numAdjNodes);
00324       m->n2e_getAll(ghostid, &adjElts, &numAdjElts);
00325       
00326       
00327 #ifdef DEBUG 
00328       CmiMemoryCheck(); 
00329 #endif
00330       if(!((numAdjNodes==0) && (numAdjElts==0))) {
00331     CkPrintf("Error: Node %d cannot be removed, it is connected to :\n",ghostid);
00332     FEM_Print_n2e(m,ghostid);
00333     FEM_Print_n2n(m,ghostid);
00334       }
00335       
00336       m->node.ghost->set_invalid(localIdx,true);
00337     }
00338     
00339   }
00340   return;
00341 }
00342 
00343 void FEM_MUtil::addGhostElementRemote(FEM_Mesh *m, int chk, int elemType, int numGhostIndices, int *ghostIndices, int numSharedIndices, int *sharedIndices, int connSize) {
00344   int numNewGhostIndices = connSize - (numGhostIndices + numSharedIndices);
00345   int *conn = (int *)malloc(connSize*sizeof(int));
00346   for(int i=0; i<numNewGhostIndices; i++) {
00347     
00348     int newGhostNode = FEM_add_node_local(m, 1);
00349     m->node.ghost->ghostRecv.addNode(newGhostNode,chk);
00350     
00351     int sharedIdx = exists_in_IDXL(m,FEM_To_ghost_index(newGhostNode),chk,2);
00352     int2Msg *i2 = new int2Msg(idx, sharedIdx);
00353     chunkListMsg *clm = meshMod[chk].getChunksSharingGhostNode(i2);
00354     conn[i] = FEM_To_ghost_index(newGhostNode);
00355     for(int j=0; j<clm->numChunkList; j++) {
00356       if(clm->chunkList[j]==idx) continue;
00357       int chk1 = clm->chunkList[j];
00358       int sharedIdx1 = clm->indexList[j];
00359       idxllock(m,chk1,0);
00360       m->node.ghost->ghostRecv.addNode(newGhostNode,chk1);
00361       
00362       meshMod[chk1].addTransIDXLRemote(idx,sharedIdx1,chk);
00363       idxlunlock(m,chk1,0);
00364     }
00365     FEM_Ghost_Essential_attributes(m, mmod->fmAdaptAlgs->coord_attr, FEM_BOUNDARY, conn[i]);
00366   }
00367   
00368   const IDXL_List ll1 = m->node.ghost->ghostRecv.addList(chk);
00369   for(int i=0; i<numGhostIndices; i++) {
00370     conn[i+numNewGhostIndices] = FEM_To_ghost_index(ll1[ghostIndices[i]]);
00371   }
00372   
00373 #ifdef DEBUG 
00374   CmiMemoryCheck(); 
00375 #endif
00376   const IDXL_List ll2 = m->node.shared.addList(chk);
00377   for(int i=0; i<numSharedIndices; i++) {
00378     conn[i+numNewGhostIndices+numGhostIndices] = ll2[sharedIndices[i]];
00379   }
00380   int newGhostElement = FEM_add_element_local(m, conn, connSize, elemType, 1);
00381   m->elem[elemType].ghost->ghostRecv.addNode(FEM_To_ghost_index(newGhostElement),chk);
00382   free(conn);
00383   return;
00384 }
00385 
00386 chunkListMsg *FEM_MUtil::getChunksSharingGhostNodeRemote(FEM_Mesh *m, int chk, int sharedIdx) {
00387   const IDXL_List ll = m->node.ghostSend.addList(chk);
00388   int localIdx = ll[sharedIdx];
00389   int numChunkList = 0;
00390   const IDXL_Rec *tween = m->node.shared.getRec(localIdx);
00391   if(tween) {
00392     numChunkList = tween->getShared();
00393   }
00394 #ifdef DEBUG 
00395   CmiMemoryCheck(); 
00396 #endif
00397   chunkListMsg *clm = new (numChunkList, numChunkList, 0) chunkListMsg;
00398   clm->numChunkList = numChunkList;
00399   for(int i=0; i<numChunkList; i++) {
00400     clm->chunkList[i] = tween->getChk(i);
00401     clm->indexList[i] = tween->getIdx(i);
00402   }
00403   
00404   for(int i=0; i<numChunkList; i++) {
00405     for(int j=i+1; j<numChunkList; j++) {
00406       if(clm->chunkList[i]> clm->chunkList[j]) {
00407     int tmp = clm->chunkList[i];
00408     clm->chunkList[i] = clm->chunkList[j];
00409     clm->chunkList[j] = tmp;
00410     tmp = clm->indexList[i];
00411     clm->indexList[i] = clm->indexList[j];
00412     clm->indexList[j] = tmp;
00413       }
00414     }
00415   }
00416   return clm;
00417 }
00418 
00419 void FEM_MUtil::buildChunkToNodeTable(int *nodetype, int sharedcount, int ghostcount, int localcount, int *conn, int connSize, CkVec<int> ***allShared, int *numSharedChunks, CkVec<int> **allChunks, int ***sharedConn) {
00420   if((sharedcount > 0 && ghostcount == 0) || (ghostcount > 0 && localcount == 0)) { 
00421     *allShared = (CkVec<int> **)malloc(connSize*sizeof(CkVec<int> *));
00422     for(int i=0; i<connSize; i++) {
00423 #ifdef DEBUG 
00424       CmiMemoryCheck(); 
00425 #endif
00426       (*allShared)[i] = new CkVec<int>; 
00427       int numchunks;
00428       IDXL_Share **chunks1;
00429       if(nodetype[i] == 1) { 
00430     getChunkNos(0,conn[i],&numchunks,&chunks1);
00431       }
00432       else if(nodetype[i] == 2) { 
00433     getChunkNos(0,conn[i],&numchunks,&chunks1);
00434       }
00435       else if(nodetype[i] == 0) {
00436     numchunks = 1;
00437     (*allShared)[i]->push_back(getIdx());
00438       }
00439       if((nodetype[i] == 1) || (nodetype[i] == 2)) {
00440     for(int j=0; j<numchunks; j++) {
00441       (*allShared)[i]->push_back(chunks1[j]->chk);
00442     }
00443       }
00444       if(nodetype[i]==1 || nodetype[i]==2) {
00445     for(int j=0; j<numchunks; j++) {
00446       delete chunks1[j];
00447     }
00448     if(numchunks!=0) free(chunks1);
00449       }
00450     }
00451     
00452     *allChunks = new CkVec<int>;
00453     for(int i=0; i<connSize; i++) {
00454       for(int j=0; j<(*allShared)[i]->size(); j++) {
00455     int exists = 0;
00456     for(int k=0; k<(*allChunks)->size(); k++) {
00457       if((*(*allChunks))[k]==(*(*allShared)[i])[j]) {
00458         exists = 1;
00459         break;
00460       }
00461     }
00462     if(!exists) {
00463       (*allChunks)->push_back((*(*allShared)[i])[j]);
00464       (*numSharedChunks)++;
00465     }
00466       }
00467     }
00468     *sharedConn = (int **)malloc((*numSharedChunks)*sizeof(int *));
00469     for(int j=0; j<*numSharedChunks; j++) {
00470       (*sharedConn)[j] = (int *)malloc(connSize*sizeof(int));
00471     }
00472     int index = getIdx();
00473     for(int i=0; i<connSize; i++) {
00474       
00475       int chkindex = -1;
00476       if((nodetype[i] == 1) || (nodetype[i] == 2)) {
00477     for(int j=0; j<(*numSharedChunks); j++) {
00478       (*sharedConn)[j][i] = -1;
00479     }
00480     for(int j=0; j<(*allShared)[i]->size(); j++) {
00481       for(int k=0; k<*numSharedChunks; k++) {
00482         if((*(*allShared)[i])[j] == (*(*allChunks))[k]) chkindex = k;
00483       }
00484       (*sharedConn)[chkindex][i] = 1; 
00485     }
00486     if(nodetype[i] == 2) {
00487       for(int k=0; k<*numSharedChunks; k++) {
00488         if(index == (*(*allChunks))[k]) chkindex = k;
00489       }
00490       (*sharedConn)[chkindex][i] = 2;
00491       if((*allShared)[i]->size()==1) {
00492         for(int k=0; k<*numSharedChunks; k++) {
00493           if((*(*allShared)[i])[0] == (*(*allChunks))[k]) chkindex = k;
00494         }
00495         (*sharedConn)[chkindex][i] = 0;
00496       }
00497     }
00498       }
00499       else {
00500     
00501     for(int j=0; j<(*numSharedChunks); j++) {
00502       (*sharedConn)[j][i] = -1; 
00503     }
00504     for(int k=0; k<*numSharedChunks; k++) {
00505       if(index == (*(*allChunks))[k]) chkindex = k;
00506     }
00507     (*sharedConn)[chkindex][i] = 0;
00508       }
00509     }
00510   }
00511 #ifdef DEBUG 
00512   CmiMemoryCheck(); 
00513 #endif
00514   CkAssert(*numSharedChunks>0);
00515   return;
00516 }
00517 
00518 void FEM_MUtil::addElemRemote(FEM_Mesh *m, int chk, int elemtype, int connSize, int *conn, int numGhostIndex, int *ghostIndices) {
00519   
00520   
00521   
00522   const IDXL_List ll1 = m->node.ghostSend.addList(chk);
00523   const IDXL_List ll2 = m->node.shared.addList(chk);
00524 
00525   int *localIndices = (int *)malloc(connSize*sizeof(int));
00526   int j=0;
00527   int ghostsRemaining = numGhostIndex;
00528   for(int i=0; i<connSize; i++) {
00529     if(ghostsRemaining > 0) {
00530       if(ghostIndices[j] == i) {
00531     localIndices[i] = ll1[conn[i]];
00532     ghostsRemaining--;
00533     j++;
00534       }
00535       else {
00536     localIndices[i] = ll2[conn[i]];
00537       }
00538     }
00539     else {
00540       localIndices[i] = ll2[conn[i]];
00541     }
00542   }
00543 
00544 #ifdef DEBUG 
00545   CmiMemoryCheck(); 
00546 #endif
00547   FEM_add_element(m, localIndices, connSize, elemtype, idx);
00548   free(localIndices);
00549   return;
00550 }
00551 
00552 
00553 void FEM_MUtil::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) {
00554   
00555   
00556   int localIdx;
00557   
00558   const IDXL_List lgre = m->elem[elemtype].ghost->ghostRecv.addList(chk);
00559   localIdx = lgre[elementid];
00560   if(localIdx == -1) {
00561     CkPrintf("Ghost element at shared index %d, already removed\n",elementid);
00562     return;
00563   }
00564 #ifdef DEBUG 
00565   CmiMemoryCheck(); 
00566 #endif
00567   
00568   
00569   FEM_remove_element_local(m, FEM_To_ghost_index(localIdx), elemtype);
00570 
00571   
00572   if(numGhostIndex > 0) {
00573     const IDXL_List lgrn = m->node.ghost->ghostRecv.addList(chk);
00574     for(int i=0; i<numGhostIndex; i++) {
00575       localIdx = lgrn[ghostIndices[i]];
00576       m->node.ghost->ghostRecv.removeNode(localIdx, chk); 
00577       if(m->node.ghost->ghostRecv.getRec(localIdx)) {
00578     
00579       }
00580       else {
00581     FEM_remove_node_local(m, FEM_To_ghost_index(localIdx));
00582       }
00583     }
00584   }
00585 
00586 #ifdef DEBUG 
00587   CmiMemoryCheck(); 
00588 #endif
00589   if(numGhostREIndex > 0) {
00590     const IDXL_List lgse = m->elem[elemtype].ghostSend.addList(chk);
00591     for(int i=0; i<numGhostREIndex; i++) {
00592       localIdx = lgse[ghostREIndices[i]];
00593       m->elem[elemtype].ghostSend.removeNode(localIdx, chk); 
00594     }
00595   }
00596 
00597   if(numGhostRNIndex > 0) {
00598     const IDXL_List lgsn = m->node.ghostSend.addList(chk);
00599     for(int i=0; i<numGhostRNIndex; i++) {
00600       localIdx = lgsn[ghostRNIndices[i]];
00601       m->node.ghostSend.removeNode(localIdx, chk); 
00602     }
00603   }
00604 
00605 #ifdef DEBUG 
00606   CmiMemoryCheck(); 
00607 #endif
00608   if(numSharedIndex > 0) { 
00609     const IDXL_List lsn = m->node.shared.addList(chk);
00610     for(int i=0; i<numSharedIndex; i++) {
00611       bool flag1 = true;
00612       
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 {
00626     if(sharedIndices[i]<0 && sharedIndices[i]>=-500000000) {
00627       sharedIndices[i] += 500000000;
00628       flag1 = false;
00629     }
00630     localIdx = lsn[sharedIndices[i]];
00631     if(flag1) m->node.ghostSend.addNode(localIdx, chk);
00632     m->node.shared.removeNode(localIdx, chk);
00633       }
00634     }
00635   }
00636 
00637   return;
00638 }
00639 
00640 void FEM_MUtil::removeElemRemote(FEM_Mesh *m, int chk, int elementid, int elemtype, int permanent) {
00641 
00642   const IDXL_List ll = m->elem[elemtype].ghostSend.addList(chk);
00643   int localIdx = ll[elementid];
00644   FEM_remove_element(m, localIdx, elemtype, permanent);
00645 #ifdef DEBUG 
00646   CmiMemoryCheck(); 
00647 #endif
00648   return;
00649 }
00650 
00651 int FEM_MUtil::lookup_in_IDXL(FEM_Mesh *m, int sharedIdx, int chk, int type, int elemType) {
00652   int localIdx  = -1;
00653   IDXL_List ll;
00654   if(type == 0) { 
00655     ll = m->node.shared.addList(chk);
00656   }
00657   else if(type == 1) { 
00658     ll = m->node.ghostSend.addList(chk);
00659   }
00660   else if(type == 2) { 
00661     ll = m->node.ghost->ghostRecv.addList(chk);
00662   }
00663   else if(type == 3) { 
00664     ll = m->elem[elemType].ghostSend.addList(chk);
00665   }
00666   else if(type == 4) { 
00667     ll = m->elem[elemType].ghost->ghostRecv.addList(chk);
00668   }
00669 #ifdef DEBUG 
00670   CmiMemoryCheck(); 
00671 #endif
00672   CkAssert(sharedIdx < ll.size());
00673   localIdx = ll[sharedIdx];
00674   return localIdx;
00675 }
00676 
00677 int FEM_MUtil::getRemoteIdx(FEM_Mesh *m, int elementid, int elemtype) {
00678   CkAssert(elementid < -1);
00679   int ghostid = FEM_To_ghost_index(elementid);
00680   const IDXL_Rec *irec = m->elem[elemtype].ghost->ghostRecv.getRec(ghostid);
00681   int size = irec->getShared();
00682 #ifdef DEBUG 
00683   CmiMemoryCheck(); 
00684 #endif
00685   CkAssert(size == 1);
00686   int remoteChunk = irec->getChk(0);
00687   int sharedIdx = irec->getIdx(0);
00688   return remoteChunk;
00689 }
00690 
00691 int FEM_MUtil::Replace_node_local(FEM_Mesh *m, int oldIdx, int newIdx) {
00692   
00693   if(newIdx==-1) {
00694     newIdx = m->node.size();
00695     m->node.setLength(newIdx+1); 
00696     m->node.set_valid(newIdx,true);   
00697     m->n2e_removeAll(newIdx);    
00698     m->n2n_removeAll(newIdx);    
00699     mmod->fmLockN.push_back(new FEM_lockN(newIdx,mmod));
00700     mmod->fmLockN[newIdx]->wlock(idx); 
00701   }
00702 
00703 #ifdef DEBUG 
00704   CmiMemoryCheck(); 
00705 #endif
00706   FEM_Interpolate *inp = mmod->getfmInp();
00707   inp->FEM_InterpolateCopyAttributes(oldIdx,newIdx);
00708   
00709   
00710   int *nnbrs;
00711   int nsize;
00712   m->n2n_getAll(oldIdx, &nnbrs, &nsize);
00713   m->n2n_removeAll(newIdx);
00714   for(int i=0; i<nsize; i++) {
00715     m->n2n_add(newIdx, nnbrs[i]);
00716     m->n2n_replace(nnbrs[i], oldIdx, newIdx);
00717   }
00718   int *enbrs;
00719   int esize;
00720   m->n2e_getAll(oldIdx, &enbrs, &esize);
00721   m->n2e_removeAll(newIdx);
00722   for(int i=0; i<esize; i++) {
00723     m->n2e_add(newIdx, enbrs[i]);
00724     m->e2n_replace(enbrs[i], oldIdx, newIdx, 0);
00725   }
00726 
00727   
00728 #ifdef DEBUG 
00729   CmiMemoryCheck(); 
00730 #endif
00731   m->n2n_removeAll(oldIdx);
00732   m->n2e_removeAll(oldIdx);
00733 
00734   if(nsize>0) delete[] nnbrs;
00735   if(esize>0) delete[] enbrs;
00736   return newIdx;  
00737 }
00738 
00739 void FEM_MUtil::addToSharedList(FEM_Mesh *m, int fromChk, int sharedIdx) {
00740   int elemType = 0;
00741   int connSize = m->elem[elemType].getConn().width();
00742   int localIdx = mmod->fmUtil->lookup_in_IDXL(m,sharedIdx,fromChk,1); 
00743 
00744   
00745   m->node.shared.addNode(localIdx, fromChk);
00746   m->node.ghostSend.removeNode(localIdx, fromChk);
00747 
00748   
00749   const IDXL_Rec *irec2 = m->node.ghostSend.getRec(localIdx);
00750   if(irec2!=NULL) {
00751     for(int i=0; i<irec2->getShared(); i++) {
00752       
00753       int pchk = irec2->getChk(i);
00754       int shidx = irec2->getIdx(i);
00755       meshMod[pchk].addghostsendr(idx,shidx,fromChk,exists_in_IDXL(m,localIdx,fromChk,0));
00756     }
00757   }
00758 
00759   int *enbrs;
00760   int esize;
00761   m->n2e_getAll(localIdx, &enbrs, &esize);
00762 #ifdef DEBUG 
00763   CmiMemoryCheck(); 
00764 #endif
00765   for(int i=0; i<esize; i++) {
00766     if(enbrs[i] >= 0) { 
00767       
00768       int exists = mmod->fmUtil->exists_in_IDXL(m, enbrs[i], fromChk, 3);
00769       if(exists == -1) {
00770     
00771     
00772     m->elem[elemType].ghostSend.addNode(enbrs[i], fromChk);
00773     
00774     int numNodesToAdd = 0;
00775     int numSharedGhosts = 0;
00776     int numSharedNodes = 0;
00777     int *sharedGhosts = (int *)malloc(connSize*sizeof(int));
00778     int *sharedNodes = (int *)malloc(connSize*sizeof(int));
00779     int *nnbrs = (int*)malloc(connSize*sizeof(int));
00780     int *nodesToAdd = (int*)malloc(connSize*sizeof(int));
00781     m->e2n_getAll(enbrs[i], nnbrs, elemType);
00782     for(int j=0; j<connSize; j++) {
00783 #ifdef DEBUG 
00784       CmiMemoryCheck(); 
00785 #endif
00786       int sharedNode = mmod->fmUtil->exists_in_IDXL(m,nnbrs[j],fromChk,0);
00787       if(sharedNode == -1) {
00788         
00789         int sharedGhost = mmod->fmUtil->exists_in_IDXL(m,nnbrs[j],fromChk,1);
00790         if( sharedGhost == -1) {
00791           
00792           
00793           const IDXL_Rec *irec = m->node.shared.getRec(nnbrs[j]);
00794           if(irec) {
00795         int noShared = irec->getShared();
00796         for(int sharedck=0; sharedck<noShared; sharedck++) {
00797           int ckshared = irec->getChk(sharedck);
00798           int idxshared = irec->getIdx(sharedck);
00799           if(ckshared == fromChk) continue;
00800           CkAssert(fromChk!=idx && fromChk!=ckshared && ckshared!=idx);
00801           int idxghostsend = meshMod[ckshared].getIdxGhostSend(idx,idxshared,fromChk)->i;
00802           if(idxghostsend != -1) {
00803             m->node.ghostSend.addNode(nnbrs[j],fromChk);
00804             meshMod[fromChk].updateIdxlList(idx,idxghostsend,ckshared);
00805             sharedGhost = exists_in_IDXL(m,nnbrs[j],fromChk,1);
00806             CkAssert(sharedGhost != -1);
00807             break; 
00808           }
00809           
00810         }
00811           }
00812           
00813         }
00814         if( sharedGhost == -1) {
00815           
00816           nodesToAdd[numNodesToAdd] = nnbrs[j];
00817           numNodesToAdd++;
00818         }
00819         else {
00820           
00821           sharedGhosts[numSharedGhosts] = sharedGhost;
00822           numSharedGhosts++;
00823         }
00824       }
00825       else {
00826         
00827         sharedNodes[numSharedNodes] = sharedNode;
00828         numSharedNodes++;
00829       }
00830     }
00831     
00832     addGhostElemMsg *fm = new (numSharedGhosts, numSharedNodes, 0)addGhostElemMsg;
00833     fm->chk = getIdx();
00834     fm->elemType = elemType;
00835     fm->numGhostIndex = numSharedGhosts;
00836     for(int j=0; j<numSharedGhosts; j++) {
00837       fm->ghostIndices[j] = sharedGhosts[j];
00838     }
00839     fm->numSharedIndex = numSharedNodes;
00840     for(int j=0; j<numSharedNodes; j++) {
00841       fm->sharedIndices[j] = sharedNodes[j];
00842     }
00843     for(int j=0; j<numNodesToAdd; j++) {
00844       m->node.ghostSend.addNode(nodesToAdd[j],fromChk);
00845     }
00846     fm->connSize = connSize;
00847     meshMod[fromChk].addGhostElem(fm); 
00848 
00849     for(int j=0; j<numNodesToAdd; j++) {
00850       
00851       
00852       const IDXL_Rec *irec1 = m->node.shared.getRec(nodesToAdd[j]);
00853       if(irec1!=NULL) {
00854         for(int sh=0; sh<irec1->getShared(); sh++) {
00855           int transIdx = exists_in_IDXL(m,nodesToAdd[j],fromChk,1);
00856           meshMod[irec1->getChk(sh)].addghostsendl(idx,irec1->getIdx(sh),fromChk,transIdx);
00857         }
00858       }
00859     }
00860 
00861     
00862     
00863     free(nodesToAdd);
00864     free(sharedGhosts);
00865     free(sharedNodes);
00866     free(nnbrs);
00867       }
00868     }
00869   }
00870 #ifdef DEBUG 
00871   CmiMemoryCheck(); 
00872 #endif
00873   delete[] enbrs;
00874   return;
00875 }
00876 
00877 
00878 void FEM_MUtil::findGhostSend(int nodeId, int **chunkl, int *numchunkl) {
00879   if(nodeId<0) return;
00880   CkVec<int> chkl;
00881   int *adjnds, numadjnds=0;
00882   mmod->fmMesh->n2n_getAll(nodeId, &adjnds, &numadjnds);
00883   for(int j=0; j<numadjnds; j++) {
00884     int node1 = adjnds[j];
00885     if(node1>=0) {
00886       const IDXL_Rec *irec = mmod->fmMesh->node.shared.getRec(node1);
00887       if(irec) {
00888     for(int k=0; k<irec->getShared(); k++) {
00889       int pchk = irec->getChk(k);
00890       
00891       
00892       if(exists_in_IDXL(mmod->fmMesh,nodeId,pchk,0)!=-1) continue;
00893       bool shouldadd=true;
00894       for(int l=0; l<chkl.size(); l++) {
00895         if(chkl[l]==pchk) {
00896           shouldadd=false;
00897           break;
00898         }
00899       }
00900       if(shouldadd) chkl.push_back(pchk);
00901     }
00902       }
00903     }
00904   }
00905   if(numadjnds>0) delete[] adjnds;
00906   *numchunkl = chkl.size();
00907   if(numchunkl>0) 
00908     *chunkl = new int[*numchunkl];
00909   for(int i=0;i<*numchunkl;i++) {
00910     (*chunkl)[i] = chkl[i];
00911   }
00912   
00913   chkl.free();
00914   return;
00915 }
00916 
00917 
00918 void FEM_MUtil::UpdateGhostSend(int nodeId, int *chunkl, int numchunkl) {
00919   if(nodeId<0) return;
00920   const IDXL_Rec *irec = mmod->fmMesh->node.ghostSend.getRec(nodeId);
00921   int numchunks=0;
00922   int *chunks1, *inds1;
00923   if(irec) {
00924     numchunks = irec->getShared();
00925     chunks1 = new int[numchunks];
00926     inds1 = new int[numchunks];
00927     for(int i=0; i<numchunks; i++) {
00928       chunks1[i] = irec->getChk(i);
00929       inds1[i] = irec->getIdx(i);
00930     }
00931   }
00932   for(int i=0; i<numchunks; i++) {
00933     bool shouldbeSent = false;
00934     for(int j=0; j<numchunkl; j++) { 
00935       if(chunks1[i]==chunkl[j]) {
00936     shouldbeSent=true;
00937     break;
00938       }
00939     }
00940     if(!shouldbeSent) {
00941       meshMod[chunks1[i]].removeGhostNode(idx, inds1[i]);
00942       mmod->fmMesh->node.ghostSend.removeNode(nodeId,chunks1[i]);
00943     }
00944   }
00945 
00946   if(numchunks>0) {
00947     delete[] chunks1;
00948     delete[] inds1;
00949   }
00950   return;
00951 }
00952 
00953 
00954 int FEM_MUtil::eatIntoElement(int localIdx) {
00955   CkAssert(FEM_Is_ghost_index(localIdx));
00956   int nodesPerEl = mmod->fmMesh->elem[0].getConn().width();
00957   int *adjnodes = new int[nodesPerEl];
00958   int *oldnodes = new int[nodesPerEl];
00959   mmod->fmMesh->e2n_getAll(localIdx, adjnodes, 0);
00960 #ifdef DEBUG_1
00961   CkPrintf("Chunk %d eating elem %d(%d,%d,%d)\n",idx,localIdx,adjnodes[0],adjnodes[1],adjnodes[2]);
00962 #endif
00963   int remChk = mmod->fmMesh->elem[0].ghost->ghostRecv.getRec(FEM_From_ghost_index(localIdx))->getChk(0);
00964   
00965   for(int i=0; i<nodesPerEl; i++) {
00966     if(FEM_Is_ghost_index(adjnodes[i])) { 
00967       
00968       int sharedIdx = exists_in_IDXL(mmod->fmMesh,adjnodes[i],remChk,2);
00969       meshMod[remChk].modifyLockAll(idx,sharedIdx);
00970     }
00971   }
00972   FEM_remove_element(mmod->fmMesh,localIdx,0,idx);
00973   for(int j=0; j<nodesPerEl; j++) oldnodes[j] = adjnodes[j];
00974   int newEl = FEM_add_element(mmod->fmMesh, adjnodes, nodesPerEl, 0, idx);
00975   copyElemData(0,localIdx,newEl); 
00976   FEM_purge_element(mmod->fmMesh,localIdx,0);
00977   for(int i=0; i<nodesPerEl; i++) {
00978     if(adjnodes[i]!=oldnodes[i]) {
00979       
00980       FEM_Modify_LockUpdate(mmod->fmMesh,adjnodes[i]);
00981     }
00982   }
00983   delete [] adjnodes;
00984   delete [] oldnodes;
00985   return newEl;
00986 }
00987 
00988 int FEM_MUtil::getLockOwner(int nodeId) {
00989   int owner = -1;
00990   if(nodeId>=0) {
00991     const IDXL_Rec *irec = mmod->fmMesh->node.shared.getRec(nodeId);
00992     
00993     int minchunk = MAX_CHUNK;
00994     if(irec) {
00995       for(int i=0; i<irec->getShared(); i++) {
00996     int pchk = irec->getChk(i);
00997     if(pchk<minchunk) minchunk = pchk;
00998       }
00999     }
01000     else minchunk = idx;
01001     if(minchunk == idx) owner = mmod->fmMesh->getfmMM()->getfmLockN(nodeId)->lockOwner();
01002     else {
01003       CkAssert(minchunk!=MAX_CHUNK);
01004       int sharedIdx = mmod->getfmUtil()->exists_in_IDXL(mmod->fmMesh,nodeId,minchunk,0);
01005       owner = meshMod[minchunk].hasLockRemoteNode(sharedIdx, idx, 0)->i;
01006     }
01007   }
01008   else {
01009     int otherchk = mmod->fmMesh->node.ghost->ghostRecv.getRec(FEM_From_ghost_index(nodeId))->getChk(0);
01010     int sharedIdx = mmod->fmMesh->node.ghost->ghostRecv.getRec(FEM_From_ghost_index(nodeId))->getIdx(0);
01011     owner = meshMod[otherchk].getLockOwner(idx, sharedIdx)->i;
01012   }
01013   
01014   return owner;
01015 }
01016 
01017 bool FEM_MUtil::knowsAbtNode(int chk, int nodeId) {
01018   if(nodeId >= 0) {
01019     const IDXL_Rec *irec = mmod->fmMesh->node.ghostSend.getRec(nodeId);
01020     if(irec) {
01021       for(int i=0; i<irec->getShared(); i++) {
01022     if(irec->getChk(i) == chk) return true;
01023       }
01024     }
01025     irec = mmod->fmMesh->node.shared.getRec(nodeId);
01026     if(irec) {
01027       for(int i=0; i<irec->getShared(); i++) {
01028     if(irec->getChk(i) == chk) return true;
01029       }
01030     }
01031   }
01032   else { 
01033     
01034     int owner = mmod->fmMesh->node.ghost->ghostRecv.getRec(FEM_From_ghost_index(nodeId))->getChk(0);
01035     int sharedIdx = mmod->fmMesh->node.ghost->ghostRecv.getRec(FEM_From_ghost_index(nodeId))->getIdx(0);
01036     
01037     return meshMod[owner].knowsAbtNode(idx, chk, sharedIdx)->b;
01038   }
01039   return false;
01040 }
01041 
01042 void FEM_MUtil::StructureTest(FEM_Mesh *m) {
01043   int noNodes = m->node.size();
01044   int noEle = m->elem[0].size();
01045   int noGhostEle = m->elem[0].ghost->size();
01046   int noGhostNodes = m->node.ghost->size();
01047 
01048   int wdt = m->elem[0].getConn().width();
01049   int *e2n = (int*)malloc(wdt*sizeof(int));
01050 
01051   for(int i=0; i<noEle; i++) {
01052     if(m->elem[0].is_valid(i)) {
01053       m->e2n_getAll(i,e2n,0);
01054       
01055       if(e2n[0]==e2n[1] || e2n[1]==e2n[2] || e2n[2]==e2n[0]) {
01056     CkPrintf("ERROR: element %d, has connectivity (%d,%d,%d)\n",i,e2n[0],e2n[1],e2n[2]);
01057     CkAssert(false);
01058       }
01059       
01060       if(e2n[0]<0 || e2n[1]<0 || e2n[2]<0) {
01061     CkPrintf("ERROR: element %d, has connectivity (%d,%d,%d)\n",i,e2n[0],e2n[1],e2n[2]);
01062     CkAssert(false);
01063       }
01064       for(int j=0; j<3; j++) {
01065     
01066     CkAssert(m->node.is_valid(e2n[j]));
01067       }
01068     }
01069   }
01070   for(int i=0; i<noGhostEle; i++) {
01071     if(m->elem[0].ghost->is_valid(i)) {
01072       int ghostIndex = FEM_To_ghost_index(i);
01073       m->e2n_getAll(ghostIndex,e2n,0);
01074       if(e2n[0]==e2n[1] || e2n[1]==e2n[2] || e2n[2]==e2n[0]) {
01075     
01076     CkPrintf("ERROR: element %d, has connectivity (%d,%d,%d)\n",ghostIndex,e2n[0],e2n[1],e2n[2]);
01077     CkAssert(false);
01078       }
01079       if(!(e2n[0]>=0 || e2n[1]>=0 || e2n[2]>=0)) {
01080     
01081     CkPrintf("ERROR: element %d, has connectivity (%d,%d,%d)\n",ghostIndex,e2n[0],e2n[1],e2n[2]);
01082     CkAssert(false);
01083       }
01084       for(int j=0; j<3; j++) {
01085     
01086     if(e2n[j]>=0) CkAssert(m->node.is_valid(e2n[j]));
01087     else CkAssert(m->node.ghost->is_valid(FEM_From_ghost_index(e2n[j])));
01088       }
01089     }
01090   }
01091 
01092   int *n2e, n2esize=0;
01093   int *n2n, n2nsize=0;
01094 
01095   for(int i=0; i<noNodes; i++) {
01096     if(m->node.is_valid(i)) {
01097       m->n2e_getAll(i,&n2e,&n2esize);
01098       m->n2n_getAll(i,&n2n,&n2nsize);
01099       if(n2esize!=n2nsize && n2nsize!=(n2esize+1)) {
01100     FEM_Print_coords(m,i);
01101     FEM_Print_n2e(m,i);
01102     FEM_Print_n2n(m,i);
01103     CkPrintf("ERROR: local node %d, with inconsistent adjacency list\n",i);
01104     CkAssert(false);
01105       }
01106     }
01107     else {
01108       continue;
01109     }
01110     if(n2esize > 0) {
01111       for(int j=0; j<n2esize; j++) {
01112     CkAssert(n2e[j]!=-1);
01113     if(FEM_Is_ghost_index(n2e[j])) CkAssert(m->elem[0].ghost->is_valid(FEM_From_ghost_index(n2e[j]))==1);
01114     else CkAssert(m->elem[0].is_valid(n2e[j])==1);
01115       }
01116 
01117       m->e2n_getAll(n2e[0],e2n,0);
01118 
01119       
01120       bool done = false;
01121       for(int j=0; j<n2esize; j++) {
01122     if(n2e[j] >= 0) {
01123       done = true; 
01124       break;
01125     }
01126       }
01127       if(!done) {
01128     FEM_Print_coords(m,i);
01129     FEM_Print_n2e(m,i);
01130     FEM_Print_n2n(m,i);
01131     CkPrintf("ERROR: isolated local node %d, with no local element connectivity\n",i);
01132     CkAssert(false);
01133       }
01134 
01135       
01136       int testnode = i;
01137       int startnode = (e2n[0]==testnode) ? e2n[1] : e2n[0];
01138       int othernode = (e2n[2]==testnode) ? e2n[1] : e2n[2];
01139       int previousnode = startnode;
01140       int nextnode = -1;
01141       int numdeadends = 0;
01142       int numunused = n2esize-1;
01143       n2e[0] = -1;
01144       for(int j=0; j<n2esize-1; j++) {
01145     nextnode = -1;
01146     for(int k=1; k<n2esize; k++) {
01147       if(n2e[k]==-1) continue;
01148       m->e2n_getAll(n2e[k],e2n,0);
01149       if(e2n[0]==previousnode || e2n[1]==previousnode || e2n[2]==previousnode) {
01150         nextnode = (e2n[0]==previousnode) ? ((e2n[1]==testnode)? e2n[2]:e2n[1]) : ((e2n[1]==previousnode)? ((e2n[0]==testnode)? e2n[2]:e2n[0]):((e2n[1]==testnode)? e2n[0]:e2n[1]));
01151         previousnode = nextnode;
01152         n2e[k] = -1;
01153         numunused--;
01154       }
01155     }
01156     if(nextnode==othernode && othernode!=-1) {
01157       
01158       break;
01159     }
01160     else if(nextnode==-1) {
01161       
01162       numdeadends++;
01163       previousnode = othernode;
01164       othernode = -1;
01165     }
01166     if(numdeadends>=2 && numunused!=0) {
01167       FEM_Print_coords(m,i);
01168       FEM_Print_n2e(m,i);
01169       FEM_Print_n2n(m,i);
01170       CkPrintf("ERROR: cloud connectivity of node %d is discontinuous\n",i);
01171       CkAssert(false);
01172     }
01173       }
01174       
01175       int n2n1size = 0;
01176       int *n2n1 = (int*)malloc(n2nsize*sizeof(int));
01177       int n2n1Count = 0;
01178       m->n2e_getAll(i,&n2e,&n2esize);
01179       for(int j=0; j<n2esize; j++) {
01180     CkAssert(n2e[j]!=-1);
01181     
01182     int e2n1[3];
01183     m->e2n_getAll(n2e[j],e2n1,0);
01184     if(e2n1[0]!=i && e2n1[1]!=i && e2n1[2]!=i) {
01185       FEM_Print_coords(m,i);
01186       FEM_Print_n2e(m,i);
01187       FEM_Print_e2n(m,n2e[j]);
01188       CkPrintf("ERROR: ghost elem %d & ghost node %d have inconsistent adjacency list\n",n2e[j],i);
01189       CkAssert(false);
01190     }
01191     for(int k=0; k<3;k++) {
01192       if(e2n1[k] == i) continue;
01193       bool flag1 = true;
01194       for(int l=0; l<n2n1Count; l++) {
01195         if(e2n1[k] == n2n1[l]) flag1 = false;
01196       }
01197       if(flag1 && n2n1Count<n2nsize) { 
01198         n2n1[n2n1Count] = e2n1[k];
01199         n2n1Count++;
01200       }
01201     }
01202       }
01203       
01204       
01205       bool flag2 = true;
01206       if(n2n1Count!=n2nsize) flag2 = false;
01207       for(int j=0; j<n2n1Count; j++) {
01208     bool flag1 = false;
01209     for(int k=0; k<n2nsize; k++) {
01210       if(n2n[k]==n2n1[j]) flag1 = true;
01211     }
01212     if(!flag1) {
01213       flag2 = false;
01214       break;
01215     }
01216       }
01217       if(!flag2) {
01218     FEM_Print_coords(m,i);
01219     FEM_Print_n2n(m,i);
01220     for(int l=0; l<n2esize; l++) FEM_Print_e2n(m,n2e[l]);
01221     CkPrintf("ERROR: ghost node %d has inconsistent adjacency list\n",i);
01222     CkAssert(false);
01223       }
01224       
01225       free(n2n1);
01226       delete [] n2e;
01227       if(n2nsize>0) delete [] n2n;
01228     }
01229   }
01230   for(int i=0; i<noGhostNodes; i++) {
01231     int ghostidx = FEM_To_ghost_index(i);
01232     if(m->node.ghost->is_valid(i)) {
01233       m->n2e_getAll(ghostidx,&n2e,&n2esize);
01234       m->n2n_getAll(ghostidx,&n2n,&n2nsize);
01235       bool done = false;
01236       for(int k=0;k<n2nsize;k++) {
01237     if(n2n[k]>=0) {
01238       done = true;
01239       break;
01240     }
01241       }
01242       if(n2esize>n2nsize || !done) {
01243     FEM_Print_coords(m,ghostidx);
01244     FEM_Print_n2e(m,ghostidx);
01245     FEM_Print_n2n(m,ghostidx);
01246     CkPrintf("ERROR: ghost node %d, with inconsistent adjacency list\n",ghostidx);
01247     CkAssert(false);
01248       }
01249       if(n2esize > 0) {
01250     
01251     int n2n1size = 0;
01252     int *n2n1 = (int*)malloc(n2nsize*sizeof(int));
01253     int n2n1Count = 0;
01254     for(int j=0; j<n2esize; j++) {
01255       CkAssert(n2e[j]!=-1);
01256       if(FEM_Is_ghost_index(n2e[j])) CkAssert(m->elem[0].ghost->is_valid(FEM_From_ghost_index(n2e[j]))==1);
01257       else CkAssert(m->elem[0].is_valid(n2e[j])==1);
01258       
01259       int e2n1[3];
01260       m->e2n_getAll(n2e[j],e2n1,0);
01261       if(e2n1[0]!=ghostidx && e2n1[1]!=ghostidx && e2n1[2]!=ghostidx) {
01262         FEM_Print_coords(m,ghostidx);
01263         FEM_Print_n2e(m,ghostidx);
01264         FEM_Print_e2n(m,n2e[j]);
01265         CkPrintf("ERROR: ghost elem %d & ghost node %d have inconsistent adjacency list\n",n2e[j],ghostidx);
01266         CkAssert(false);
01267       }
01268       for(int k=0; k<3;k++) {
01269         if(e2n1[k] == ghostidx) continue;
01270         bool flag1 = true;
01271         for(int l=0; l<n2n1Count; l++) {
01272           if(e2n1[k] == n2n1[l]) flag1 = false;
01273         }
01274         if(flag1 && n2n1Count<n2nsize) { 
01275           n2n1[n2n1Count] = e2n1[k];
01276           n2n1Count++;
01277         }
01278       }
01279     }
01280 
01281     
01282     bool flag2 = true;
01283     if(n2n1Count!=n2nsize) flag2 = false;
01284     for(int j=0; j<n2n1Count; j++) {
01285       bool flag1 = false;
01286       for(int k=0; k<n2nsize; k++) {
01287         if(n2n[k]==n2n1[j]) flag1 = true;
01288       }
01289       if(!flag1) {
01290         flag2 = false;
01291         break;
01292       }
01293     }
01294     if(!flag2) {
01295       FEM_Print_coords(m,ghostidx);
01296       FEM_Print_n2n(m,ghostidx);
01297       for(int l=0; l<n2esize; l++) FEM_Print_e2n(m,n2e[l]);
01298       CkPrintf("ERROR: ghost node %d has inconsistent adjacency list\n",ghostidx);
01299       CkAssert(false);
01300     }
01301     free(n2n1);
01302     delete [] n2e;
01303       }
01304       if(n2nsize > 0) {
01305     for(int j=0; j<n2nsize; j++) {
01306       CkAssert(n2n[j]!=-1);
01307     }
01308     delete [] n2n;
01309       }
01310       
01311       const IDXL_Rec *irec = m->node.ghost->ghostRecv.getRec(i);
01312       
01313       int remChk = irec->getChk(0);
01314       int sharedIdx = irec->getIdx(0);
01315       int numsh = irec->getShared();
01316       verifyghostsendMsg *vmsg = new(numsh,0)verifyghostsendMsg();
01317       vmsg->fromChk = idx;
01318       vmsg->sharedIdx = sharedIdx;
01319       vmsg->numchks = numsh;
01320       for(int k=0; k<numsh; k++) vmsg->chunks[k] = irec->getChk(k);
01321       meshMod[remChk].verifyghostsend(vmsg);
01322     }
01323     else {
01324       continue;
01325     }
01326   }
01327 
01328   free(e2n);
01329   return;
01330 }
01331 
01332 int FEM_MUtil::AreaTest(FEM_Mesh *m) {
01333   int noEle = m->elem[0].size();
01334   int wdt = m->elem[0].getConn().width();
01335   int *con = (int*)malloc(wdt*sizeof(int));
01336 
01337   for(int i=0; i<noEle; i++) {
01338     if(m->elem[0].is_valid(i)) {
01339       m->e2n_getAll(i,con,0);
01340       double area = mmod->fmAdaptAlgs->getArea(con[0],con[1],con[2]);
01341       if(fabs(area) < SLIVERAREA) {
01342     CkAssert(false);
01343     free(con);
01344     return -1;
01345       }
01346     }
01347   }
01348   free(con);
01349   return 1;
01350 }
01351 
01352 int FEM_MUtil::IdxlListTest(FEM_Mesh *m) {
01353   for(int type=0; type <5; type++) {
01354     int listsize = 0;
01355     if(type==0) listsize = m->node.shared.size();
01356     else if(type==1) listsize = m->node.ghostSend.size();
01357     else if(type==2) listsize = m->node.ghost->ghostRecv.size();
01358     else if(type==3) listsize = m->elem[0].ghostSend.size();
01359     else if(type==4) listsize = m->elem[0].ghost->ghostRecv.size();
01360     
01361     for(int i=0; i<listsize; i++) {
01362       IDXL_List il;
01363       if(type==0) il = m->node.shared.getLocalList(i);
01364       else if(type==1) il = m->node.ghostSend.getLocalList(i);
01365       else if(type==2) il = m->node.ghost->ghostRecv.getLocalList(i);
01366       else if(type==3) il = m->elem[0].ghostSend.getLocalList(i);
01367       else if(type==4) il = m->elem[0].ghost->ghostRecv.getLocalList(i);
01368       int shck = il.getDest();
01369       int size = il.size();
01370       
01371       meshMod[shck].verifyIdxlList(idx,size,type);
01372       
01373       for(int j=0; j<size; j++) {
01374     CkAssert(il[j] >= -1);
01375       }
01376     }
01377   }
01378   
01379   return 1;
01380 }
01381 
01382 int FEM_MUtil::residualLockTest(FEM_Mesh *m) {
01383   int noNodes = m->node.size();
01384   for(int i=0; i<noNodes; i++) {
01385     if(m->node.is_valid(i)) {
01386       CkAssert(!mmod->fmLockN[i]->haslocks());
01387     }
01388   }
01389   for(int i=0; i<mmod->numChunks*5; i++) {
01390     CkAssert(mmod->fmIdxlLock[i]==false);
01391   }
01392   return 1;
01393 }
01394 
01395 void FEM_MUtil::verifyIdxlListRemote(FEM_Mesh *m, int fromChk, int fsize, int type) {
01396   IDXL_Side is;
01397 
01398   IDXL_List il;
01399   if(type==0) il = m->node.shared.addList(fromChk);
01400   else if(type==1) il = m->node.ghost->ghostRecv.addList(fromChk);
01401   else if(type==2) il = m->node.ghostSend.addList(fromChk);
01402   else if(type==3) il = m->elem[0].ghost->ghostRecv.addList(fromChk);
01403   else if(type==4) il = m->elem[0].ghostSend.addList(fromChk);
01404   int size = il.size();
01405   CkAssert(fsize == size);
01406   
01407   for(int j=0; j<size; j++) {
01408     CkAssert(il[j] >= -1);
01409   }
01410   
01411   return;
01412 }
01413 
01414 void FEM_MUtil::FEM_Print_n2n(FEM_Mesh *m, int nodeid){
01415   CkPrintf("node %d is adjacent to nodes:", nodeid);
01416   int *adjnodes;
01417   int sz;
01418   m->n2n_getAll(nodeid, &adjnodes, &sz); 
01419   for(int i=0;i<sz;i++)
01420     CkPrintf(" %d", adjnodes[i]);
01421   if(sz!=0) delete[] adjnodes;  
01422   CkPrintf("\n");
01423 }
01424 
01425 void FEM_MUtil::FEM_Print_n2e(FEM_Mesh *m, int eid){
01426   CkPrintf("node %d is adjacent to elements:", eid);
01427   int *adjes;
01428   int sz;
01429   m->n2e_getAll(eid, &adjes, &sz);
01430   for(int i=0;i<sz;i++)
01431     CkPrintf(" %d", adjes[i]);
01432   if(sz!=0) delete[] adjes;
01433   CkPrintf("\n");
01434 }
01435 
01436 void FEM_MUtil::FEM_Print_e2n(FEM_Mesh *m, int eid){
01437   CkPrintf("element %d is adjacent to nodes:", eid);
01438   int consz = m->elem[0].getConn().width();
01439   int *adjns = new int[consz];
01440   m->e2n_getAll(eid, adjns, 0); 
01441   for(int i=0;i<consz;i++)
01442     CkPrintf(" %d", adjns[i]);
01443   CkPrintf("\n");
01444   delete [] adjns;
01445 }
01446 
01447 void FEM_MUtil::FEM_Print_e2e(FEM_Mesh *m, int eid){
01448   CkPrintf("element %d is adjacent to elements:", eid);
01449   int consz = m->elem[0].getConn().width();
01450   int *adjes = new int[consz];
01451   m->e2e_getAll(eid, adjes, 0); 
01452   for(int i=0;i<consz;i++)
01453     CkPrintf(" %d", adjes[i]);
01454   CkPrintf("\n");
01455   delete [] adjes;
01456 }
01457 
01458 void FEM_MUtil::FEM_Print_coords(FEM_Mesh *m, int nodeid) {
01459   double crds[2];
01460   int bound;
01461   if(!FEM_Is_ghost_index(nodeid)) {
01462     FEM_Mesh_dataP(m, FEM_NODE, mmod->fmAdaptAlgs->coord_attr, (void *)crds, nodeid, 1, FEM_DOUBLE, 2);
01463     FEM_Mesh_dataP(m, FEM_NODE, FEM_BOUNDARY, (void *)&bound, nodeid, 1, FEM_INT, 1);
01464   }
01465   else {
01466     int numchunks;
01467     IDXL_Share **chunks1;
01468     getChunkNos(0,nodeid,&numchunks,&chunks1);
01469     int index = mmod->idx;
01470     for(int j=0; j<numchunks; j++) {
01471       int chk = chunks1[j]->chk;
01472       if(chk==index) continue;
01473       int ghostidx = exists_in_IDXL(m,nodeid,chk,2);
01474       double2Msg *d = meshMod[chk].getRemoteCoord(index,ghostidx);
01475       intMsg *im = meshMod[chk].getRemoteBound(index,ghostidx);
01476       crds[0] = d->i;
01477       crds[1] = d->j;
01478       bound = im->i;
01479       for(int j=0; j<numchunks; j++) {
01480     delete chunks1[j];
01481       }
01482       if(numchunks != 0) free(chunks1);
01483       break;
01484     }
01485   }
01486   CkPrintf("node %d (%f,%f) and boundary %d\n",nodeid,crds[0],crds[1],bound);
01487 }
01488 
01489 void FEM_MUtil::idxllock(FEM_Mesh *m, int chk, int type) {
01490 #ifdef DEBUG 
01491 CmiMemoryCheck();
01492 #endif
01493   if(idx < chk) {
01494     idxllockLocal(m,chk,type);
01495   } else {
01496     meshMod[chk].idxllockRemote(idx,type);
01497   }
01498 #ifdef DEBUG 
01499   CmiMemoryCheck(); 
01500 #endif
01501   return;
01502 }
01503 
01504 void FEM_MUtil::idxlunlock(FEM_Mesh *m, int chk, int type) {
01505 #ifdef DEBUG 
01506   CmiMemoryCheck(); 
01507 #endif
01508   if(idx < chk) {
01509     
01510     idxlunlockLocal(m,chk,type);
01511   } else {
01512     
01513     meshMod[chk].idxlunlockRemote(idx,type);
01514   }
01515 #ifdef DEBUG 
01516   CmiMemoryCheck(); 
01517 #endif
01518   return;
01519 }
01520 
01521 void FEM_MUtil::idxllockLocal(FEM_Mesh *m, int toChk, int type) {
01522   CkAssert(toChk>=0 && toChk<mmod->numChunks && toChk!=idx && type>=0 && type<5);
01523   while(mmod->fmIdxlLock[toChk*5 + type] == true) {
01524     
01525     CthYield();
01526   }
01527   
01528   mmod->fmIdxlLock[toChk*5 + type] = true;
01529 #ifdef DEBUG_IDXLLock
01530   CkPrintf("[%d]locked idxl lock %d\n",idx,toChk*5+type);
01531 #endif
01532 #ifdef DEBUG 
01533   CmiMemoryCheck(); 
01534 #endif
01535   return;
01536 }
01537 
01538 void FEM_MUtil::idxlunlockLocal(FEM_Mesh *m, int toChk, int type) {
01539   CkAssert(toChk>=0 && toChk<mmod->numChunks && toChk!=idx && type>=0 && type<5);
01540   CkAssert(mmod->fmIdxlLock[toChk*5 + type] == true);
01541   
01542   mmod->fmIdxlLock[toChk*5 + type] = false;
01543 #ifdef DEBUG_IDXLLock
01544   CkPrintf("[%d]unlocked idxl lock %d\n",idx,toChk*5+type);
01545 #endif
01546 #ifdef DEBUG 
01547   CmiMemoryCheck(); 
01548 #endif
01549   return;
01550 }
01551 
01552 
01553 void FEM_MUtil::copyElemData(int etype, int elemid, int newEl) {
01554   FEM_Interpolate *inp = mmod->getfmInp();
01555   FEM_Interpolate::ElementArgs em;
01556   em.e = newEl;
01557   em.oldElement = elemid;
01558   em.elType = etype;
01559   inp->FEM_InterpolateElementCopy(em);
01560 }
01561