00001
00002
00003 #include "element.h"
00004 #include "chunk.h"
00005 #include "matrix.h"
00006
00007 void element::setTargetVolume(double volume) {
00008 if ((volume < targetVolume) || (targetVolume < 0.0)) targetVolume = volume;
00009 }
00010
00011 void element::update(nodeRef& oldval, nodeRef& newval)
00012 {
00013 if (nodes[0] == oldval) nodes[0] = newval;
00014 else if (nodes[1] == oldval) nodes[1] = newval;
00015 else if (nodes[2] == oldval) nodes[2] = newval;
00016 else if (nodes[3] == oldval) nodes[3] = newval;
00017 else CkPrintf("ERROR: element::update: oldval not found\n");
00018 }
00019
00020 int element::hasNode(nodeRef n)
00021 {
00022 return ((n==nodes[0]) || (n==nodes[1]) || (n==nodes[2]) || (n==nodes[3]));
00023 }
00024
00025 int element::hasNode(node n)
00026 {
00027 node nodeCoords[4];
00028 for (int i=0; i<4; i++) nodeCoords[i] = C->theNodes[nodes[i].idx];
00029 return ((n==nodeCoords[0]) || (n==nodeCoords[1]) || (n==nodeCoords[2])
00030 || (n==nodeCoords[3]));
00031 }
00032
00033 int element::hasNodes(nodeRef n1, nodeRef n2, nodeRef n3)
00034 {
00035 return (hasNode(n1) && hasNode(n2) && hasNode(n3));
00036 }
00037
00038 int element::hasNodes(double nodeCoords[3][3])
00039 {
00040 node inNodes[3];
00041 inNodes[0].set(nodeCoords[0][0], nodeCoords[0][1], nodeCoords[0][2]);
00042 inNodes[1].set(nodeCoords[1][0], nodeCoords[1][1], nodeCoords[1][2]);
00043 inNodes[2].set(nodeCoords[2][0], nodeCoords[2][1], nodeCoords[2][2]);
00044 return (hasNode(inNodes[0]) && hasNode(inNodes[1]) && hasNode(inNodes[2]));
00045 }
00046
00047 int element::getNode(node n) {
00048 for (int i=0; i<4; i++)
00049 if (C->theNodes[nodes[i].idx] == n)
00050 return i;
00051 return -1;
00052 }
00053
00054 int element::getNodeIdx(nodeRef n)
00055 {
00056 if (nodes[0] == n) return 0;
00057 else if (nodes[1] == n) return 1;
00058 else if (nodes[2] == n) return 2;
00059 else if (nodes[3] == n) return 3;
00060 else {
00061 CkPrintf("ERROR: element::getNodeIdx: nodeRef n not found on element.\n");
00062 return -1;
00063 }
00064 }
00065
00066 int element::checkFace(node n1, node n2, node n3, elemRef nbr)
00067 {
00068 int a=-1, b=-1, c=-1, d=-1;
00069 elemRef abc, abd, acd, bcd;
00070 double Aabc, Aabd, Aacd, Abcd;
00071
00072 a = getNode(n1);
00073 b = getNode(n2);
00074 c = getNode(n3);
00075 d = 6-a-b-c;
00076 abc = faceElements[a+b+c-3];
00077 abd = faceElements[a+b+d-3];
00078 acd = faceElements[a+c+d-3];
00079 bcd = faceElements[b+c+d-3];
00080 CmiAssert(abc == nbr);
00081 Aabc = getArea(a, b, c);
00082 Aabd = getArea(a, b, d);
00083 Aacd = getArea(a, c, d);
00084 Abcd = getArea(b, c, d);
00085 if ((Aabc >= Aabd) && (Aabc >= Aacd) && (Aabc >= Abcd))
00086 return 1;
00087 mesh[myRef.cid].refineElement(myRef.idx, getVolume()/2.0);
00088 return 0;
00089 }
00090
00091 double element::getVolume()
00092 {
00093 if (currentVolume < 0.0)
00094 calculateVolume();
00095 return currentVolume;
00096 }
00097
00098 void element::calculateVolume()
00099 {
00100 Matrix mtx(4);
00101 int i, j;
00102
00103
00104 for (i=0; i<4; i++)
00105 for (j=0; j<3; j++)
00106 mtx.setElement(i, j, C->theNodes[nodes[i].idx].getCoord(j));
00107 for (i=0; i<4; i++)
00108 mtx.setElement(i, 3, 1.0);
00109 currentVolume = mtx.determinant() / 6.0;
00110 if (currentVolume < 0.0) currentVolume *= -1.0;
00111 }
00112
00113 double element::getArea(int n1, int n2, int n3)
00114 {
00115
00116
00117 node n[3];
00118 double s, perimeter, len[3];
00119 n[0] = C->theNodes[nodes[n1].idx];
00120 n[1] = C->theNodes[nodes[n2].idx];
00121 n[2] = C->theNodes[nodes[n3].idx];
00122
00123 len[0] = n[0].distance(n[1]);
00124 len[1] = n[0].distance(n[2]);
00125 len[2] = n[1].distance(n[2]);
00126
00127 perimeter = len[0] + len[1] + len[2];
00128 s = perimeter / 2.0;
00129
00130 return(sqrt(s * (s - len[0]) * (s - len[1]) * (s - len[2])));
00131 }
00132
00133 double element::findLongestEdge(int *le1, int *le2, int *nl1, int *nl2)
00134 {
00135 double maxLength = 0.0, length;
00136 for (int i=0; i<4; i++)
00137 for (int j=i+1; j<4; j++) {
00138 length = C->theNodes[nodes[i].idx].distance(C->theNodes[nodes[j].idx]);
00139 if (length > maxLength) {
00140 maxLength = length;
00141 *le1 = i; *le2 = j;
00142 }
00143 }
00144 if (*le1 == 0) {
00145 if (*le2 == 1) { *nl1 = 2; *nl2 = 3; }
00146 else if (*le2 == 2) { *nl1 = 1; *nl2 = 3; }
00147 else { *nl1 = 1; *nl2 = 2; }
00148 }
00149 else if (*le1 == 1) {
00150 if (*le2 == 2) { *nl1 = 0; *nl2 = 3; }
00151 else { *nl1 = 0; *nl2 = 2; }
00152 }
00153 else { *nl1 = 0; *nl2 = 1; }
00154 return maxLength;
00155 }
00156
00157
00158
00159 void element::flip23(int face[3])
00160 {
00161
00162
00163 int a = face[0], b = face[1], c = face[2], d = 6 - (face[0]+face[1]+face[2]);
00164 int ap, bp, cp, ep;
00165
00166 elemRef nbrRef = getFace(a, b, c), acdNbr = getFace(a, c, d),
00167 bcdNbr = getFace(b, c, d);
00168 elemRef abeNbr, aceNbr, bceNbr, newElem;
00169
00170 if (nbrRef.cid == myRef.cid) {
00171
00172 ap = C->theElements[nbrRef.idx].getNodeIdx(nodes[a]);
00173 bp = C->theElements[nbrRef.idx].getNodeIdx(nodes[b]);
00174 cp = C->theElements[nbrRef.idx].getNodeIdx(nodes[c]);
00175 ep = 6 - (ap+bp+cp);
00176
00177 abeNbr = C->theElements[nbrRef.idx].getFace(ap, bp, ep);
00178 aceNbr = C->theElements[nbrRef.idx].getFace(ap, cp, ep);
00179 bceNbr = C->theElements[nbrRef.idx].getFace(bp, cp, ep);
00180
00181 newElem = C->addElement(nodes[a], nodes[c], nodes[d],
00182 C->theElements[nbrRef.idx].nodes[ep]);
00183
00184 C->theElements[newElem.idx].faceElements[0] = acdNbr;
00185 C->theElements[newElem.idx].faceElements[1] = aceNbr;
00186 C->theElements[newElem.idx].faceElements[2] = myRef;
00187 C->theElements[newElem.idx].faceElements[3] = nbrRef;
00188
00189 nodes[c] = C->theElements[nbrRef.idx].nodes[ep];
00190
00191 faceElements[0] = abeNbr;
00192 faceElements[2] = newElem;
00193 faceElements[3] = nbrRef;
00194
00195 C->theElements[nbrRef.idx].nodes[ap] = nodes[d];
00196
00197 C->theElements[nbrRef.idx].setFace(ap, bp, cp, bcdNbr);
00198 C->theElements[nbrRef.idx].setFace(ap, bp, ep, myRef);
00199 C->theElements[nbrRef.idx].setFace(ap, cp, ep, newElem);
00200
00201 mesh[acdNbr.cid].updateFace(acdNbr.idx, myRef, newElem);
00202 mesh[aceNbr.cid].updateFace(aceNbr.idx, nbrRef, newElem);
00203 mesh[abeNbr.cid].updateFace(abeNbr.idx, nbrRef, myRef);
00204 mesh[bcdNbr.cid].updateFace(bcdNbr.idx, myRef, nbrRef);
00205 }
00206 else {
00207 flip23request *fr = new flip23request;
00208 flip23response *rf;
00209
00210
00211 fr->a = C->theNodes[nodes[a].idx];
00212 fr->b = C->theNodes[nodes[b].idx];
00213 fr->c = C->theNodes[nodes[c].idx];
00214 fr->d = C->theNodes[nodes[d].idx];
00215 fr->acd = acdNbr;
00216 fr->bcd = bcdNbr;
00217 fr->requester = myRef;
00218 fr->requestee = nbrRef.idx;
00219
00220 rf = mesh[nbrRef.cid].flip23remote(fr);
00221
00222
00223
00224 if (getFace(a, c, d).idx == -1)
00225 C->removeFace(nodes[a].idx, nodes[c].idx, nodes[d].idx);
00226 if (getFace(b, c, d).idx == -1)
00227 C->removeFace(nodes[b].idx, nodes[c].idx, nodes[d].idx);
00228
00229
00230 nodeRef eRef = C->findNode(rf->e);
00231 if (eRef.idx == -1)
00232 eRef = C->addNode(rf->e);
00233
00234
00235 nodes[c] = eRef;
00236
00237 setFace(a, b, c, rf->abe);
00238 setFace(a, c, d, rf->acde);
00239 setFace(b, c, d, nbrRef);
00240 if (rf->abe.idx == -1)
00241 C->addFace(nodes[a].idx, nodes[b].idx, nodes[c].idx);
00242
00243 mesh[acdNbr.cid].updateFace(acdNbr.idx, myRef, rf->acde);
00244 mesh[bcdNbr.cid].updateFace(bcdNbr.idx, myRef, nbrRef);
00245 }
00246 }
00247
00248 flip23response *element::flip23remote(flip23request *fr)
00249 {
00250 int a, b, c, e;
00251 elemRef newElem, abeNbr, aceNbr;
00252 flip23response *rf = new flip23response;
00253
00254
00255 nodeRef dRef = C->findNode(fr->d);
00256 if (dRef.idx == -1)
00257 dRef = C->addNode(fr->d);
00258
00259
00260 for (int i=0; i<4; i++)
00261 if (C->theNodes[nodes[i].idx] == fr->a)
00262 a = i;
00263 else if (C->theNodes[nodes[i].idx] == fr->b)
00264 b = i;
00265 else if (C->theNodes[nodes[i].idx] == fr->c)
00266 c = i;
00267 e = 6 - (a + b + c);
00268 abeNbr = getFace(a, b, e);
00269 aceNbr = getFace(a, c, e);
00270
00271
00272 if (getFace(a, b, e).idx == -1)
00273 C->removeFace(nodes[a].idx, nodes[b].idx, nodes[e].idx);
00274
00275
00276 if (fr->acd.idx == -1)
00277 C->addFace(nodes[a].idx, nodes[c].idx, dRef.idx);
00278 if (fr->bcd.idx == -1)
00279 C->addFace(nodes[b].idx, nodes[c].idx, dRef.idx);
00280
00281
00282 newElem = C->addElement(nodes[a], nodes[c], dRef, nodes[e]);
00283
00284 C->theElements[newElem.idx].setFace(0, fr->acd);
00285 C->theElements[newElem.idx].setFace(1, aceNbr);
00286 C->theElements[newElem.idx].setFace(2, fr->requester);
00287 C->theElements[newElem.idx].setFace(3, myRef);
00288
00289
00290 nodes[a] = dRef;
00291
00292 setFace(a, b, c, fr->bcd);
00293 setFace(a, b, e, fr->requester);
00294 setFace(a, c, e, newElem);
00295
00296
00297 mesh[abeNbr.cid].updateFace(abeNbr.idx, myRef, fr->requester);
00298 mesh[aceNbr.cid].updateFace(aceNbr.idx, myRef, newElem);
00299
00300
00301 rf->acde = newElem;
00302 rf->abe = abeNbr;
00303 rf->e = C->theNodes[nodes[e].idx];
00304
00305 CkFreeMsg(fr);
00306 return rf;
00307 }
00308
00309
00310 void element::flip32(int edge[2])
00311 {
00312 int a = 0, b, d = edge[0], e = edge[1];
00313 elemRef acde, bcde, abeNbr;
00314
00315
00316 if ((d == 0) || (e == 0)) {
00317 a = 1;
00318 if ((d == 1) || (e == 1)) {
00319 a = 2;
00320 if ((d == 2) || (e == 2)) a = 3;
00321 }
00322 }
00323 b = 6 - (a + d + e);
00324
00325
00326 acde = getFace(a, d, e);
00327 bcde = getFace(b, d, e);
00328
00329 abeNbr = getFace(a, b, e);
00330
00331
00332
00333 flip32request *fr1 = new flip32request;
00334 flip32response *rf1;
00335 fr1->requestee = bcde.idx;
00336 fr1->requester = myRef;
00337 fr1->b = C->theNodes[nodes[b].idx];
00338 fr1->d = C->theNodes[nodes[d].idx];
00339 fr1->e = C->theNodes[nodes[e].idx];
00340 if (bcde.cid == myRef.cid)
00341 rf1 = C->theElements[bcde.idx].remove32element(fr1);
00342 else rf1 = mesh[bcde.cid].remove32element(fr1);
00343
00344
00345
00346
00347 flip32request *fr2 = new flip32request;
00348 flip32response *rf2;
00349 fr2->requestee = acde.idx;
00350 fr2->bcde = bcde;
00351 fr2->requester = myRef;
00352 fr2->a = C->theNodes[nodes[a].idx];
00353 fr2->d = C->theNodes[nodes[d].idx];
00354 fr2->e = C->theNodes[nodes[e].idx];
00355 fr2->abe = abeNbr;
00356 fr2->bce = rf1->bce;
00357 if (acde.cid == myRef.cid)
00358 rf2 = C->theElements[acde.idx].flip32remote(fr2);
00359 else rf2 = mesh[acde.cid].flip32remote(fr2);
00360
00361
00362
00363 if ( !(rf1->c == rf2->c) )
00364 CkPrintf("ERROR: flip32: Neighbors disagree about node c.\n");
00365
00366
00367 nodeRef cRef = C->findNode(rf1->c);
00368 if (cRef.idx == -1)
00369 cRef = C->addNode(rf1->c);
00370
00371
00372 if ((abeNbr.idx == -1) && (acde.cid != myRef.cid))
00373 C->removeFace(nodes[a].idx, nodes[b].idx, nodes[e].idx);
00374
00375 if ((rf2->acd.idx == -1) && (acde.cid != myRef.cid))
00376 C->addFace(nodes[a].idx, cRef.idx, nodes[d].idx);
00377 if ((rf1->bcd.idx == -1) && (bcde.cid != myRef.cid))
00378 C->addFace(nodes[b].idx, cRef.idx, nodes[d].idx);
00379
00380
00381 nodes[e] = cRef;
00382
00383 setFace(a, b, e, acde);
00384 setFace(a, d, e, rf2->acd);
00385 setFace(b, d, e, rf1->bcd);
00386
00387 mesh[rf2->acd.cid].updateFace(rf2->acd.idx, acde, myRef);
00388 mesh[rf1->bcd.cid].updateFace(rf1->bcd.idx, bcde, myRef);
00389 }
00390
00391 flip32response *element::flip32remote(flip32request *fr)
00392 {
00393
00394 flip32response *rf = new flip32response();
00395 int a, b, c, d, e;
00396 elemRef acdNbr;
00397
00398
00399 for (int i=0; i<4; i++) {
00400 if (C->theNodes[nodes[i].idx] == fr->a)
00401 a = i;
00402 else if (C->theNodes[nodes[i].idx] == fr->d)
00403 d = i;
00404 else if (C->theNodes[nodes[i].idx] == fr->e)
00405 e = i;
00406 else
00407 c = i;
00408 }
00409 acdNbr = getFace(a, c, d);
00410
00411
00412 rf->acd = acdNbr;
00413 rf->c = C->theNodes[nodes[c].idx];
00414
00415
00416 nodeRef bRef = C->findNode(fr->b);
00417 if (bRef.idx == -1)
00418 bRef = C->addNode(fr->b);
00419
00420
00421 b = d;
00422 nodes[b] = bRef;
00423 setFace(a, b, e, fr->abe);
00424 setFace(b, c, e, fr->bce);
00425 setFace(a, b, c, fr->requester);
00426
00427
00428 if (acdNbr.idx == -1)
00429 C->removeFace(nodes[a].idx, nodes[c].idx, nodes[d].idx);
00430
00431
00432 if (fr->abe.idx == -1)
00433 C->addFace(nodes[a].idx, nodes[b].idx, nodes[e].idx);
00434 if (fr->bce.idx == -1)
00435 C->addFace(nodes[b].idx, nodes[c].idx, nodes[e].idx);
00436
00437
00438 mesh[fr->abe.cid].updateFace(fr->abe.idx, fr->requester, myRef);
00439 mesh[fr->bce.cid].updateFace(fr->bce.idx, fr->bcde, myRef);
00440
00441 CkFreeMsg(fr);
00442 return rf;
00443 }
00444
00445 flip32response *element::remove32element(flip32request *fr)
00446 {
00447
00448 flip32response *rf = new flip32response;
00449 int b, c, d, e;
00450 elemRef bcdNbr, bceNbr;
00451
00452
00453 for (int i=0; i<4; i++) {
00454 if (C->theNodes[nodes[i].idx] == fr->b)
00455 b = i;
00456 else if (C->theNodes[nodes[i].idx] == fr->d)
00457 d = i;
00458 else if (C->theNodes[nodes[i].idx] == fr->e)
00459 e = i;
00460 else
00461 c = i;
00462 }
00463 bcdNbr = getFace(b, c, d);
00464 bceNbr = getFace(b, c, e);
00465
00466
00467 rf->bcd = bcdNbr;
00468 rf->bce = bceNbr;
00469 rf->c = C->theNodes[nodes[c].idx];
00470
00471
00472
00473 if (bcdNbr.idx == -1)
00474 C->removeFace(nodes[b].idx, nodes[c].idx, nodes[d].idx);
00475 if (bceNbr.idx == -1)
00476 C->removeFace(nodes[b].idx, nodes[c].idx, nodes[e].idx);
00477
00478
00479 present = 0;
00480
00481
00482 CkFreeMsg(fr);
00483 return rf;
00484 }
00485
00486
00487
00488 int element::test23(int face[3])
00489 {
00490 return 0;
00491 }
00492
00493
00494
00495 int element::test32(int edge[2])
00496 {
00497 return 0;
00498 }
00499
00500 int element::connectTest()
00501 {
00502 intMsg *result;
00503 for (int i=0; i<4; i++) {
00504
00505 result = mesh[faceElements[i].cid].checkFace(faceElements[i].idx, myRef);
00506 if (!result->anInt) return 0;
00507 CkPrintf("Face %d is fine...\n", i);
00508 }
00509 return 1;
00510 }
00511
00512 int element::hasFace(elemRef face)
00513 {
00514 return((faceElements[0] == face) || (faceElements[1] == face) ||
00515 (faceElements[2] == face) || (faceElements[3] == face));
00516 }
00517
00518
00519 void element::refineLF()
00520 {
00521 static int start = 0;
00522 int lf, a, b, c, d;
00523 node n1, n2, n3, n4, centerpoint;
00524 elemRef abc, acd, bcd;
00525 double f[4], length;
00526
00527
00528
00529 f[0] = getArea(0,1,2);
00530 f[1] = getArea(0,1,3);
00531 f[2] = getArea(0,2,3);
00532 f[3] = getArea(1,2,3);
00533 lf = start;
00534 for (int i=0; i<4; i++) if (f[i] > f[lf]) lf = i;
00535
00536 a = (lf == 3) ? 1 : 0;
00537 b = (lf > 1) ? 2 : 1;
00538 c = (lf == 0) ? 2 : 3;
00539 CmiAssert(a+b+c-3 == lf);
00540 abc = faceElements[a+b+c-3];
00541
00542 if (abc.cid != -1) {
00543 n1 = C->theNodes[nodes[a].idx];
00544 n2 = C->theNodes[nodes[b].idx];
00545 n3 = C->theNodes[nodes[c].idx];
00546 intMsg *im = mesh[abc.cid].checkFace(abc.idx, n1, n2, n3, myRef);
00547 if (!im->anInt) {
00548 CkFreeMsg(im);
00549 return;
00550 }
00551 }
00552
00553
00554
00555 if ((currentVolume < targetVolume) || (currentVolume == 0.0)
00556 || (targetVolume == 0.0)) {
00557 return;
00558 }
00559
00560
00561 int iResult;
00562 intMsg *result;
00563 length = findLongestEdge(&a, &b, &c, &d);
00564 iResult = C->lockLocalChunk(myRef.cid, length);
00565 while (iResult != 1) {
00566 if (iResult == 0) return;
00567 else if (iResult == -1) {
00568 CthYield();
00569 length = findLongestEdge(&a, &b, &c, &d);
00570 iResult = C->lockLocalChunk(myRef.cid, length);
00571 }
00572 }
00573
00574 f[0] = getArea(0,1,2);
00575 f[1] = getArea(0,1,3);
00576 f[2] = getArea(0,2,3);
00577 f[3] = getArea(1,2,3);
00578 lf = start;
00579 for (int i=0; i<4; i++) if (f[i] > f[lf]) lf = i;
00580 start = (start+1) % 4;
00581
00582 a = (lf == 3) ? 1 : 0;
00583 b = (lf > 1) ? 2 : 1;
00584 c = (lf == 0) ? 2 : 3;
00585 d = 3 - lf;
00586 CmiAssert(a+b+c-3 == lf);
00587 abc = faceElements[a+b+c-3];
00588 acd = faceElements[a+c+d-3];
00589 bcd = faceElements[b+c+d-3];
00590
00591 CkPrintf("-> Refine STATUS: a=%d b=%d c=%d d=%d abc=[%d,%d](fe%d) acd=[%d,%d](fe%d) bcd=[%d,%d](fe%d)\n", a, b, c, d, abc.idx, abc.cid, a+b+c-3, acd.idx, acd.cid, a+c+d-3, bcd.idx, bcd.cid, b+c+d-3);
00592
00593
00594 if (acd.cid != -1) {
00595 result = mesh[acd.cid].lockChunk(myRef.cid, length);
00596 while (result->anInt != 1) {
00597 if (result->anInt == 0) {
00598 C->unlockLocalChunk(myRef.cid);
00599 CkFreeMsg(result);
00600 return;
00601 }
00602 else if (result->anInt == -1) {
00603 CkFreeMsg(result);
00604 CthYield();
00605 result = mesh[acd.cid].lockChunk(myRef.cid, length);
00606 }
00607 }
00608 CkFreeMsg(result);
00609 }
00610
00611 if (bcd.cid != -1) {
00612 result = mesh[bcd.cid].lockChunk(myRef.cid, length);
00613 while (result->anInt != 1) {
00614 if (result->anInt == 0) {
00615 C->unlockLocalChunk(myRef.cid);
00616 if (acd.cid != -1) mesh[acd.cid].unlockChunk(myRef.cid);
00617 CkFreeMsg(result);
00618 return;
00619 }
00620 else if (result->anInt == -1) {
00621 CkFreeMsg(result);
00622 CthYield();
00623 result = mesh[bcd.cid].lockChunk(myRef.cid, length);
00624 }
00625 }
00626 CkFreeMsg(result);
00627 }
00628
00629 n1 = C->theNodes[nodes[a].idx];
00630 n2 = C->theNodes[nodes[b].idx];
00631 n3 = C->theNodes[nodes[c].idx];
00632 n4 = C->theNodes[nodes[d].idx];
00633 if (abc.cid != -1) {
00634 CkPrintf(" -> Refine: %d on %d: Locking %d on %d.\n", myRef.idx,
00635 myRef.cid, abc.idx, abc.cid);
00636 result = mesh[abc.cid].lockLF(abc.idx, n1, n2, n3, n4, myRef, length);
00637 if (result->anInt == 0) {
00638
00639
00640 CkFreeMsg(result);
00641 C->unlockLocalChunk(myRef.cid);
00642 if (acd.cid != -1) mesh[acd.cid].unlockChunk(myRef.cid);
00643 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
00644 return;
00645 }
00646
00647
00648 CkFreeMsg(result);
00649 }
00650
00651
00652
00653
00654 if (abc.cid == -1) {
00655
00656
00657
00658
00659 centerpoint.set((n1.getCoord(0)+n2.getCoord(0)+n3.getCoord(0))/3.0,
00660 (n1.getCoord(1)+n2.getCoord(1)+n3.getCoord(1))/3.0,
00661 (n1.getCoord(2)+n2.getCoord(2)+n3.getCoord(2))/3.0);
00662 centerpoint.setSurface();
00663 centerpoint.notFixed();
00664 nodeRef newNode = C->addNode(centerpoint);
00665
00666 elemRef newElem1 = C->addElement(nodes[a],newNode,nodes[c],nodes[d]);
00667 elemRef newElem2 = C->addElement(newNode,nodes[b],nodes[c],nodes[d]);
00668
00669
00670 if (acd.cid != -1)
00671 mesh[acd.cid].updateFace(acd.idx, myRef, newElem1);
00672 if (bcd.cid != -1)
00673 mesh[bcd.cid].updateFace(bcd.idx, myRef, newElem2);
00674
00675 C->theElements[newElem1.idx].faceElements[0] = abc;
00676 C->theElements[newElem1.idx].faceElements[1] = myRef;
00677 C->theElements[newElem1.idx].faceElements[2] = acd;
00678 C->theElements[newElem1.idx].faceElements[3] = newElem2;
00679 C->theElements[newElem2.idx].faceElements[0] = abc;
00680 C->theElements[newElem2.idx].faceElements[1] = myRef;
00681 C->theElements[newElem2.idx].faceElements[2] = newElem1;
00682 C->theElements[newElem2.idx].faceElements[3] = bcd;
00683
00684 faceElements[a+c+d-3] = newElem1;
00685 faceElements[b+c+d-3] = newElem2;
00686
00687 C->theElements[newElem1.idx].setTargetVolume(targetVolume);
00688 C->theElements[newElem2.idx].setTargetVolume(targetVolume);
00689
00690 C->updateFace(nodes[a].idx, nodes[b].idx, nodes[c].idx,
00691 nodes[c].idx, newNode.idx);
00692 C->addFace(nodes[b].idx, newNode.idx, nodes[c].idx);
00693 C->addFace(nodes[a].idx, newNode.idx, nodes[c].idx);
00694
00695 nodes[c] = newNode;
00696 calculateVolume();
00697
00698
00699 }
00700 else {
00701
00702
00703
00704 splitResponse *theResult =
00705 mesh[abc.cid].splitLF(abc.idx, n1, n2, n3, n4, myRef);
00706
00707 if (theResult->success == 1) {
00708
00709 node newNode(theResult->newNode[0], theResult->newNode[1],
00710 theResult->newNode[2]);
00711 newNode.notFixed();
00712 newNode.notSurface();
00713 nodeRef newRef = C->addNode(newNode);
00714
00715 elemRef newElem3 = C->addElement(nodes[a],newRef,nodes[c],nodes[d]);
00716 elemRef newElem4 = C->addElement(newRef,nodes[b],nodes[c],nodes[d]);
00717
00718
00719 if (acd.cid != -1) mesh[acd.cid].updateFace(acd.idx, myRef, newElem3);
00720 if (bcd.cid != -1) mesh[bcd.cid].updateFace(bcd.idx, myRef, newElem4);
00721
00722 nodes[c] = newRef;
00723
00724 C->theElements[newElem3.idx].faceElements[0].cid = abc.cid;
00725 C->theElements[newElem3.idx].faceElements[0].idx = theResult->ance;
00726 C->theElements[newElem3.idx].faceElements[1] = myRef;
00727 C->theElements[newElem3.idx].faceElements[2] = acd;
00728 C->theElements[newElem3.idx].faceElements[3] = newElem4;
00729 C->theElements[newElem4.idx].faceElements[0].cid = abc.cid;
00730 C->theElements[newElem4.idx].faceElements[0].idx = theResult->bnce;
00731 C->theElements[newElem4.idx].faceElements[1] = myRef;
00732 C->theElements[newElem4.idx].faceElements[2] = newElem3;
00733 C->theElements[newElem4.idx].faceElements[3] = bcd;
00734
00735 faceElements[a+c+d-3] = newElem3;
00736 faceElements[b+c+d-3] = newElem4;
00737
00738 C->theElements[newElem3.idx].setTargetVolume(targetVolume);
00739 C->theElements[newElem4.idx].setTargetVolume(targetVolume);
00740 calculateVolume();
00741
00742
00743
00744 if (abc.cid != -1) {
00745 mesh[abc.cid].updateFace(theResult->ance, newElem3.cid, newElem3.idx);
00746 mesh[abc.cid].updateFace(theResult->bnce, newElem4.cid, newElem4.idx);
00747
00748
00749
00750
00751
00752
00753 }
00754 }
00755 else if (theResult->success == 0) {
00756
00757
00758 mesh[myRef.cid].refineElement(myRef.idx, currentVolume);
00759 }
00760 else CkPrintf("Refine: %d on %d: WHAT THE FRELL?\n", myRef.idx, myRef.cid);
00761 }
00762 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
00763 if (acd.cid != -1) mesh[acd.cid].unlockChunk(myRef.cid);
00764 if (abc.cid != -1) mesh[abc.cid].unlockChunk(myRef.cid);
00765 C->unlockLocalChunk(myRef.cid);
00766
00767 }
00768
00769 int element::lockLF(node n1, node n2, node n3, node n4, elemRef requester,
00770 double prio)
00771 {
00772 int a=-1, b=-1, c=-1, d=-1;
00773 elemRef abc, acd, bcd;
00774
00775 intMsg *result;
00776 int iResult = C->lockLocalChunk(requester.cid, prio);
00777 while (iResult != 1) {
00778 if (iResult == 0) return 0;
00779 else if (iResult == -1) CthYield();
00780 iResult = C->lockLocalChunk(requester.cid, prio);
00781 }
00782
00783 int found = 0;
00784 for (int i=0; i<4; i++)
00785 if (faceElements[i] == requester)
00786 found = 1;
00787 CmiAssert(found);
00788 a = getNode(n1);
00789 b = getNode(n2);
00790 c = getNode(n3);
00791 CmiAssert((a != -1) && (b != -1) && (c != -1));
00792
00793 d = 6-a-b-c;
00794 abc = faceElements[a+b+c-3];
00795 CmiAssert(abc == requester);
00796 acd = faceElements[a+c+d-3];
00797 bcd = faceElements[b+c+d-3];
00798
00799 if (acd.cid != -1) {
00800 result = mesh[acd.cid].lockChunk(requester.cid, prio);
00801 while (result->anInt != 1) {
00802 if (result->anInt == 0) {
00803 C->unlockLocalChunk(requester.cid);
00804 CkFreeMsg(result);
00805 return 0;
00806 }
00807 else if (result->anInt == -1) {
00808 CthYield();
00809 CkFreeMsg(result);
00810 result = mesh[acd.cid].lockChunk(requester.cid, prio);
00811 }
00812 }
00813 CkFreeMsg(result);
00814 }
00815 if (bcd.cid != -1) {
00816 result = mesh[bcd.cid].lockChunk(requester.cid, prio);
00817 while (result->anInt != 1) {
00818 if (result->anInt == 0) {
00819 C->unlockLocalChunk(requester.cid);
00820 if (acd.cid != -1) mesh[acd.cid].unlockChunk(requester.cid);
00821 CkFreeMsg(result);
00822 return 0;
00823 }
00824 else if (result->anInt == -1) {
00825 CthYield();
00826 CkFreeMsg(result);
00827 result = mesh[bcd.cid].lockChunk(requester.cid, prio);
00828 }
00829 }
00830 CkFreeMsg(result);
00831 }
00832 return 1;
00833 }
00834
00835 splitResponse *element::splitLF(node in1, node in2, node in3, node in4, elemRef requester)
00836 {
00837
00838 splitResponse *theResult = new splitResponse;
00839 int a=-1, b=-1, c=-1, d=-1;
00840 node centerpoint;
00841 elemRef abc, acd, bcd;
00842
00843
00844
00845 theResult->success = 1;
00846 int found = 0;
00847
00848 for (int i=0; i<4; i++)
00849 if (faceElements[i] == requester)
00850 found = 1;
00851 CmiAssert(found);
00852 a = getNode(in1);
00853 b = getNode(in2);
00854 c = getNode(in3);
00855 CmiAssert((a != -1) && (b != -1) && (c != -1));
00856 d = 6-a-b-c;
00857 abc = faceElements[a+b+c-3];
00858 CmiAssert(abc == requester);
00859 acd = faceElements[a+c+d-3];
00860 bcd = faceElements[b+c+d-3];
00861
00862 centerpoint.set((C->theNodes[nodes[a].idx].getCoord(0) +
00863 C->theNodes[nodes[b].idx].getCoord(0) +
00864 C->theNodes[nodes[c].idx].getCoord(0)) / 3.0,
00865 (C->theNodes[nodes[a].idx].getCoord(1) +
00866 C->theNodes[nodes[b].idx].getCoord(1) +
00867 C->theNodes[nodes[c].idx].getCoord(1)) / 3.0,
00868 (C->theNodes[nodes[a].idx].getCoord(2) +
00869 C->theNodes[nodes[b].idx].getCoord(2) +
00870 C->theNodes[nodes[c].idx].getCoord(2)) / 3.0);
00871 centerpoint.notSurface();
00872 centerpoint.notFixed();
00873 nodeRef newRef = C->addNode(centerpoint);
00874
00875 elemRef newElem1 = C->addElement(nodes[a], newRef, nodes[c], nodes[d]);
00876 elemRef newElem2 = C->addElement(newRef, nodes[b], nodes[c], nodes[d]);
00877
00878
00879 if (acd.cid != -1) mesh[acd.cid].updateFace(acd.idx, myRef, newElem1);
00880 if (bcd.cid != -1) mesh[bcd.cid].updateFace(bcd.idx, myRef, newElem2);
00881
00882 nodes[c] = newRef;
00883
00884 C->theElements[newElem1.idx].faceElements[1] = myRef;
00885 C->theElements[newElem1.idx].faceElements[2] = acd;
00886 C->theElements[newElem1.idx].faceElements[3] = newElem2;
00887 C->theElements[newElem2.idx].faceElements[1] = myRef;
00888 C->theElements[newElem2.idx].faceElements[2] = newElem1;
00889 C->theElements[newElem2.idx].faceElements[3] = bcd;
00890
00891 faceElements[a+c+d-3] = newElem1;
00892 faceElements[b+c+d-3] = newElem2;
00893
00894 C->theElements[newElem1.idx].setTargetVolume(targetVolume);
00895 C->theElements[newElem2.idx].setTargetVolume(targetVolume);
00896 calculateVolume();
00897
00898 theResult->ance = newElem1.idx;
00899 theResult->bnce = newElem2.idx;
00900 theResult->newNode[0] = centerpoint.getCoord(0);
00901 theResult->newNode[1] = centerpoint.getCoord(1);
00902 theResult->newNode[2] = centerpoint.getCoord(2);
00903
00904 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(requester.cid);
00905 if (acd.cid != -1) mesh[acd.cid].unlockChunk(requester.cid);
00906
00907
00908 return theResult;
00909 }
00910
00911
00912 void element::refineLE()
00913 {
00914 int a, b, c, d, iResult;
00915 elemRef abc, abd, bcd;
00916 nodeRef oldNode;
00917 intMsg *result;
00918 double length;
00919 int arc1=0, arc2=0;
00920
00921
00922
00923
00924 length = findLongestEdge(&a, &b, &c, &d);
00925 iResult = C->lockLocalChunk(myRef.cid, length);
00926 while (iResult != 1) {
00927 if (iResult == 0) return;
00928 else if (iResult == -1) CthYield();
00929 length = findLongestEdge(&a, &b, &c, &d);
00930 iResult = C->lockLocalChunk(myRef.cid, length);
00931 }
00932
00933
00934 abc = getFace(a, b, c); CmiAssert(abc == faceElements[a+b+c-3]);
00935 abd = getFace(a, b, d); CmiAssert(abd == faceElements[a+b+d-3]);
00936 bcd = getFace(b, c, d); CmiAssert(bcd == faceElements[b+c+d-3]);
00937
00938
00939
00940 if (bcd.cid != -1) {
00941 result = mesh[bcd.cid].lockChunk(myRef.cid, length);
00942 while (result->anInt != 1) {
00943 if (result->anInt == 0) {
00944 C->unlockLocalChunk(myRef.cid);
00945 return;
00946 }
00947 else if (result->anInt == -1) {
00948 CthYield();
00949 bcd = getFace(b, c, d);
00950 result = mesh[bcd.cid].lockChunk(myRef.cid, length);
00951 }
00952 }
00953 CkFreeMsg(result);
00954 }
00955 if (abc.cid != -1) {
00956 arc1 = 1;
00957
00958 result = mesh[abc.cid].lockChunk(myRef.cid, length);
00959 while (result->anInt != 1) {
00960
00961 if (result->anInt == 0) {
00962
00963 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
00964 C->unlockLocalChunk(myRef.cid);
00965 return;
00966 }
00967 else if (result->anInt == -1) {
00968 CthYield();
00969 abc = getFace(a, b, c);
00970
00971 result = mesh[abc.cid].lockChunk(myRef.cid, length);
00972 }
00973 }
00974
00975 CkFreeMsg(result);
00976
00977 lockArcMsg *lm1 = new lockArcMsg;
00978 lm1->idx = abc.idx;
00979 lm1->prioRef = lm1->parentRef = myRef;
00980 lm1->destRef = abd;
00981 lm1->prio = length;
00982 lm1->a = C->theNodes[nodes[a].idx];
00983 lm1->b = C->theNodes[nodes[b].idx];
00984 lockResult *lr1 = mesh[abc.cid].lockArc(lm1);
00985 if (lr1->result == 1) {}
00986 else if ((lr1->result == -1) && (abd.cid != -1)) {
00987 arc2 = 1;
00988
00989 result = mesh[abd.cid].lockChunk(myRef.cid, length);
00990 while (result->anInt != 1) {
00991 if (result->anInt == 0) {
00992 mesh[abc.cid].unlockArc1(abc.idx, myRef.cid, myRef, abd,
00993 C->theNodes[nodes[a].idx],
00994 C->theNodes[nodes[b].idx]);
00995 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
00996 C->unlockLocalChunk(myRef.cid);
00997 return;
00998 }
00999 else if (result->anInt == -1) {
01000 CthYield();
01001 abd = getFace(a, b, d);
01002 result = mesh[abd.cid].lockChunk(myRef.cid, length);
01003 }
01004 }
01005
01006 CkFreeMsg(result);
01007
01008 lockArcMsg *lm2 = new lockArcMsg;
01009 lm2->idx = abd.idx;
01010 lm2->prioRef = lm2->parentRef = myRef;
01011 lm2->destRef = abc;
01012 lm2->prio = length;
01013 lm2->a = C->theNodes[nodes[a].idx];
01014 lm2->b = C->theNodes[nodes[b].idx];
01015 lockResult *lr2 = mesh[abd.cid].lockArc(lm2);
01016 if (lr2->result == 0) {
01017 mesh[abc.cid].unlockArc1(abc.idx, myRef.cid, myRef, abd,
01018 C->theNodes[nodes[a].idx],
01019 C->theNodes[nodes[b].idx]);
01020 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
01021 C->unlockLocalChunk(myRef.cid);
01022 return;
01023 }
01024 }
01025 else if (lr1->result == 0) {
01026 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
01027 C->unlockLocalChunk(myRef.cid);
01028 return;
01029 }
01030 }
01031 else if (abd.cid != -1) {
01032 arc2 = 1;
01033 result = mesh[abd.cid].lockChunk(myRef.cid, length);
01034 while (result->anInt != 1) {
01035 if (result->anInt == 0) {
01036 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
01037 C->unlockLocalChunk(myRef.cid);
01038 return;
01039 }
01040 else if (result->anInt == -1) {
01041 CthYield();
01042 abd = getFace(a, b, d);
01043 result = mesh[abd.cid].lockChunk(myRef.cid, length);
01044 }
01045 }
01046 CkFreeMsg(result);
01047
01048 lockArcMsg *lm3 = new lockArcMsg;
01049 lm3->idx = abd.idx;
01050 lm3->prioRef = lm3->parentRef = myRef;
01051 lm3->destRef = abc;
01052 lm3->prio = length;
01053 lm3->a = C->theNodes[nodes[a].idx];
01054 lm3->b = C->theNodes[nodes[b].idx];
01055 lockResult *lr3 = mesh[abd.cid].lockArc(lm3);
01056 if (lr3->result == 0) {
01057 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(myRef.cid);
01058 C->unlockLocalChunk(myRef.cid);
01059 return;
01060 }
01061 }
01062
01063
01064
01065
01066
01067 node mid = C->theNodes[nodes[a].idx].midpoint(C->theNodes[nodes[b].idx]);
01068 if (C->edgeOnSurface(nodes[a].idx, nodes[b].idx))
01069 mid.setSurface();
01070 else mid.notSurface();
01071 if (C->theNodes[nodes[a].idx].isFixed() &&
01072 C->theNodes[nodes[b].idx].isFixed())
01073 mid.fix();
01074 else mid.notFixed();
01075 nodeRef newNode = C->addNode(mid);
01076
01077
01078
01079 elemRef newElem = C->addElement(newNode, nodes[b], nodes[c], nodes[d]);
01080
01081 C->theElements[newElem.idx].faceElements[0] = faceElements[a+b+c-3];
01082 C->theElements[newElem.idx].faceElements[1] = faceElements[a+b+d-3];
01083 C->theElements[newElem.idx].faceElements[2] = myRef;
01084 C->theElements[newElem.idx].faceElements[3] = faceElements[b+c+d-3];
01085 C->theElements[newElem.idx].calculateVolume();
01086 C->theElements[newElem.idx].setTargetVolume(targetVolume);
01087 if (faceElements[b+c+d-3].cid != -1)
01088 mesh[faceElements[b+c+d-3].cid].updateFace(faceElements[b+c+d-3].idx,
01089 myRef, newElem);
01090 faceElements[b+c+d-3] = newElem;
01091 oldNode = nodes[b];
01092 nodes[b] = newNode;
01093 calculateVolume();
01094
01095
01096
01097 if (abc.cid != -1) {
01098 LEsplitMsg *lsm1 = new LEsplitMsg;
01099 lsm1->idx = abc.idx;
01100 lsm1->root = myRef;
01101 lsm1->parent = myRef;
01102 lsm1->newNodeRef = newNode;
01103 lsm1->newNode = C->theNodes[newNode.idx];
01104 lsm1->newRootElem = newElem;
01105 lsm1->newElem = newElem;
01106 lsm1->targetElem = abd;
01107 lsm1->targetVol = targetVolume;
01108 lsm1->a = C->theNodes[nodes[a].idx];
01109 lsm1->b = C->theNodes[oldNode.idx];
01110 LEsplitResult *lsr1 = mesh[abc.cid].LEsplit(lsm1);
01111 C->theElements[newElem.idx].faceElements[0] = lsr1->newElem1;
01112 if (lsr1->status == 0) {
01113 if (abd.cid != -1) {
01114 LEsplitMsg *lsm2 = new LEsplitMsg;
01115 lsm2->idx = abd.idx;
01116 lsm2->root = myRef;
01117 lsm2->parent = myRef;
01118 lsm2->newNodeRef = newNode;
01119 lsm2->newNode = C->theNodes[newNode.idx];
01120 lsm2->newRootElem = newElem;
01121 lsm2->newElem = newElem;
01122 lsm2->targetElem = abc;
01123 lsm2->targetVol = targetVolume;
01124 lsm2->a = C->theNodes[nodes[a].idx];
01125 lsm2->b = C->theNodes[oldNode.idx];
01126 LEsplitResult *lsr2 = mesh[abd.cid].LEsplit(lsm2);
01127 C->theElements[newElem.idx].faceElements[1] = lsr2->newElem1;
01128 }
01129 }
01130 else {
01131 CmiAssert(lsr1->status == 1);
01132 C->theElements[newElem.idx].faceElements[1] = lsr1->newElem2;
01133 }
01134 }
01135 else if (abd.cid != -1) {
01136 LEsplitMsg *lsm3 = new LEsplitMsg;
01137 lsm3->idx = abd.idx;
01138 lsm3->root = myRef;
01139 lsm3->parent = myRef;
01140 lsm3->newNodeRef = newNode;
01141 lsm3->newNode = C->theNodes[newNode.idx];
01142 lsm3->newRootElem = newElem;
01143 lsm3->newElem = newElem;
01144 lsm3->targetElem = abc;
01145 lsm3->targetVol = targetVolume;
01146 lsm3->a = C->theNodes[nodes[a].idx];
01147 lsm3->b = C->theNodes[oldNode.idx];
01148 LEsplitResult *lsr3 = mesh[abd.cid].LEsplit(lsm3);
01149 CmiAssert(lsr3->status == 0);
01150 C->theElements[newElem.idx].faceElements[1] = lsr3->newElem1;
01151 }
01152
01153
01154 if ((arc1 == 1) && (abc.cid != -1))
01155 mesh[abc.cid].unlockArc2(abc.idx, myRef.cid, myRef, abd,
01156 C->theNodes[nodes[a].idx],
01157 C->theNodes[nodes[b].idx]);
01158
01159
01160 if ((arc2 == 1) && (abd.cid != -1))
01161 mesh[abd.cid].unlockArc2(abd.idx, myRef.cid, myRef, abc,
01162 C->theNodes[nodes[a].idx],
01163 C->theNodes[nodes[b].idx]);
01164
01165
01166 if (bcd.cid != -1)
01167 mesh[bcd.cid].unlockChunk(myRef.cid);
01168
01169
01170 C->unlockLocalChunk(myRef.cid);
01171 }
01172
01173 LEsplitResult *element::LEsplit(elemRef root, elemRef parent,
01174 nodeRef newNodeRef, node newNode,
01175 elemRef newRootElem, elemRef newElem,
01176 elemRef targetElem, double targetVol,
01177 node aIn, node bIn)
01178 {
01179 int a=-1, b=-1, c=-1, d=-1;
01180 elemRef abc, abd;
01181 nodeRef oldNode;
01182
01183 calculateVolume();
01184
01185
01186
01187
01188
01189 for (int i=0; i<4; i++) {
01190 if (C->theNodes[nodes[i].idx] == aIn)
01191 a = i;
01192 else if (C->theNodes[nodes[i].idx] == bIn)
01193 b = i;
01194 else if (c == -1)
01195 c = i;
01196 else
01197 d = i;
01198 }
01199
01200 CmiAssert((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!=-1));
01201
01202 abc = getFace(a, b, c);
01203 if (!(abc == parent)) {
01204 int tmp = c;
01205 c = d;
01206 d = tmp;
01207 abd = abc;
01208 abc = getFace(a, b, c);
01209 }
01210 else abd = getFace(a, b, d);
01211 CmiAssert(abc == parent);
01212
01213
01214
01215
01216 if (newNodeRef.cid != myRef.cid)
01217 newNodeRef = C->addNode(newNode);
01218
01219
01220 elemRef myNewElem = C->addElement(newNodeRef, nodes[b], nodes[c], nodes[d]);
01221
01222 C->theElements[myNewElem.idx].faceElements[0] = newElem;
01223 C->theElements[myNewElem.idx].faceElements[1] = faceElements[a+b+d-3];
01224 C->theElements[myNewElem.idx].faceElements[2] = myRef;
01225 C->theElements[myNewElem.idx].faceElements[3] = faceElements[b+c+d-3];
01226 C->theElements[myNewElem.idx].calculateVolume();
01227 C->theElements[myNewElem.idx].setTargetVolume(targetVolume);
01228 if (faceElements[b+c+d-3].cid != -1)
01229 mesh[faceElements[b+c+d-3].cid].updateFace(faceElements[b+c+d-3].idx,
01230 myRef, myNewElem);
01231 faceElements[b+c+d-3] = myNewElem;
01232 oldNode = nodes[b];
01233 nodes[b] = newNodeRef;
01234 calculateVolume();
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246 LEsplitResult *result = new LEsplitResult;
01247 if (myRef == targetElem) {
01248 result->status = 1;
01249 C->theElements[myNewElem.idx].faceElements[1] = newRootElem;
01250 result->newElem1 = myNewElem;
01251 result->newElem2 = myNewElem;
01252 }
01253 else if (abd.cid != -1) {
01254 LEsplitMsg *lsm = new LEsplitMsg;
01255 lsm->idx = abd.idx;
01256 lsm->root = root;
01257 lsm->parent = myRef;
01258 lsm->newNodeRef = newNodeRef;
01259 lsm->newNode = C->theNodes[newNodeRef.idx];
01260 lsm->newRootElem = newRootElem;
01261 lsm->newElem = myNewElem;
01262 lsm->targetElem = targetElem;
01263 lsm->targetVol = targetVol;
01264 lsm->a = aIn;
01265 lsm->b = bIn;
01266 LEsplitResult *lsr = mesh[abd.cid].LEsplit(lsm);
01267 C->theElements[myNewElem.idx].faceElements[1] = lsr->newElem1;
01268 result->newElem1 = myNewElem;
01269 result->newElem2 = lsr->newElem2;
01270 result->status = lsr->status;
01271 }
01272 else {
01273 result->status = 0;
01274 result->newElem1 = myNewElem;
01275 result->newElem2.cid = -1; result->newElem2.idx = -1;
01276 }
01277
01278
01279
01280 return result;
01281 }
01282
01283 lockResult *element::lockArc(elemRef prioRef, elemRef parentRef, double prio,
01284 elemRef destRef, node aNode, node bNode)
01285 {
01286 lockResult *myResult = new lockResult;
01287 elemRef abc, bcd;
01288 int a=-1, b=-1, c=-1, d=-1;
01289
01290
01291
01292
01293
01294 for (int i=0; i<4; i++) {
01295 if (C->theNodes[nodes[i].idx] == aNode) a = i;
01296 else if (C->theNodes[nodes[i].idx] == bNode) b = i;
01297 else if (c == -1) c = i;
01298 else d = i;
01299 }
01300 int ap, bp, cp, dp;
01301 double length = findLongestEdge(&ap, &bp, &cp, &dp);
01302 if (!(((ap == a) && (bp == b)) || ((ap == b) && (bp == a)) ||
01303 (length == prio))) {
01304 mesh[myRef.cid].refineElement(myRef.idx, getVolume()/2.0);
01305 myResult->result = 0;
01306 CkPrintf("Nbr failed LE test...\n");
01307 C->unlockLocalChunk(prioRef.cid);
01308 return myResult;
01309 }
01310
01311 CmiAssert((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!=-1));
01312
01313
01314
01315 abc = getFace(a, b, c);
01316 if (abc == parentRef) {
01317 int tmp = c;
01318 c = d;
01319 d = tmp;
01320 abc = getFace(a, b, c);
01321 }
01322 CmiAssert(!(abc == parentRef));
01323
01324
01325 bcd = getFace(b, c, d);
01326 if (bcd.cid != -1) {
01327 intMsg *result = mesh[bcd.cid].lockChunk(prioRef.cid, prio);
01328
01329
01330 while (result->anInt != 1) {
01331 if (result->anInt == 0) {
01332 myResult->result = 0;
01333 C->unlockLocalChunk(prioRef.cid);
01334 return myResult;
01335 }
01336 else if (result->anInt == -1) {
01337 CthYield();
01338 bcd = getFace(b, c, d);
01339 result = mesh[bcd.cid].lockChunk(prioRef.cid, prio);
01340 }
01341 }
01342 }
01343
01344
01345
01346 if (myRef == destRef) {
01347
01348
01349 myResult->result = 1;
01350 }
01351 else if (abc.cid != -1) {
01352 intMsg *result = mesh[abc.cid].lockChunk(prioRef.cid, prio);
01353
01354
01355
01356 while (result->anInt != 1) {
01357 if (result->anInt == 0) {
01358 myResult->result = 0;
01359 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(prioRef.cid);
01360 C->unlockLocalChunk(prioRef.cid);
01361 return myResult;
01362 }
01363 else if (result->anInt == -1) {
01364 CthYield();
01365 abc = getFace(a, b, c);
01366 result = mesh[abc.cid].lockChunk(prioRef.cid, prio);
01367 }
01368 }
01369
01370
01371 lockArcMsg *lm1 = new lockArcMsg;
01372 lm1->idx = abc.idx;
01373 lm1->prioRef = prioRef;
01374 lm1->parentRef = myRef;
01375 lm1->destRef = destRef;
01376 lm1->prio = prio;
01377 lm1->a = aNode;
01378 lm1->b = bNode;
01379 lockResult *lr1 = mesh[abc.cid].lockArc(lm1);
01380
01381
01382 if (lr1->result == 1) myResult->result = 1;
01383 else if (lr1->result == -1) myResult->result = -1;
01384 else if (lr1->result == 0) {
01385 if (bcd.cid != -1) mesh[bcd.cid].unlockChunk(prioRef.cid);
01386 C->unlockLocalChunk(prioRef.cid);
01387 myResult->result = 0;
01388 }
01389 }
01390 else {
01391
01392
01393 myResult->result = -1;
01394 }
01395 return myResult;
01396 }
01397
01398 void element::unlockArc1(int prio, elemRef parentRef, elemRef destRef,
01399 node aNode, node bNode)
01400 {
01401 elemRef abc, bcd;
01402 int a=-1, b=-1, c=-1, d=-1;
01403
01404
01405
01406 C->unlockLocalChunk(prio);
01407
01408 for (int i=0; i<4; i++) {
01409 if (C->theNodes[nodes[i].idx] == aNode) a = i;
01410 else if (C->theNodes[nodes[i].idx] == bNode) b = i;
01411 else if (c == -1) c = i;
01412 else d = i;
01413 }
01414 CmiAssert((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!=-1));
01415
01416
01417
01418 abc = getFace(a, b, c);
01419 if (abc == parentRef) {
01420 int tmp = c;
01421 c = d;
01422 d = tmp;
01423 abc = getFace(a, b, c);
01424 }
01425 CmiAssert(!(abc == parentRef));
01426 bcd = getFace(b, c, d);
01427
01428
01429
01430 if (bcd.cid != -1)
01431 mesh[bcd.cid].unlockChunk(prio);
01432
01433
01434 if (myRef == destRef) return;
01435 else if (abc.cid != -1)
01436 mesh[abc.cid].unlockArc1(abc.idx, prio, myRef, destRef, aNode, bNode);
01437
01438
01439 }
01440
01441 void element::unlockArc2(int prio, elemRef parentRef, elemRef destRef,
01442 node aNode, node bNode)
01443 {
01444 elemRef abc, bcd;
01445 int a=-1, b=-1, c=-1, d=-1;
01446
01447
01448
01449 C->unlockLocalChunk(prio);
01450
01451 for (int i=0; i<4; i++) {
01452 if (C->theNodes[nodes[i].idx] == aNode) a = i;
01453 else if (C->theNodes[nodes[i].idx] == bNode) b = i;
01454 else if (c == -1) c = i;
01455 else d = i;
01456 }
01457 CmiAssert((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!=-1));
01458
01459
01460
01461 abc = getFace(a, b, c);
01462 if (abc == parentRef) {
01463 int tmp = c;
01464 c = d;
01465 d = tmp;
01466 abc = getFace(a, b, c);
01467 }
01468 CmiAssert(!(abc == parentRef));
01469
01470
01471 bcd = getFace(b, c, d);
01472
01473 elemRef bcdNbr = C->theElements[bcd.idx].faceElements[3];
01474 if (bcdNbr.cid != -1)
01475 mesh[bcdNbr.cid].unlockChunk(prio);
01476
01477
01478 if (myRef == destRef) return;
01479 else if (abc.cid != -1)
01480 mesh[abc.cid].unlockArc2(abc.idx, prio, myRef, destRef, aNode, bNode);
01481
01482
01483 }
01484
01485 void element::refineCP()
01486 {
01487 int a, b, c, d, iResult;
01488 node n1, n2, n3, n4, centerpoint;
01489 elemRef abcn, ancd, nbcd, abnd;
01490 intMsg *result;
01491 double length;
01492
01493
01494
01495 if ((currentVolume == 0.0) || (targetVolume == 0.0)) {
01496 CkPrintf("WARNING: %d on %d has dwindled; using bailout!\n",
01497 myRef.idx, myRef.cid);
01498 targetVolume = -1.0;
01499 return;
01500 }
01501 if (currentVolume < targetVolume) return;
01502
01503
01504 length = findLongestEdge(&a, &b, &c, &d);
01505 iResult = C->lockLocalChunk(myRef.cid, length);
01506 while (iResult != 1) {
01507 if (iResult == 0) return;
01508 else if (iResult == -1) CthYield();
01509 length = findLongestEdge(&a, &b, &c, &d);
01510 iResult = C->lockLocalChunk(myRef.cid, length);
01511 }
01512 a = 0;
01513 b = 1;
01514 c = 2;
01515 d = 3;
01516 abcn = faceElements[0];
01517 abnd = faceElements[1];
01518 ancd = faceElements[2];
01519 nbcd = faceElements[3];
01520 if (abnd.cid != -1) {
01521 result = mesh[abnd.cid].lockChunk(myRef.cid, length);
01522 while (result->anInt != 1) {
01523 if (result->anInt == 0) {
01524 C->unlockLocalChunk(myRef.cid);
01525 CkFreeMsg(result);
01526 return;
01527 }
01528 else if (result->anInt == -1) {
01529 CthYield();
01530 CkFreeMsg(result);
01531 result = mesh[abnd.cid].lockChunk(myRef.cid, length);
01532 }
01533 }
01534 CkFreeMsg(result);
01535 }
01536 if (ancd.cid != -1) {
01537 result = mesh[ancd.cid].lockChunk(myRef.cid, length);
01538 while (result->anInt != 1) {
01539 if (result->anInt == 0) {
01540 C->unlockLocalChunk(myRef.cid);
01541 if (abnd.cid != -1) mesh[abnd.cid].unlockChunk(myRef.cid);
01542 CkFreeMsg(result);
01543 return;
01544 }
01545 else if (result->anInt == -1) {
01546 CthYield();
01547 CkFreeMsg(result);
01548 result = mesh[ancd.cid].lockChunk(myRef.cid, length);
01549 }
01550 }
01551 CkFreeMsg(result);
01552 }
01553 if (nbcd.cid != -1) {
01554 result = mesh[nbcd.cid].lockChunk(myRef.cid, length);
01555 while (result->anInt != 1) {
01556 if (result->anInt == 0) {
01557 C->unlockLocalChunk(myRef.cid);
01558 if (abnd.cid != -1) mesh[abnd.cid].unlockChunk(myRef.cid);
01559 if (ancd.cid != -1) mesh[ancd.cid].unlockChunk(myRef.cid);
01560 CkFreeMsg(result);
01561 return;
01562 }
01563 else if (result->anInt == -1) {
01564 CthYield();
01565 CkFreeMsg(result);
01566 result = mesh[nbcd.cid].lockChunk(myRef.cid, length);
01567 }
01568 }
01569 CkFreeMsg(result);
01570 }
01571
01572
01573
01574 n1 = C->theNodes[nodes[a].idx];
01575 n2 = C->theNodes[nodes[b].idx];
01576 n3 = C->theNodes[nodes[c].idx];
01577 n4 = C->theNodes[nodes[d].idx];
01578
01579 centerpoint.set(
01580 (n1.getCoord(0)+n2.getCoord(0)+n3.getCoord(0)+n4.getCoord(0))/4.0,
01581 (n1.getCoord(1)+n2.getCoord(1)+n3.getCoord(1)+n4.getCoord(1))/4.0,
01582 (n1.getCoord(2)+n2.getCoord(2)+n3.getCoord(2)+n4.getCoord(2))/4.0);
01583 centerpoint.notSurface();
01584 centerpoint.notFixed();
01585 nodeRef newNode = C->addNode(centerpoint);
01586
01587
01588
01589
01590
01591 elemRef newElem1 = C->addElement(nodes[a],nodes[b],newNode,nodes[d]);
01592 elemRef newElem2 = C->addElement(nodes[a],newNode,nodes[c],nodes[d]);
01593 elemRef newElem3 = C->addElement(newNode,nodes[b],nodes[c],nodes[d]);
01594
01595
01596 if (abnd.cid != -1) mesh[abnd.cid].updateFace(abnd.idx, myRef, newElem1);
01597 if (ancd.cid != -1) mesh[ancd.cid].updateFace(ancd.idx, myRef, newElem2);
01598 if (nbcd.cid != -1) mesh[nbcd.cid].updateFace(nbcd.idx, myRef, newElem3);
01599
01600 C->theElements[newElem1.idx].faceElements[0] = myRef;
01601 C->theElements[newElem1.idx].faceElements[1] = abnd;
01602 C->theElements[newElem1.idx].faceElements[2] = newElem2;
01603 C->theElements[newElem1.idx].faceElements[3] = newElem3;
01604 C->theElements[newElem2.idx].faceElements[0] = myRef;
01605 C->theElements[newElem2.idx].faceElements[1] = newElem1;
01606 C->theElements[newElem2.idx].faceElements[2] = ancd;
01607 C->theElements[newElem2.idx].faceElements[3] = newElem3;
01608 C->theElements[newElem3.idx].faceElements[0] = myRef;
01609 C->theElements[newElem3.idx].faceElements[1] = newElem1;
01610 C->theElements[newElem3.idx].faceElements[2] = newElem2;
01611 C->theElements[newElem3.idx].faceElements[3] = nbcd;
01612
01613 faceElements[a+b+d-3] = newElem1;
01614 faceElements[a+c+d-3] = newElem2;
01615 faceElements[b+c+d-3] = newElem3;
01616
01617 C->theElements[newElem1.idx].setTargetVolume(targetVolume);
01618 C->theElements[newElem2.idx].setTargetVolume(targetVolume);
01619 C->theElements[newElem3.idx].setTargetVolume(targetVolume);
01620
01621 nodes[d] = newNode;
01622 calculateVolume();
01623 if (abnd.cid != -1) mesh[abnd.cid].unlockChunk(myRef.cid);
01624 if (ancd.cid != -1) mesh[ancd.cid].unlockChunk(myRef.cid);
01625 if (nbcd.cid != -1) mesh[nbcd.cid].unlockChunk(myRef.cid);
01626 C->unlockLocalChunk(myRef.cid);
01627
01628 }
01629
01630 void element::coarsen()
01631 {
01632 }
01633
01634
01635 void element::improveElement()
01636 {
01637 for (int i=0; i<4; i++)
01638 if (!C->theNodes[nodes[i].idx].isFixed()) {
01639 if (C->theNodes[nodes[i].idx].onSurface())
01640 improveSurfaceNode(i);
01641 else improveInternalNode(i);
01642 }
01643 }
01644
01645 void element::improveInternalNode(int n)
01646 {
01647 int ot1=(n+1)%4, ot2=(n+2)%4, ot3=(n+3)%4;
01648 node aNode=C->theNodes[nodes[n].idx], n1=C->theNodes[nodes[ot1].idx],
01649 n2=C->theNodes[nodes[ot2].idx], n3=C->theNodes[nodes[ot3].idx];
01650 double l1=aNode.distance(n1), l2=aNode.distance(n2), l3=aNode.distance(n3),
01651 l4=n1.distance(n2), l5=n2.distance(n3), l6=n3.distance(n1);
01652 double r = (l1 + l2 + l3 + l4 + l5 + l6) / 6.0, s1, s2, s3;
01653 s1 = l1 - r; s2 = l2 - r; s3 = l3 - r;
01654 node v1, v2, v3, vote;
01655 if (l1 > r)
01656 v1.set( (r*aNode.getCoord(0) + s1*n1.getCoord(0)) / (r+s1),
01657 (r*aNode.getCoord(1) + s1*n1.getCoord(1)) / (r+s1),
01658 (r*aNode.getCoord(2) + s1*n1.getCoord(2)) / (r+s1) );
01659 else v1 = n1;
01660 if (l2 > r)
01661 v2.set( (r*aNode.getCoord(0) + s2*n2.getCoord(0)) / (r+s2),
01662 (r*aNode.getCoord(1) + s2*n2.getCoord(1)) / (r+s2),
01663 (r*aNode.getCoord(2) + s2*n2.getCoord(2)) / (r+s2) );
01664 else v2 = n2;
01665 if (l3 > r)
01666 v3.set( (r*aNode.getCoord(0) + s3*n3.getCoord(0)) / (r+s3),
01667 (r*aNode.getCoord(1) + s3*n3.getCoord(1)) / (r+s3),
01668 (r*aNode.getCoord(2) + s3*n3.getCoord(2)) / (r+s3) );
01669 else v3 = n3;
01670 vote.set( (v1.getCoord(0) + v2.getCoord(0) + v3.getCoord(0)) / 3.0,
01671 (v1.getCoord(1) + v2.getCoord(1) + v3.getCoord(1)) / 3.0,
01672 (v1.getCoord(2) + v2.getCoord(2) + v3.getCoord(2)) / 3.0 );
01673 nodeVoteMsg *nvm = new nodeVoteMsg;
01674 CkPrintf("Node (%lf,%lf,%lf) has vote to move to (%lf,%lf,%lf)\n",
01675 aNode.getCoord(0), aNode.getCoord(1), aNode.getCoord(2),
01676 vote.getCoord(0), vote.getCoord(1), vote.getCoord(2));
01677 nvm->oldCoord[0] = aNode.getCoord(0);
01678 nvm->oldCoord[1] = aNode.getCoord(1);
01679 nvm->oldCoord[2] = aNode.getCoord(2);
01680 nvm->newCoord[0] = vote.getCoord(0);
01681 nvm->newCoord[1] = vote.getCoord(1);
01682 nvm->newCoord[2] = vote.getCoord(2);
01683 mesh.relocationVote(nvm);
01684 }
01685
01686 void element::improveSurfaceNode(int n)
01687 {
01688 int ot1=(n+1)%4, ot2=(n+2)%4, ot3=(n+3)%4;
01689 if (C->faceOnSurface(nodes[n].idx, nodes[ot1].idx, nodes[ot2].idx))
01690 improveSurfaceNodeHelp(n, ot1, ot2);
01691 else if (C->faceOnSurface(nodes[n].idx, nodes[ot1].idx, nodes[ot3].idx))
01692 improveSurfaceNodeHelp(n, ot1, ot3);
01693 else if (C->faceOnSurface(nodes[n].idx, nodes[ot2].idx, nodes[ot3].idx))
01694 improveSurfaceNodeHelp(n, ot2, ot3);
01695 }
01696
01697 void element::improveSurfaceNodeHelp(int n, int ot1, int ot2)
01698 {
01699 node aNode=C->theNodes[nodes[n].idx], n1=C->theNodes[nodes[ot1].idx],
01700 n2=C->theNodes[nodes[ot2].idx];
01701 double l1=aNode.distance(n1), l2=aNode.distance(n2), l3=n1.distance(n2);
01702 double r = (l1 + l2 + l3) / 3.0, s1, s2;
01703 s1 = l1 - r; s2 = l2 - r;
01704 node v1, v2, vote;
01705 if (l1 > r)
01706 v1.set( (r*aNode.getCoord(0) + s1*n1.getCoord(0)) / (r+s1),
01707 (r*aNode.getCoord(1) + s1*n1.getCoord(1)) / (r+s1),
01708 (r*aNode.getCoord(2) + s1*n1.getCoord(2)) / (r+s1) );
01709 else v1 = n1;
01710 if (l2 > r)
01711 v2.set( (r*aNode.getCoord(0) + s2*n2.getCoord(0)) / (r+s2),
01712 (r*aNode.getCoord(1) + s2*n2.getCoord(1)) / (r+s2),
01713 (r*aNode.getCoord(2) + s2*n2.getCoord(2)) / (r+s2) );
01714 else v2 = n2;
01715 vote.set( (v1.getCoord(0) + v2.getCoord(0)) / 2.0,
01716 (v1.getCoord(1) + v2.getCoord(1)) / 2.0,
01717 (v1.getCoord(2) + v2.getCoord(2)) / 2.0 );
01718 nodeVoteMsg *nvm = new nodeVoteMsg;
01719 nvm->oldCoord[0] = aNode.getCoord(0);
01720 nvm->oldCoord[1] = aNode.getCoord(1);
01721 nvm->oldCoord[2] = aNode.getCoord(2);
01722 nvm->newCoord[0] = vote.getCoord(0);
01723 nvm->newCoord[1] = vote.getCoord(1);
01724 nvm->newCoord[2] = vote.getCoord(2);
01725 mesh.relocationVote(nvm);
01726 }
01727
01728 int element::LEtest()
01729 {
01730 double ml = 0.0, ml2 = 0.0, ml3 = 0.0, l[4][4];
01731 for (int i=0; i<4; i++)
01732 for (int j=i+1; j<4; j++) {
01733 l[i][j] = C->theNodes[nodes[i].idx].distance(C->theNodes[nodes[j].idx]);
01734 if (l[i][j] > ml) {
01735 ml3 = ml2;
01736 ml2 = ml;
01737 ml = l[i][j];
01738 }
01739 }
01740 if (ml3 + (0.33*ml3) <= ml) return 1;
01741 return 0;
01742 }
01743
01744 int element::LFtest()
01745 {
01746 double lf=0.0, lf2=0.0, f[4];
01747 f[0] = getArea(0,1,2);
01748 f[1] = getArea(0,1,3);
01749 f[2] = getArea(0,2,3);
01750 f[3] = getArea(1,2,3);
01751 for (int i=0; i<4; i++) if (f[i] > lf) { lf2 = lf; lf = f[i]; }
01752 if (lf2 + (0.25*lf2) <= lf) return 1;
01753 return 0;
01754 }
01755
01756 int element::CPtest()
01757 {
01758 double avg = 0.0, l[4][4];
01759 for (int i=0; i<4; i++)
01760 for (int j=i+1; j<4; j++) {
01761 l[i][j] = C->theNodes[nodes[i].idx].distance(C->theNodes[nodes[j].idx]);
01762 avg += l[i][j];
01763 }
01764 avg = avg / 6.0;
01765 for (int i=0; i<4; i++)
01766 for (int j=i+1; j<4; j++) {
01767 if ((l[i][j] > avg) && (l[i][j] - l[i][j]*0.25 > avg))
01768 return 0;
01769 else if ((l[i][j] < avg) && (l[i][j] + l[i][j]*0.25 < avg))
01770 return 0;
01771 }
01772 return 1;
01773 }