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