00001 #include "element.h"
00002 #include "tri.h"
00003
00004 #define ZEROAREA 1.0e-15
00005
00006 int myisnan(double x) { return (x!=x); }
00007
00008 int element::lockOpNode(edgeRef e, double l)
00009 {
00010 int edgeIdx = getEdgeIdx(e);
00011 int opNode = (edgeIdx + 2) % 3;
00012 return C->theNodes[nodes[opNode]].lock(l, e);
00013 }
00014
00015 void element::unlockOpNode(edgeRef e)
00016 {
00017 int edgeIdx = getEdgeIdx(e);
00018 int opNode = (edgeIdx + 2) % 3;
00019 C->theNodes[nodes[opNode]].unlock();
00020 }
00021
00022 void element::calculateArea()
00023 {
00024
00025
00026 int i;
00027 double s, perimeter, len[3];
00028
00029 len[0] = (C->theNodes[nodes[0]]).distance(C->theNodes[nodes[1]]);
00030 len[1] = (C->theNodes[nodes[1]]).distance(C->theNodes[nodes[2]]);
00031 len[2] = (C->theNodes[nodes[2]]).distance(C->theNodes[nodes[0]]);
00032 CkAssert(len[0] > 0.0);
00033 CkAssert(len[1] > 0.0);
00034 CkAssert(len[2] > 0.0);
00035
00036 perimeter = len[0] + len[1] + len[2];
00037 s = perimeter / 2.0;
00038
00039 currentArea = sqrt(s * (s - len[0]) * (s - len[1]) * (s - len[2]));
00040 if (myisnan(currentArea)) currentArea = 0.0;
00041 }
00042
00043 void element::refine()
00044 {
00045 int longEdge = findLongestEdge();
00046 split(longEdge);
00047 }
00048
00049 void element::split(int longEdge)
00050 {
00051
00052
00053
00054
00055
00056
00057
00058
00059 int opnode, othernode, fixnode, modEdge, otherEdge, result, local, first;
00060 edgeRef e_prime, newEdge;
00061 int oldothernode;
00062 int m = -2, nullNbr=0;
00063 elemRef newElem, nullRef;
00064
00065
00066 opnode = (longEdge + 2) % 3;
00067 othernode = longEdge;
00068 modEdge = opnode;
00069 otherEdge = (longEdge + 1) % 3;
00070 fixnode = otherEdge;
00071
00072 int fIdx, oIdx;
00073 #ifdef TDEBUG3
00074 CkPrintf("TMRC2D: [%d] oIdx=%d fIdx=%d ", myRef.cid, nodes[othernode],
00075 nodes[fixnode]);
00076 CkPrintf("node[oIdx]="); C->theNodes[nodes[othernode]].dump();
00077 CkPrintf(" node[fIdx]="); C->theNodes[nodes[fixnode]].dump();
00078 CkPrintf("\n");
00079 #endif
00080
00081 if (edges[longEdge].cid == myRef.cid) {
00082 oIdx = nodes[othernode];
00083 fIdx = nodes[fixnode];
00084 }
00085 else {
00086 FEM_Node *theNodes = &(C->meshPtr->node);
00087 FEM_Comm_Rec *oNodeRec=(FEM_Comm_Rec *)(theNodes->shared.getRec(nodes[othernode]));
00088 FEM_Comm_Rec *fNodeRec=(FEM_Comm_Rec *)(theNodes->shared.getRec(nodes[fixnode]));
00089 edge e;
00090 oIdx = oNodeRec->getIdx(e.existsOn(oNodeRec, edges[longEdge].cid));
00091 fIdx = fNodeRec->getIdx(e.existsOn(fNodeRec, edges[longEdge].cid));
00092 #ifdef TDEBUG3
00093 CkPrintf("TMRC2D: [%d] oIdx=%d locally, %d on longEdge's chunk\n",
00094 myRef.cid, nodes[othernode], oIdx);
00095 CkPrintf("TMRC2D: [%d] fIdx=%d locally, %d on longEdge's chunk\n",
00096 myRef.cid, nodes[fixnode], fIdx);
00097 CkPrintf("oNodeRec: chk=%d idx=%d\n", oNodeRec->getChk(0), oNodeRec->getIdx(0));
00098 CkPrintf("fNodeRec: chk=%d idx=%d\n", fNodeRec->getChk(0), fNodeRec->getIdx(0));
00099 #endif
00100 }
00101 CkAssert(fIdx > -1);
00102 CkAssert(oIdx > -1);
00103 CkAssert(oIdx != fIdx);
00104
00105 if ((result=edges[longEdge].split(&m, &e_prime,oIdx, fIdx,
00106 myRef, &local, &first, &nullNbr)) == 1) {
00107
00108 #ifdef TDEBUG2
00109 CkPrintf("TMRC2D: [%d] Refining element %d, opnode=%d ^othernode=%d fixnode=%d longEdge=%d modEdge=%d otherEdge=%d\n", myRef.cid, myRef.idx, nodes[opnode], nodes[othernode], nodes[fixnode], edges[longEdge].idx, edges[modEdge].idx, edges[otherEdge].idx);
00110 #endif
00111 newEdge = C->addEdge(m, nodes[opnode], 0);
00112 #ifdef TDEBUG2
00113 CkPrintf("TMRC2D: [%d] New edge (%d,%d) added between nodes %d and %d\n", myRef.cid, newEdge.cid, newEdge.idx, m, nodes[opnode]);
00114 #endif
00115
00116 if (opnode == 0) {
00117 if (othernode == 1)
00118 newElem = C->addElement(nodes[0], nodes[1], m,
00119 edges[modEdge], e_prime, newEdge);
00120 else
00121 newElem = C->addElement(nodes[0], m, nodes[2],
00122 newEdge, e_prime, edges[modEdge]);
00123 }
00124 else if (opnode == 1) {
00125 if (othernode == 0)
00126 newElem = C->addElement(nodes[0], nodes[1], m,
00127 edges[modEdge], newEdge, e_prime);
00128 else
00129 newElem = C->addElement(m, nodes[1], nodes[2],
00130 newEdge, edges[modEdge], e_prime);
00131 }
00132 else {
00133 if (othernode == 0)
00134 newElem = C->addElement(nodes[0], m, nodes[2],
00135 e_prime, newEdge, edges[modEdge]);
00136 else
00137 newElem = C->addElement(m, nodes[1], nodes[2],
00138 e_prime, edges[modEdge], newEdge);
00139 }
00140 edges[modEdge].update(myRef, newElem, 0);
00141 C->theEdges[newEdge.idx].update(nullRef, myRef);
00142 C->theEdges[newEdge.idx].update(nullRef, newElem);
00143 e_prime.update(nullRef, newElem, 0);
00144 oldothernode = nodes[othernode];
00145 nodes[othernode] = m;
00146 edges[modEdge].checkPending(myRef, newElem);
00147 edges[modEdge] = newEdge;
00148 edges[otherEdge].checkPending(myRef);
00149 C->theElements[newElem.idx].setTargetArea(targetArea);
00150 calculateArea();
00151 C->theElements[newElem.idx].calculateArea();
00152
00153 int flag;
00154 if (local && first) flag = LOCAL_FIRST;
00155 if (local && !first) flag = LOCAL_SECOND;
00156 if (!local && first) flag = BOUND_FIRST;
00157 if (!local && !first) flag = BOUND_SECOND;
00158 int b = 0;
00159 if (nullNbr) b = edges[longEdge].getBoundary();
00160 if(C->theClient) {
00161 C->theClient->split(myRef.idx, oldothernode,nodes[fixnode],nodes[opnode], m, newElem.idx, 0.5, flag,b, 0, b);
00162 #ifdef TDEBUG1
00163 CkPrintf("TMRC2D: [%d] theClient->split(elem=%d, edge=%d, newNode=%d, newElem=%d, bound=%d)\n", myRef.cid, myRef.idx, longEdge, m, newElem.idx, b);
00164 #endif
00165 }
00166
00167 if (!first || nullNbr) {
00168 #ifdef TDEBUG3
00169 if (!first)
00170 CkPrintf("TMRC2D: [%d] Resetting pending edges, second split complete.\n", myRef.cid);
00171 else if (nullNbr)
00172 CkPrintf("TMRC2D: [%d] Resetting pending edges, neighbor NULL.\n",
00173 myRef.cid);
00174 #endif
00175 edges[longEdge].resetEdge();
00176 }
00177 }
00178 else if (result == 0) {
00179
00180 #ifdef TDEBUG2
00181 CkPrintf("TMRC2D: [%d] Refining element %d, opnode=%d othernode=%d ^fixnode=%d longEdge=%d modEdge=%d otherEdge=%d\n", myRef.cid, myRef.idx, nodes[opnode], nodes[othernode], nodes[fixnode], edges[longEdge].idx, edges[modEdge].idx, edges[otherEdge].idx);
00182 #endif
00183 newEdge = C->addEdge(m, nodes[opnode], 0);
00184 #ifdef TDEBUG2
00185 CkPrintf("TMRC2D: [%d] New edge (%d,%d) added between nodes %d and %d\n", myRef.cid, newEdge.cid, newEdge.idx, m, nodes[opnode]);
00186 #endif
00187
00188 if (opnode == 0) {
00189 if (fixnode == 1)
00190 newElem = C->addElement(nodes[0], nodes[1], m,
00191 edges[otherEdge], e_prime, newEdge);
00192 else
00193 newElem = C->addElement(nodes[0], m, nodes[2],
00194 newEdge, e_prime, edges[otherEdge]);
00195 }
00196 else if (opnode == 1) {
00197 if (fixnode == 0)
00198 newElem = C->addElement(nodes[0], nodes[1], m,
00199 edges[otherEdge], newEdge, e_prime);
00200 else
00201 newElem = C->addElement(m, nodes[1], nodes[2],
00202 newEdge, edges[otherEdge], e_prime);
00203 }
00204 else {
00205 if (fixnode == 0)
00206 newElem = C->addElement(nodes[0], m, nodes[2],
00207 e_prime, newEdge, edges[otherEdge]);
00208 else
00209 newElem = C->addElement(m, nodes[1], nodes[2],
00210 e_prime, edges[otherEdge], newEdge);
00211 }
00212 edges[otherEdge].update(myRef, newElem, 0);
00213 C->theEdges[newEdge.idx].update(nullRef, myRef);
00214 C->theEdges[newEdge.idx].update(nullRef, newElem);
00215 e_prime.update(nullRef, newElem, 0);
00216 int oldfixnode = nodes[fixnode];
00217 nodes[fixnode] = m;
00218 edges[otherEdge].checkPending(myRef, newElem);
00219 edges[otherEdge] = newEdge;
00220 edges[modEdge].checkPending(myRef);
00221 C->theElements[newElem.idx].setTargetArea(targetArea);
00222 calculateArea();
00223 C->theElements[newElem.idx].calculateArea();
00224
00225 int flag;
00226 CkAssert(!first);
00227 if (local) flag = LOCAL_SECOND;
00228 else flag = BOUND_SECOND;
00229 int b = 0;
00230 if (nullNbr) b = edges[longEdge].getBoundary();
00231 if (C->theClient) {
00232 C->theClient->split(myRef.idx,oldfixnode,nodes[othernode],nodes[opnode], m, newElem.idx, 0.5,flag,b, 0, b);
00233 #ifdef TDEBUG1
00234 CkPrintf("TMRC2D: [%d] theClient->split(elem=%d, edge=%d, newNode=%d, newElem=%d, bound=%d)\n", myRef.cid, myRef.idx, longEdge, m, newElem.idx, b);
00235 #endif
00236 }
00237 #ifdef TDEBUG3
00238 CkPrintf("TMRC2D: [%d] Resetting pending edges, second split complete.\n",
00239 myRef.cid);
00240 #endif
00241 edges[longEdge].resetEdge();
00242 }
00243 #ifdef TDEBUG2
00244 else {
00245
00246 CkPrintf("TMRC2D: [%d] Can't bisect element %d, longEdge %d pending\n",
00247 myRef.cid, myRef.idx, edges[longEdge].idx);
00248 }
00249 #endif
00250 }
00251
00252 void element::coarsen()
00253 {
00254 int shortEdge = findShortestEdge();
00255
00256 if (!(edges[shortEdge].isPending(myRef))) {
00257 if (edges[(shortEdge+1)%3].isPending(myRef)) {
00258 shortEdge = (shortEdge+1)%3;
00259 }
00260 else if (edges[(shortEdge+2)%3].isPending(myRef)) {
00261 shortEdge = (shortEdge+2)%3;
00262 }
00263 }
00264 collapse(shortEdge);
00265 }
00266
00267
00268 void element::collapse(int shortEdge)
00269 {
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 int opnode, delNode, keepNode, delEdge, keepEdge;
00282 int kBound, dBound, kFixed, dFixed;
00283 elemRef nbr, delNbr, keepNbr;
00284 double frac;
00285
00286 opnode = (shortEdge+2)%3; delNode = shortEdge; keepNode = (shortEdge+1)%3;
00287 delEdge = opnode; keepEdge = keepNode;
00288
00289 kBound = C->theNodes[nodes[keepNode]].boundary;
00290 dBound = C->theNodes[nodes[delNode]].boundary;
00291 kFixed = C->theNodes[nodes[keepNode]].fixed;
00292 dFixed = C->theNodes[nodes[delNode]].fixed;
00293 keepNbr = edges[keepEdge].getNbr(myRef);
00294 delNbr = edges[delEdge].getNbr(myRef);
00295 nbr = edges[shortEdge].getNbr(myRef);
00296
00297 if (!safeToCoarsen(&nonCoarsenCount, shortEdge, delNbr, keepNbr,nbr)) return;
00298
00299
00300 node newNode;
00301 if (!findNewNodeDetails(&newNode, &frac, kBound, dBound, kFixed, dFixed,
00302 &keepNode, &delNode, &nonCoarsenCount, &keepEdge,
00303 &delEdge, &keepNbr, &delNbr, &nbr))
00304 return;
00305
00306
00307 int kIdx, dIdx;
00308 translateNodeIDs(&kIdx, &dIdx, shortEdge, keepNode, delNode);
00309
00310 #ifdef FLIPPREVENT
00311 if (edges[shortEdge].flipPrevent(myRef, kIdx, dIdx, keepNbr, delNbr,
00312 edges[keepEdge], edges[delEdge], newNode)
00313 == -1) {
00314 nonCoarsenCount++;
00315 return;
00316 }
00317 #endif
00318
00319
00320 present = 0;
00321 edges[shortEdge].collapse(myRef, kIdx, dIdx, keepNbr, delNbr,
00322 edges[keepEdge], edges[delEdge], newNode, frac);
00323 present = 1;
00324 C->removeElement(myRef.idx);
00325 }
00326
00327 int element::findLongestEdge()
00328 {
00329 int i, longEdge;
00330 double maxlen = 0.0, len[3];
00331
00332 len[0] = C->theNodes[nodes[0]].distance(C->theNodes[nodes[1]]);
00333 len[1] = C->theNodes[nodes[1]].distance(C->theNodes[nodes[2]]);
00334 len[2] = C->theNodes[nodes[2]].distance(C->theNodes[nodes[0]]);
00335 for (i=0; i<3; i++)
00336 if (len[i] > maxlen) {
00337 longEdge = i;
00338 maxlen = len[i];
00339 }
00340 CkAssert(longEdge > -1);
00341 CkAssert(longEdge < 3);
00342 return longEdge;
00343 }
00344
00345 int element::findShortestEdge()
00346 {
00347 int i, shortEdge = 0;
00348 double minlen, len[3];
00349
00350 minlen = len[0] = C->theNodes[nodes[0]].distance(C->theNodes[nodes[1]]);
00351 len[1] = C->theNodes[nodes[1]].distance(C->theNodes[nodes[2]]);
00352 len[2] = C->theNodes[nodes[2]].distance(C->theNodes[nodes[0]]);
00353 for (i=1; i<3; i++)
00354 if (len[i] < minlen) {
00355 shortEdge = i;
00356 minlen = len[i];
00357 }
00358 return shortEdge;
00359 }
00360
00361 double element::getShortestEdge(double *angle)
00362 {
00363 double minlen, len[3];
00364 int shortest=0;
00365
00366 minlen = len[0] = C->theNodes[nodes[0]].distance(C->theNodes[nodes[1]]);
00367 len[1] = C->theNodes[nodes[1]].distance(C->theNodes[nodes[2]]);
00368 len[2] = C->theNodes[nodes[2]].distance(C->theNodes[nodes[0]]);
00369 for (int i=1; i<3; i++)
00370 if (len[i] < minlen) {
00371 shortest = i;
00372 minlen = len[i];
00373 }
00374 double A, B, C;
00375 C = len[shortest];
00376 A = len[(shortest+1)%3];
00377 B = len[(shortest+2)%3];
00378 (*angle) = acos((C*C - A*A - B*B)/(-2*A*B));
00379 return minlen;
00380 }
00381
00382 double element::getAreaQuality()
00383 {
00384 double f, q, len[3];
00385 len[0] = C->theNodes[nodes[0]].distance(C->theNodes[nodes[1]]);
00386 len[1] = C->theNodes[nodes[1]].distance(C->theNodes[nodes[2]]);
00387 len[2] = C->theNodes[nodes[2]].distance(C->theNodes[nodes[0]]);
00388 f = 4.0*sqrt(3.0);
00389 q = (f*currentArea)/(len[0]*len[0]+len[1]*len[1]+len[2]*len[2]);
00390 return q;
00391 }
00392
00393 double element::getLargestEdge(double *angle)
00394 {
00395 double maxlen, len[3];
00396 int largest=0;
00397
00398 maxlen = len[0] = C->theNodes[nodes[0]].distance(C->theNodes[nodes[1]]);
00399 len[1] = C->theNodes[nodes[1]].distance(C->theNodes[nodes[2]]);
00400 len[2] = C->theNodes[nodes[2]].distance(C->theNodes[nodes[0]]);
00401 for (int i=1; i<3; i++)
00402 if (len[i] > maxlen) {
00403 largest = i;
00404 maxlen = len[i];
00405 }
00406 double A, B, C;
00407 C = len[largest];
00408 A = len[(largest+1)%3];
00409 B = len[(largest+2)%3];
00410 (*angle) = acos((C*C - A*A - B*B)/(-2*A*B));
00411 return maxlen;
00412 }
00413
00414 int element::isLongestEdge(edgeRef& e)
00415 {
00416 int longEdge = findLongestEdge();
00417 return (edges[longEdge] == e);
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 void element::sanityCheck(chunk *c, elemRef shouldRef, int n)
00477 {
00478 CkAssert(myRef == shouldRef);
00479 CkAssert(C == c);
00480 for (int i=0;i<3;i++) {
00481 CkAssert((nodes[i] < n) && (nodes[i] > -1));
00482 CkAssert(!(edges[i].isNull()));
00483 edges[i].sanityCheck();
00484 if (edges[i].cid == myRef.cid)
00485 C->theEdges[edges[i].idx].sanityCheck(nodes[i],nodes[(i+1)%3],myRef.idx);
00486 }
00487 CkAssert(nodes[0] != nodes[1]);
00488 CkAssert(nodes[0] != nodes[2]);
00489 CkAssert(nodes[2] != nodes[1]);
00490 }
00491
00492 void element::incnonCoarsen() {
00493 nonCoarsenCount++;
00494 return;
00495 }
00496
00497 bool element::flipTest(node* oldnode, node* newnode) {
00498
00499 }
00500
00501 bool element::flipInverseTest(node* oldnode, node* newnode) {
00502 double x0,x1,x2,x3,y0,y1,y2,y3;
00503 int i=0;
00504
00505 for(i=0; i<3; i++) {
00506 if( oldnode->X() == C->theNodes[nodes[i]].X() && oldnode->Y() == C->theNodes[nodes[i]].Y() ) {
00507 break;
00508 }
00509 }
00510 x0 = C->theNodes[nodes[(i+1)%3]].X();
00511 x1 = oldnode->X();
00512 x2 = C->theNodes[nodes[(i+2)%3]].X();
00513 x3 = newnode->X();
00514 y0 = C->theNodes[nodes[(i+1)%3]].Y();
00515 y1 = oldnode->Y();
00516 y2 = C->theNodes[nodes[(i+2)%3]].Y();
00517 y3 = newnode->Y();
00518
00519
00520 double res1 = (x0-x1)*(y2-y1) - (y0-y1)*(x2-x1);
00521 double res2 = (x0-x3)*(y2-y3) - (y0-y3)*(x2-x3);
00522
00523
00524
00525 if((res1>0 && res2>0)||(res1<=0 && res2<=0)) return false;
00526 else if(fabs(res2) < ZEROAREA) {
00527 CkPrintf("Zero area: Chunk %d Elem %d (%lf,%lf);(%lf,%lf)--(%lf,%lf)--(%lf,%lf)\n",myRef.cid,myRef.idx,x0,y0,x2,y2,x1,y1,x3,y3);
00528 return true;
00529 }
00530 else {
00531 CkPrintf("Flip: Chunk %d Elem %d -- (%lf,%lf);(%lf,%lf)--(%lf,%lf)--(%lf,%lf)\n",myRef.cid,myRef.idx,x0,y0,x2,y2,x1,y1,x3,y3);
00532 return true;
00533 }
00534 }
00535
00536
00537 int element::findNewNodeDetails(node *newNode, double *frac, int kBc, int dBc,
00538 int kFx, int dFx, int *kNd, int *dNd,
00539 short *nonCC, int *kEg, int *dEg,
00540 elemRef *kNbr, elemRef *dNbr, elemRef *nbr)
00541 {
00542 int tmpMap;
00543 elemRef tmpRef;
00544 if ((kBc == 0) && (dBc == 0)) {
00545 if (!kFx && !dFx) {
00546 (*newNode)=C->theNodes[nodes[(*kNd)]].midpoint(C->theNodes[nodes[(*dNd)]]);
00547 (*newNode).boundary = 0;
00548 (*frac) = 0.5;
00549 return 1;
00550 }
00551 else if (dFx && kFx) (*nonCC)++;
00552 else if (dFx) {
00553 (*newNode) = C->theNodes[nodes[(*dNd)]];
00554 tmpMap = (*dNd); (*dNd) = (*kNd); (*kNd) = tmpMap;
00555 tmpMap = (*dEg); (*dEg) = (*kEg); (*kEg) = tmpMap;
00556 tmpRef = (*dNbr); (*dNbr) = (*kNbr); (*kNbr) = tmpRef;
00557 (*frac) = 1.0;
00558 return 1;
00559 }
00560 else {
00561 (*newNode) = C->theNodes[nodes[(*kNd)]];
00562 (*frac) = 1.0;
00563 return 1;
00564 }
00565 }
00566 else if ((kBc == 0) || (dBc == 0)) {
00567
00568 if (kBc && !dFx) {
00569 (*newNode) = C->theNodes[nodes[(*kNd)]];
00570 (*frac) = 1.0;
00571 return 1;
00572 }
00573 else if (dBc && !kFx) {
00574 (*newNode) = C->theNodes[nodes[(*dNd)]];
00575 tmpMap = (*dNd); (*dNd) = (*kNd); (*kNd) = tmpMap;
00576 tmpMap = (*dEg); (*dEg) = (*kEg); (*kEg) = tmpMap;
00577 tmpRef = (*dNbr); (*dNbr) = (*kNbr); (*kNbr) = tmpRef;
00578 (*frac) = 1.0;
00579 return 1;
00580 }
00581 else (*nonCC)++;
00582 }
00583 else if (kBc == dBc) {
00584 if (nbr->cid >= 0) (*nonCC)++;
00585
00586 else if (kFx && dFx) (*nonCC)++;
00587 else if (kFx || dFx) {
00588 if (kFx) {
00589 (*newNode) = C->theNodes[nodes[(*kNd)]];
00590 (*frac) = 1.0;
00591 return 1;
00592 }
00593 else {
00594 (*newNode) = C->theNodes[nodes[(*dNd)]];
00595 tmpMap = (*dNd); (*dNd) = (*kNd); (*kNd) = tmpMap;
00596 tmpMap = (*dEg); (*dEg) = (*kEg); (*kEg) = tmpMap;
00597 tmpRef = (*dNbr); (*dNbr) = (*kNbr); (*kNbr) = tmpRef;
00598 (*frac) = 1.0;
00599 return 1;
00600 }
00601 }
00602 else {
00603 (*newNode)=C->theNodes[nodes[(*kNd)]].midpoint(C->theNodes[nodes[(*dNd)]]);
00604 (*newNode).boundary = kBc;
00605 (*frac) = 0.5;
00606 return 1;
00607 }
00608 }
00609 else {
00610 if (nbr->cid >= 0) (*nonCC)++;
00611 else {
00612 if (dBc > kBc) {
00613 if (kFx) (*nonCC)++;
00614 else {
00615 (*newNode) = C->theNodes[nodes[(*dNd)]];
00616 tmpMap = (*dNd); (*dNd) = (*kNd); (*kNd) = tmpMap;
00617 tmpMap = (*dEg); (*dEg) = (*kEg); (*kEg) = tmpMap;
00618 tmpRef = (*dNbr); (*dNbr) = (*kNbr); (*kNbr) = tmpRef;
00619 (*frac) = 1.0;
00620 return 1;
00621 }
00622 }
00623 else {
00624 if (dFx) (*nonCC)++;
00625 else {
00626 (*newNode) = C->theNodes[nodes[(*kNd)]];
00627 (*frac) = 1.0;
00628 return 1;
00629 }
00630 }
00631 }
00632 }
00633 return 0;
00634 }
00635
00636 void element::translateNodeIDs(int *kIdx, int *dIdx, int sEg, int kNd, int dNd)
00637 {
00638 if (edges[sEg].cid == myRef.cid) {
00639 (*kIdx) = nodes[kNd];
00640 (*dIdx) = nodes[dNd];
00641 }
00642 else {
00643 FEM_Node *theNodes = &(C->meshPtr->node);
00644 FEM_Comm_Rec *dNodeRec=(FEM_Comm_Rec *)(theNodes->shared.getRec(nodes[dNd]));
00645 FEM_Comm_Rec *kNodeRec=(FEM_Comm_Rec *)(theNodes->shared.getRec(nodes[kNd]));
00646 edge e;
00647 (*kIdx) = kNodeRec->getIdx(e.existsOn(kNodeRec, edges[sEg].cid));
00648 (*dIdx) = dNodeRec->getIdx(e.existsOn(dNodeRec, edges[sEg].cid));
00649 }
00650 }
00651
00652 int element::safeToCoarsen(short *nonCC, int sEg, elemRef dNbr, elemRef kNbr,
00653 elemRef nbr)
00654 {
00655 if (!edges[sEg].isPending(myRef)) {
00656 if ((dNbr == kNbr) && (dNbr.cid != -1)) {
00657 (*nonCC)++;
00658 return 0;
00659 }
00660 else if ((dNbr.cid != -1) && (kNbr.cid != -1) &&
00661 (neighboring(dNbr, kNbr))) {
00662 (*nonCC)++;
00663 return 0;
00664 }
00665 else if (nbr.cid != -1) {
00666 intMsg *im;
00667 im = mesh[nbr.cid].safeToCoarsen(nbr.idx, edges[sEg]);
00668 if (im->anInt == 0) (*nonCC)++;
00669 return im->anInt;
00670 }
00671 }
00672 return 1;
00673 }
00674
00675 int element::safeToCoarsen(edgeRef ser) {
00676 elemRef nbr1, nbr2;
00677 for (int i=0; i<3; i++) {
00678 if (edges[i] == ser) {
00679 nbr1 = edges[(i+1)%3].getNbr(myRef);
00680 nbr2 = edges[(i+2)%3].getNbr(myRef);
00681 break;
00682 }
00683 }
00684 if (nbr1 == nbr2) return 0;
00685 if ((nbr1.cid == -1) || (nbr2.cid == -1)) return 1;
00686 return (!neighboring(nbr1, nbr2));
00687 }
00688
00689 int element::neighboring(elemRef e1, elemRef e2) {
00690 intMsg *im;
00691 if ((e1.cid == -1) || (e2.cid == -1)) return 0;
00692 im = mesh[e1.cid].neighboring(e1.idx, e2);
00693 return im->anInt;
00694 }
00695
00696 int element::neighboring(elemRef e) {
00697 return ((edges[0].getNbr(myRef) == e) || (edges[1].getNbr(myRef) == e) ||
00698 (edges[2].getNbr(myRef) == e));
00699 }