00001
00002
00003
00004
00005
00006 #include "fem_adapt_new.h"
00007 #include "fem_mesh_modify.h"
00008 #include <vector>
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 int FEM_Adapt::edge_flip_help(int e1, int e2, int n1, int n2, int e1_n1,
00033 int e1_n2, int e1_n3, int n3, int n4, int *locknodes)
00034 {
00035 int *conn = (int*)malloc(3*sizeof(int));
00036 int numNodes = 4;
00037 int numElems = 2;
00038 int newNode = -1;
00039
00040 int *lockelems = (int*)malloc(numElems*sizeof(int));
00041
00042 locknodes[0] = n1;
00043 locknodes[1] = n2;
00044 locknodes[2] = n3;
00045 locknodes[3] = n4;
00046 lockelems[0] = e1;
00047 lockelems[1] = e2;
00048
00049
00050
00051
00052
00053
00054
00055
00056 int e1chunk=-1, e2chunk=-1;
00057 int index = theMod->getIdx();
00058
00059 #ifdef DEBUG_1
00060 CkPrintf("Flipping edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
00061 #endif
00062
00063 double e1Sz = theMesh->elem[0].getMeshSizing(e1);
00064 double e2Sz = theMesh->elem[0].getMeshSizing(e2);
00065 int e1Topurge = e1;
00066 int e2Topurge = e2;
00067
00068 if(n1 < 0 || n2 < 0 || n3 < 0) {
00069 e1chunk = FEM_remove_element(theMesh, e1, 0, index);
00070 }
00071 else {
00072 e1chunk = FEM_remove_element(theMesh, e1, 0);
00073 }
00074
00075 if(n1 < 0 || n2 < 0 || n4 < 0) {
00076 e2chunk = FEM_remove_element(theMesh, e2, 0, index);
00077 }
00078 else {
00079 e2chunk = FEM_remove_element(theMesh, e2, 0);
00080 }
00081
00082 if(e1chunk==e2chunk && e1chunk!=index) {
00083
00084
00085
00086 }
00087 else if(e1chunk==e2chunk && e1chunk==index) {
00088
00089 }
00090 else if(e1chunk!=e2chunk && (e1chunk==index || e2chunk==index)) {
00091
00092 if(e1chunk==index) {
00093
00094
00095 e2chunk=e1chunk;
00096 conn[0] = n1; conn[1] = n2; conn[2] = n4;
00097 int newel = FEM_add_element(theMesh, conn, 3, 0, e2chunk);
00098
00099 for(int j=0; j<3; j++) {
00100 if((conn[j]!=n1)&&(conn[j]!=n2)) {
00101 int oldn4 = n4;
00102 n4 = conn[j];
00103 newNode = n4;
00104 CkPrintf("Changing node %d to node %d\n",oldn4,n4);
00105 }
00106 }
00107 locknodes[3] = n4;
00108 theMod->fmUtil->copyElemData(0,e2,newel);
00109 FEM_purge_element(theMesh,e2,0);
00110 FEM_remove_element(theMesh, newel);
00111 e2Topurge = newel;
00112 }
00113 else {
00114
00115
00116 e1chunk=e2chunk;
00117 conn[0] = n1; conn[1] = n2; conn[2] = n3;
00118 int newel = FEM_add_element(theMesh, conn, 3, 0, e1chunk);
00119 for(int j=0; j<3; j++) {
00120 if((conn[j]!=n1)&&(conn[j]!=n2)) {
00121 int oldn3 = n3;
00122 n3 = conn[j];
00123 newNode = n3;
00124 CkPrintf("Changing node %d to node %d\n",oldn3,n3);
00125 }
00126 }
00127 locknodes[2] = n3;
00128 theMod->fmUtil->copyElemData(0,e1,newel);
00129 FEM_purge_element(theMesh,e1,0);
00130 FEM_remove_element(theMesh, newel);
00131 e1Topurge = newel;
00132 }
00133
00134 }
00135 else {
00136
00137
00138 CkAbort("Flip with two external elements on two different chunks\n");
00139 }
00140
00141
00142 conn[e1_n1] = n1; conn[e1_n2] = n4; conn[e1_n3] = n3;
00143 lockelems[0] = FEM_add_element(theMesh, conn, 3, 0, e1chunk);
00144 theMod->fmUtil->copyElemData(0,e1Topurge,lockelems[0]);
00145 FEM_purge_element(theMesh,e1Topurge,0);
00146
00147
00148 conn[e1_n1] = n4; conn[e1_n2] = n2; conn[e1_n3] = n3;
00149 lockelems[1] = FEM_add_element(theMesh, conn, 3, 0, e2chunk);
00150 theMod->fmUtil->copyElemData(0,e2Topurge,lockelems[1]);
00151 FEM_purge_element(theMesh,e2Topurge,0);
00152
00153
00154
00155 for(int i=0; i<4;i++) {
00156 int nodeToUpdate = -1;
00157 if(i==0) nodeToUpdate = n1;
00158 else if(i==1) nodeToUpdate = n2;
00159 else if(i==2) nodeToUpdate = n3;
00160 else if(i==3) nodeToUpdate = n4;
00161
00162
00163
00164
00165
00166 int *chkl, numchkl=0;
00167 CkVec<int> finalchkl;
00168 theMod->fmUtil->findGhostSend(nodeToUpdate, &chkl, &numchkl);
00169 for(int j=0; j<numchkl; j++) {
00170 finalchkl.push_back(chkl[j]);
00171 }
00172 if(numchkl>0) delete[] chkl;
00173
00174 const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate);
00175 int numchunks=0;
00176 int *chunks1, *inds1;
00177 if(irec) {
00178 numchunks = irec->getShared();
00179 chunks1 = new int[numchunks];
00180 inds1 = new int[numchunks];
00181 for(int j=0; j<numchunks; j++) {
00182 chunks1[j] = irec->getChk(j);
00183 inds1[j] = irec->getIdx(j);
00184 }
00185 }
00186 for(int j=0; j<numchunks; j++) {
00187 findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]);
00188 if(fmsg->numchks>0) {
00189 for(int k=0; k<fmsg->numchks; k++) {
00190 bool shouldbeadded = true;
00191 for(int l=0; l<finalchkl.size(); l++) {
00192 if(fmsg->chunks[k]==finalchkl[l]) {
00193 shouldbeadded = false;
00194 break;
00195 }
00196 }
00197 if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]);
00198 }
00199 }
00200 delete fmsg;
00201 }
00202
00203 int *finall=NULL, numfinall=finalchkl.size();
00204 if(numfinall>0) finall = new int[numfinall];
00205 for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j];
00206 finalchkl.free();
00207
00208 theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall);
00209 for(int j=0; j<numchunks; j++) {
00210 verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg();
00211 vmsg->fromChk = index;
00212 vmsg->sharedIdx = inds1[j];
00213 vmsg->numchks = numfinall;
00214 for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k];
00215 meshMod[chunks1[j]].updateghostsend(vmsg);
00216 }
00217 if(numfinall>0) delete[] finall;
00218 if(numchunks>0) {
00219 delete[] chunks1;
00220 delete[] inds1;
00221 }
00222 }
00223
00224
00225 free(conn);
00226
00227 free(lockelems);
00228 return newNode;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 int FEM_Adapt::edge_bisect_help(int e1, int e2, int n1, int n2, int e1_n1,
00254 int e1_n2, int e1_n3, int e2_n1, int e2_n2,
00255 int e2_n3, int n3, int n4)
00256 {
00257 int n5;
00258 int *conn = (int*)malloc(3*sizeof(int));
00259 int numNodes = 4;
00260 int numElems = 2;
00261 int numNodesNew = 5;
00262 int numElemsNew = 4;
00263 int *locknodes = (int*)malloc(numNodesNew*sizeof(int));
00264 int *lockelems = (int*)malloc(numElemsNew*sizeof(int));
00265
00266 locknodes[0] = n1;
00267 locknodes[1] = n2;
00268 locknodes[2] = n3;
00269 locknodes[3] = n4;
00270 locknodes[4] = -1;
00271 lockelems[0] = e1;
00272 lockelems[1] = e2;
00273 lockelems[2] = -1;
00274 lockelems[3] = -1;
00275
00276
00277
00278 int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1, n5chunk=-1;
00279 int index = theMod->getIdx();
00280
00281 #ifdef DEBUG_1
00282 CkPrintf("Bisect edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
00283 #endif
00284
00285
00286 if(e1==-1) e1chunk=-1;
00287 else if(e1>=0) e1chunk=index;
00288 else {
00289 int ghostid = FEM_To_ghost_index(e1);
00290 const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid);
00291 CkAssert(irec->getShared()==1);
00292 e1chunk = irec->getChk(0);
00293 }
00294 if(e2==-1) e2chunk=-1;
00295 else if(e2>=0) e2chunk=index;
00296 else {
00297 int ghostid = FEM_To_ghost_index(e2);
00298 const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid);
00299 CkAssert(irec->getShared()==1);
00300 e2chunk = irec->getChk(0);
00301 }
00302 int *adjnodes = (int*)malloc(2*sizeof(int));
00303 adjnodes[0] = n1;
00304 adjnodes[1] = n2;
00305 int *chunks;
00306 int numChunks=0;
00307 int forceshared = 0;
00308 if(e1chunk==e2chunk || (e1chunk==-1 || e2chunk==-1)) {
00309 forceshared = -1;
00310 numChunks = 1;
00311 chunks = new int[1];
00312 if(e1chunk!=-1) chunks[0] = e1chunk;
00313 else chunks[0] = e2chunk;
00314 }
00315 else {
00316 numChunks = 2;
00317 chunks = new int[2];
00318 chunks[0] = e1chunk;
00319 chunks[1] = e2chunk;
00320 }
00321 n5 = FEM_add_node(theMesh,adjnodes,2,chunks,numChunks,forceshared,0);
00322 delete[] chunks;
00323
00324 FEM_Modify_LockN(theMesh, n5, 0);
00325
00326
00327 double e1Sz = theMesh->elem[0].getMeshSizing(e1);
00328 e1chunk = FEM_remove_element(theMesh, e1, 0);
00329 double e2Sz = -1.0;
00330 if (e2 != -1) e2Sz = theMesh->elem[0].getMeshSizing(e2);
00331 e2chunk = FEM_remove_element(theMesh, e2, 0);
00332
00333
00334
00335
00336 if(e1chunk==-1 || e2chunk==-1) {
00337
00338 e4chunk = e2chunk;
00339 e3chunk = e1chunk;
00340 }
00341 else if(e1chunk==e2chunk && e1chunk!=index) {
00342 n5chunk = e1chunk;
00343 e4chunk = e2chunk;
00344 e3chunk = e1chunk;
00345 }
00346 else {
00347
00348 n5chunk = -1;
00349 e4chunk = e2chunk;
00350 e3chunk = e1chunk;
00351 }
00352
00353
00354 conn[e1_n1] = n1; conn[e1_n2] = n5; conn[e1_n3] = n3;
00355 lockelems[0] = FEM_add_element(theMesh, conn, 3, 0, e1chunk);
00356 theMod->fmUtil->copyElemData(0,e1,lockelems[0]);
00357
00358
00359 conn[e1_n1] = n5; conn[e1_n2] = n2; conn[e1_n3] = n3;
00360 lockelems[1] = FEM_add_element(theMesh, conn, 3, 0, e3chunk);
00361 theMod->fmUtil->copyElemData(0,e1,lockelems[1]);
00362
00363 if (e2 != -1) {
00364
00365 conn[e2_n1] = n1; conn[e2_n2] = n5; conn[e2_n3] = n4;
00366 lockelems[2] = FEM_add_element(theMesh, conn, 3, 0, e2chunk);
00367 theMod->fmUtil->copyElemData(0,e2,lockelems[2]);
00368
00369
00370 conn[e2_n1] = n5; conn[e2_n2] = n2; conn[e2_n3] = n4;
00371 lockelems[3] = FEM_add_element(theMesh, conn, 3, 0, e4chunk);
00372 theMod->fmUtil->copyElemData(0,e2,lockelems[3]);
00373
00374 }
00375
00376 FEM_purge_element(theMesh,e1,0);
00377 FEM_purge_element(theMesh,e2,0);
00378
00379
00380 for(int i=0; i<4;i++) {
00381 int nodeToUpdate = -1;
00382 if(i==0) nodeToUpdate = n1;
00383 else if(i==1) nodeToUpdate = n2;
00384 else if(i==2) nodeToUpdate = n3;
00385 else if(i==3) nodeToUpdate = n4;
00386
00387
00388
00389
00390
00391 int *chkl, numchkl=0;
00392 CkVec<int> finalchkl;
00393 theMod->fmUtil->findGhostSend(nodeToUpdate, &chkl, &numchkl);
00394 for(int j=0; j<numchkl; j++) {
00395 finalchkl.push_back(chkl[j]);
00396 }
00397 if(numchkl>0) delete[] chkl;
00398
00399 const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate);
00400 int numchunks=0;
00401 int *chunks1, *inds1;
00402 if(irec) {
00403 numchunks = irec->getShared();
00404 chunks1 = new int[numchunks];
00405 inds1 = new int[numchunks];
00406 for(int j=0; j<numchunks; j++) {
00407 chunks1[j] = irec->getChk(j);
00408 inds1[j] = irec->getIdx(j);
00409 }
00410 }
00411 for(int j=0; j<numchunks; j++) {
00412 findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]);
00413 if(fmsg->numchks>0) {
00414 for(int k=0; k<fmsg->numchks; k++) {
00415 bool shouldbeadded = true;
00416 for(int l=0; l<finalchkl.size(); l++) {
00417 if(fmsg->chunks[k]==finalchkl[l]) {
00418 shouldbeadded = false;
00419 break;
00420 }
00421 }
00422 if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]);
00423 }
00424 }
00425 delete fmsg;
00426 }
00427
00428 int *finall=NULL, numfinall=finalchkl.size();
00429 if(numfinall>0) finall = new int[numfinall];
00430 for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j];
00431 finalchkl.free();
00432
00433 theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall);
00434 for(int j=0; j<numchunks; j++) {
00435 verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg();
00436 vmsg->fromChk = index;
00437 vmsg->sharedIdx = inds1[j];
00438 vmsg->numchks = numfinall;
00439 for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k];
00440 meshMod[chunks1[j]].updateghostsend(vmsg);
00441 }
00442 if(numfinall>0) delete[] finall;
00443 if(numchunks>0) {
00444 delete[] chunks1;
00445 delete[] inds1;
00446 }
00447 }
00448
00449 free(conn);
00450 free(locknodes);
00451 free(lockelems);
00452 free(adjnodes);
00453 FEM_Modify_UnlockN(theMesh, n5, 0);
00454 return n5;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 int FEM_Adapt::vertex_remove_help(int e1, int e2, int n1, int n2, int e1_n1,
00480 int e1_n2, int e1_n3, int e2_n1, int e2_n2,
00481 int e2_n3, int n3, int n4, int n5)
00482 {
00483 int numNodes = 5;
00484 int numElems = 4;
00485 int numNodesNew = 4;
00486 int numElemsNew = 2;
00487 int *locknodes = (int*)malloc(numNodes*sizeof(int));
00488 int *lockelems = (int*)malloc(numElems*sizeof(int));
00489
00490 locknodes[0] = n2;
00491 locknodes[1] = n3;
00492 locknodes[2] = n4;
00493 locknodes[3] = n5;
00494 locknodes[4] = n1;
00495 lockelems[0] = e1;
00496 lockelems[1] = e2;
00497 lockelems[2] = -1;
00498 lockelems[3] = -1;
00499
00500 int e3 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n1, e1_n3));
00501 int e4 = -1;
00502 lockelems[2] = e3;
00503 if (e3 != -1) {
00504 if (e2 != -1) {
00505 e4 = theMesh->e2e_getNbr(e2, get_edge_index(e2_n1, e2_n3));
00506 lockelems[3] = e4;
00507 if(e4 == -1 ) {
00508 free(locknodes);
00509 free(lockelems);
00510 return 0;
00511 }
00512 }
00513
00514
00515 int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1;
00516 int index = theMod->getIdx();
00517
00518 #ifdef DEBUG_1
00519 CkPrintf("Vertex Remove edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
00520 #endif
00521
00522 e1chunk = FEM_remove_element(theMesh, e1, 0);
00523 e3chunk = FEM_remove_element(theMesh, e3, 0);
00524 if (e2 != -1) {
00525 e2chunk = FEM_remove_element(theMesh, e2, 0);
00526 e4chunk = FEM_remove_element(theMesh, e4, 0);
00527 }
00528 FEM_remove_node(theMesh, n1);
00529
00530 int *conn = (int*)malloc(3*sizeof(int));
00531
00532 conn[e1_n1] = n2; conn[e1_n2] = n3; conn[e1_n3] = n5;
00533 lockelems[0] = FEM_add_element(theMesh, conn, 3, 0, e1chunk);
00534 if (e2 != -1) {
00535
00536 conn[e2_n1] = n5; conn[e2_n2] = n4; conn[e2_n3] = n2;
00537 lockelems[1] = FEM_add_element(theMesh, conn, 3, 0, e2chunk);
00538 }
00539
00540 free(conn);
00541 free(locknodes);
00542 free(lockelems);
00543 return 1;
00544 }
00545
00546 free(locknodes);
00547 free(lockelems);
00548 return 0;
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 int FEM_Adapt::vertex_split(int n, int n1, int n2)
00574 {
00575 if ((n < 0) || ((n1 <= -1) && (n2 <= -1)))
00576 CkAbort("FEM_Adapt::vertex_split: n and at least one of its neighbor must be local to this chunk; n1 and n2 must both exist\n");
00577 int *locknodes = (int*)malloc(2*sizeof(int));
00578 locknodes[0] = n1; locknodes[1] = n2;
00579 FEM_Modify_Lock(theMesh, locknodes, 2, locknodes, 0);
00580 int e1 = theMesh->getElementOnEdge(n, n1);
00581 if (e1 == -1) {
00582 FEM_Modify_Unlock(theMesh);
00583 free(locknodes);
00584 return -1;
00585 }
00586 int e3 = theMesh->getElementOnEdge(n, n2);
00587 if (e3 == -1) {
00588 FEM_Modify_Unlock(theMesh);
00589 free(locknodes);
00590 return -1;
00591 }
00592 int ret = vertex_split_help(n, n1, n2, e1, e3);
00593 FEM_Modify_Unlock(theMesh);
00594 free(locknodes);
00595 return ret;
00596 }
00597
00598 int FEM_Adapt::vertex_split_help(int n, int n1, int n2, int e1, int e3)
00599 {
00600 int e1_n = find_local_node_index(e1, n);
00601 int e1_n1 = find_local_node_index(e1, n1);
00602 int e2 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n, e1_n1));
00603 int e3_n = find_local_node_index(e3, n);
00604 int e3_n2 = find_local_node_index(e3, n2);
00605 int e4 = theMesh->e2e_getNbr(e3, get_edge_index(e3_n, e3_n2));
00606 if (!check_orientation(e1, e3, n, n1, n2)) {
00607 int tmp = e3;
00608 e3 = e4;
00609 e4 = tmp;
00610 e3_n = find_local_node_index(e3, n);
00611 e3_n2 = find_local_node_index(e3, n2);
00612 }
00613
00614 int *locknodes = (int*)malloc(4*sizeof(int));
00615 locknodes[0] = n1;
00616 locknodes[1] = n;
00617 locknodes[2] = n2;
00618 locknodes[3] = -1;
00619 int *lockelems = (int*)malloc(6*sizeof(int));
00620 lockelems[0] = e1;
00621 lockelems[1] = e2;
00622 lockelems[2] = e3;
00623 lockelems[3] = e4;
00624 lockelems[4] = -1;
00625 lockelems[5] = -1;
00626
00627
00628 #ifdef DEBUG_1
00629 CkPrintf("Vertex Split, %d-%d-%d on chunk %d\n", n1, n, n2, theMod->getfmUtil()->getIdx());
00630 #endif
00631 int *adjnodes = (int*)malloc(2*sizeof(int));
00632 adjnodes[0] = n;
00633
00634 int *chunks;
00635 int numChunks = 0;
00636 int np = FEM_add_node(theMesh,adjnodes,1,chunks,numChunks,0,0);
00637 locknodes[3] = np;
00638
00639 int *conn = (int*)malloc(3*sizeof(int));
00640 int current, next, nt, nl, eknp, eknt, eknl;
00641
00642 current = e2;
00643 nt = n1;
00644 while ((current != e3) && (current != -1)) {
00645 eknp = find_local_node_index(current, n);
00646 eknt = find_local_node_index(current, nt);
00647 eknl = 3 - eknp - eknt;
00648 next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl));
00649 nl = theMesh->e2n_getNode(current, eknl);
00650 FEM_remove_element(theMesh, current, 0);
00651
00652 conn[eknp] = np; conn[eknt] = nt; conn[eknl] = nl;
00653 int newelem = FEM_add_element(theMesh, conn, 3, 0);
00654 nt = nl;
00655 current = next;
00656 }
00657 if (current == -1) {
00658
00659 current = e4;
00660 nt = n2;
00661 while ((current != e1) && (current != -1)) {
00662 eknp = find_local_node_index(current, n);
00663 eknt = find_local_node_index(current, nt);
00664 eknl = 3 - eknp - eknt;
00665 next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl));
00666 nl = theMesh->e2n_getNode(current, eknl);
00667 FEM_remove_element(theMesh, current, 0);
00668
00669 conn[eknp] = np; conn[eknt] = nt; conn[eknl] = nl;
00670 int newelem = FEM_add_element(theMesh, conn, 3, 0);
00671 nt = nl;
00672 current = next;
00673 }
00674 }
00675
00676
00677 conn[e1_n] = n; conn[e1_n1] = n1; conn[3 - e1_n - e1_n1] = np;
00678 lockelems[4] = FEM_add_element(theMesh, conn, 3, 0);
00679
00680 conn[e3_n] = n; conn[e3_n2] = n2; conn[3 - e3_n - e3_n2] = np;
00681 lockelems[5] = FEM_add_element(theMesh, conn, 3, 0);
00682
00683 free(locknodes);
00684 free(lockelems);
00685 free(conn);
00686 free(adjnodes);
00687 return np;
00688 }
00689
00690
00691
00692
00693 int FEM_Adapt::get_edge_index(int local_node1, int local_node2)
00694 {
00695 int sum = local_node1 + local_node2;
00696 CkAssert(local_node1 != local_node2);
00697 if (sum == 1) return 0;
00698 else if (sum == 3) return 1;
00699 else if (sum == 2) return 2;
00700 else {
00701 CkPrintf("ERROR: local node pair is strange: [%d,%d]\n", local_node1,
00702 local_node2);
00703 CkAbort("ERROR: local node pair is strange\n");
00704 return -1;
00705 }
00706 }
00707
00708 int FEM_Adapt::find_local_node_index(int e, int n) {
00709 int result = theMesh->e2n_getIndex(e, n);
00710 if (result < 0) {
00711 CkPrintf("ERROR: node %d not found on element %d\n", n, e);
00712 CkAbort("ERROR: node not found\n");
00713 }
00714 return result;
00715 }
00716
00717 int FEM_Adapt::check_orientation(int e1, int e3, int n, int n1, int n2)
00718 {
00719 int e1_n = find_local_node_index(e1, n);
00720 int e1_n1 = find_local_node_index(e1, n1);
00721 int e3_n = find_local_node_index(e3, n);
00722 int e3_n2 = find_local_node_index(e3, n2);
00723
00724 if (((e1_n1 == (e1_n+1)%3) && (e3_n == (e3_n2+1)%3)) ||
00725 ((e1_n == (e1_n1+1)%3) && (e3_n2 == (e3_n+1)%3)))
00726 return 1;
00727 else return 0;
00728 }
00729
00730 int FEM_Adapt::findAdjData(int n1, int n2, int *e1, int *e2, int *e1n1,
00731 int *e1n2, int *e1n3, int *e2n1, int *e2n2,
00732 int *e2n3, int *n3, int *n4)
00733 {
00734
00735 (*e1n1) = (*e1n2) = (*e1n3) = (*n3) = -1;
00736
00737
00738 if(n1<0 || n2<0) return -1;
00739 if(theMesh->node.is_valid(n1)==0 || theMesh->node.is_valid(n2)==0) return -1;
00740 if(theMesh->n2n_exists(n1,n2)!=1 || theMesh->n2n_exists(n2,n1)!=1) return -1;
00741
00742 (*e1) = theMesh->getElementOnEdge(n1, n2);
00743 if ((*e1) == -1) {
00744 CkPrintf("[%d]Warning: No Element on edge %d->%d\n",theMod->idx,n1,n2);
00745 return -1;
00746 }
00747 (*e1n1) = find_local_node_index((*e1), n1);
00748 (*e1n2) = find_local_node_index((*e1), n2);
00749 (*e1n3) = 3 - (*e1n1) - (*e1n2);
00750 (*n3) = theMesh->e2n_getNode((*e1), (*e1n3));
00751 (*e2) = theMesh->e2e_getNbr((*e1), get_edge_index((*e1n1), (*e1n2)));
00752
00753 (*e2n1) = (*e2n2) = (*e2n3) = (*n4) = -1;
00754 if ((*e2) != -1) {
00755 (*e2n1) = find_local_node_index((*e2), n1);
00756 (*e2n2) = find_local_node_index((*e2), n2);
00757 (*e2n3) = 3 - (*e2n1) - (*e2n2);
00758
00759 (*n4) = theMesh->e2n_getNode((*e2), (*e2n3));
00760
00761 }
00762 if(*n3 == *n4) {
00763 CkPrintf("[%d]Warning: Identical elements %d:(%d,%d,%d) & %d:(%d,%d,%d)\n",theMod->idx,*e1,n1,n2,*n3,*e2,n1,n2,*n4);
00764 return -1;
00765 }
00766 return 1;
00767 }
00768
00769 int FEM_Adapt::getSharedNodeIdxl(int n, int chk) {
00770 return theMod->getfmUtil()->exists_in_IDXL(theMesh, n, chk, 0, -1);
00771 }
00772 int FEM_Adapt::getGhostNodeIdxl(int n, int chk) {
00773 return theMod->getfmUtil()->exists_in_IDXL(theMesh, n, chk, 2, -1);
00774 }
00775 int FEM_Adapt::getGhostElementIdxl(int e, int chk) {
00776 return theMod->getfmUtil()->exists_in_IDXL(theMesh, e, chk, 4, 0);
00777 }
00778
00779 void FEM_Adapt::printAdjacencies(int *nodes, int numNodes, int *elems, int numElems) {
00780
00781 for(int i=0; i<numNodes; i++) {
00782 if(nodes[i] == -1) continue;
00783 theMod->getfmUtil()->FEM_Print_n2e(theMesh, nodes[i]);
00784 theMod->getfmUtil()->FEM_Print_n2n(theMesh, nodes[i]);
00785 }
00786 for(int i=0; i<numElems; i++) {
00787 if(elems[i] == -1) continue;
00788 theMod->getfmUtil()->FEM_Print_e2n(theMesh, elems[i]);
00789 theMod->getfmUtil()->FEM_Print_e2e(theMesh, elems[i]);
00790 }
00791
00792 return;
00793 }
00794
00795 bool FEM_Adapt::isFixedNode(int n1) {
00796 for(int i=0; i<theMod->fmfixedNodes.size(); i++) {
00797 if(theMod->fmfixedNodes[i]==n1) return true;
00798 }
00799 return false;
00800 }
00801
00802 bool FEM_Adapt::isCorner(int n1) {
00803
00804 int *n1AdjNodes;
00805 int n1NumNodes=0;
00806 int n1_bound, n2_bound;
00807 FEM_Mesh_dataP(theMesh, FEM_NODE, FEM_BOUNDARY, &n1_bound, n1, 1 , FEM_INT, 1);
00808 if(n1_bound==0) return false;
00809 theMesh->n2n_getAll(n1, &n1AdjNodes, &n1NumNodes);
00810 for (int i=0; i<n1NumNodes; i++) {
00811 int n2 = n1AdjNodes[i];
00812 if(FEM_Is_ghost_index(n2)) {
00813 int numchunks;
00814 IDXL_Share **chunks1;
00815 theMod->fmUtil->getChunkNos(0,n2,&numchunks,&chunks1);
00816 int index = theMod->idx;
00817 CkAssert(numchunks>0);
00818 int chk = chunks1[0]->chk;
00819 int ghostidx = theMod->fmUtil->exists_in_IDXL(theMesh,n2,chk,2);
00820 intMsg *im = meshMod[chk].getRemoteBound(index,ghostidx);
00821 n2_bound = im->i;
00822 }
00823 else {
00824 FEM_Mesh_dataP(theMesh, FEM_NODE, FEM_BOUNDARY, &n2_bound, n2, 1 , FEM_INT, 1);
00825 }
00826 if(n2_bound == 0) continue;
00827 if(n1_bound != n2_bound) {
00828 if(isEdgeBoundary(n1,n2) && abs(n1_bound)>abs(n2_bound)) {
00829 if(n1NumNodes!=0) delete[] n1AdjNodes;
00830 return true;
00831 }
00832 }
00833 }
00834 if(n1NumNodes!=0) delete[] n1AdjNodes;
00835 return false;
00836 }
00837
00838 bool FEM_Adapt::isEdgeBoundary(int n1, int n2) {
00839 int *n1AdjElems, *n2AdjElems;
00840 int n1NumElems=0, n2NumElems=0;
00841 int ret = 0;
00842
00843 theMesh->n2e_getAll(n1, &n1AdjElems, &n1NumElems);
00844 theMesh->n2e_getAll(n2, &n2AdjElems, &n2NumElems);
00845 for(int k=0; k<n1NumElems; k++) {
00846 for (int j=0; j<n2NumElems; j++) {
00847 if (n1AdjElems[k] == n2AdjElems[j]) {
00848 if(n1AdjElems[k] != -1) {
00849 ret++;
00850 }
00851 }
00852 }
00853 }
00854 if(n1NumElems!=0) delete[] n1AdjElems;
00855 if(n2NumElems!=0) delete[] n2AdjElems;
00856 if(ret==1) return true;
00857 return false;
00858 }