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