00001 
00002 
00003 
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include "tri.h"
00007 
00008 
00009 CProxy_chunk mesh;
00010 CtvDeclare(chunk *, _refineChunk);
00011 
00012 void refineChunkInit(void) {
00013   CtvInitialize(chunk *, _refineChunk);
00014 }
00015 
00016 static elemRef nullRef(-1,-1);
00017 
00018 
00019 void edgeRef::updateElement(chunk *C, elemRef oldval, elemRef newval)
00020 {
00021   if (cid == C->cid) 
00022     C->theEdges[idx].updateElement(oldval, newval);
00023   else 
00024     mesh[cid].updateElement(idx, oldval, newval);
00025 }
00026 
00027 int edgeRef::lock(chunk *C)
00028 {
00029   
00030   if (cid == C->cid) { 
00031     if (C->theEdges[idx].locked())
00032       return 0;
00033     else { 
00034       C->theEdges[idx].lock();
00035       return 1;
00036     }
00037   }
00038   else { 
00039     intMsg *im2;
00040     int result;
00041     im2 = mesh[cid].lock(idx);
00042     result = im2->anInt;
00043     CkFreeMsg(im2);
00044     return result;
00045   }
00046 }
00047 
00048 void edgeRef::unlock(chunk *C)
00049 {
00050   if (cid == C->cid) 
00051     C->theEdges[idx].unlock();
00052   else 
00053     mesh[cid].unlock(idx);
00054 }
00055 
00056 int edgeRef::locked(chunk *C) const
00057 {
00058   if (cid == C->cid) 
00059     return C->theEdges[idx].locked();
00060   else { 
00061     intMsg *im2;
00062     int result;
00063     im2 = mesh[cid].locked(idx);
00064     result = im2->anInt;
00065     CkFreeMsg(im2);
00066     return result;
00067   }
00068 }
00069 
00070 
00071 double elemRef::getArea(chunk *C)
00072 {
00073   if (cid == C->cid) 
00074     return C->theElements[idx].getArea();
00075   else { 
00076     doubleMsg *dm;
00077     double result;
00078     dm = mesh[cid].getArea(idx);
00079     result = dm->aDouble;
00080     CkFreeMsg(dm);
00081     return result;
00082   }
00083 }
00084 
00085 int elemRef::checkIfLongEdge(chunk *C, edgeRef e)
00086 {
00087   if (cid == C->cid) 
00088     return C->theElements[idx].checkIfLongEdge(e);
00089   else { 
00090     intMsg *im;
00091     int result;
00092     im = mesh[cid].checkElement(e, idx);
00093     result = im->anInt;
00094     CkFreeMsg(im);
00095     return result;
00096   }
00097 }
00098 
00099 void elemRef::updateEdges(chunk *C, edgeRef e0, edgeRef e1, 
00100               edgeRef e2)
00101 {
00102   if (cid == C->cid) 
00103     C->theElements[idx].updateEdges(e0, e1, e2);
00104   else 
00105     mesh[cid].updateEdges(idx, e0, e1, e2);
00106 }
00107 
00108 void elemRef::setDependent(chunk *C, int anIdx, int aCid)
00109 {
00110   if (cid == C->cid) { 
00111     C->theElements[idx].setDependent(aCid, anIdx);
00112     C->setModified(); 
00113     if (!C->isRefining()) { 
00114       C->setRefining();
00115       mesh[cid].refiningElements(); 
00116     }
00117   }
00118   else 
00119     mesh[cid].setDependent(objRef(aCid, anIdx), idx);
00120 }
00121 
00122 void elemRef::unsetDependency(chunk *C)
00123 {
00124   if (cid == C->cid) { 
00125     C->theElements[idx].unsetDependency();
00126     C->setModified(); 
00127     if (!C->isRefining()) { 
00128       C->setRefining();
00129       mesh[cid].refiningElements(); 
00130     }
00131   }
00132   else 
00133     mesh[cid].unsetDependency(idx);
00134 }
00135 
00136 int elemRef::hasDependent(chunk *C)
00137 {
00138   if (cid == C->cid) 
00139     return (C->theElements[idx].hasDependent());
00140   else { 
00141     intMsg *im2;
00142     int result;
00143     im2 = mesh[cid].hasDependent(idx);
00144     result = im2->anInt;
00145     CkFreeMsg(im2);
00146     return result;
00147   }
00148 }
00149 
00150 void elemRef::setTargetArea(chunk *C, double ta)
00151 {
00152   if (cid == C->cid) 
00153     C->theElements[idx].setTargetArea(ta);
00154   else 
00155     mesh[cid].setTargetArea(idx, ta);
00156 }
00157 
00158 
00159 void edge::init(int i, chunk *cPtr) 
00160 { 
00161   C = cPtr;  myRef.init(C->cid,i);  theLock = 0;
00162 }
00163 
00164 void edge::init(elemRef *e, int i, chunk *cPtr) 
00165 {
00166   elements[0] = e[0];  elements[1] = e[1];
00167   C = cPtr;  myRef.init(C->cid,i);  theLock = 0;
00168 }
00169 
00170 void edge::updateElement(elemRef oldval, elemRef newval)
00171 { 
00172   if (elements[0] == oldval)
00173     elements[0] = newval;
00174   else if (elements[1] == oldval)
00175     elements[1] = newval;
00176   else 
00177     CkAbort("ERROR: edge::updateElement: no match for oldval\n");
00178 }
00179 
00180 
00181 element::element()
00182 {
00183   targetArea = currentArea = -1.0;
00184   specialRequest = pendingRequest = requestResponse = depend = 0;
00185   unsetDependent();
00186   specialRequester.init();
00187   newNode.init();
00188   otherNode.init();
00189   newLongEdgeRef.init();
00190   C = NULL;
00191 }
00192 
00193 void element::init()
00194 {
00195   targetArea = currentArea = -1.0;
00196   specialRequest = pendingRequest = requestResponse = depend = 0;
00197   unsetDependent();
00198 }
00199 
00200 void element::init(int *n, int index, chunk *chk)
00201 {
00202   for (int i=0; i<3; i++) {
00203     nodes[i] = n[i];
00204     edges[i].init();
00205   }
00206   C = chk;
00207   myRef.init(C->cid, index);
00208   targetArea = currentArea = -1.0;
00209   specialRequest = pendingRequest = requestResponse = depend = 0;
00210   unsetDependent();
00211 }
00212 
00213 void element::init(int *n, edgeRef *e, int index, chunk *chk)
00214 {
00215   for (int i=0; i<3; i++) {
00216     nodes[i] = n[i];
00217     edges[i] = e[i];
00218   }
00219   C = chk;
00220   myRef.init(C->cid, index);
00221   targetArea = currentArea = -1.0;
00222   specialRequest = pendingRequest = requestResponse = depend = 0;
00223   unsetDependent();
00224 }
00225 
00226 double element::getArea()
00227 { 
00228   calculateArea();
00229   return currentArea;
00230 }
00231 
00232 void element::calculateArea()
00233 { 
00234   
00235   
00236 
00237   node n[3];
00238   double s, perimeter, len[3];
00239 
00240   for (int i=0; i<3; i++) 
00241     n[i] = C->theNodes[nodes[i]];
00242   
00243   len[0] = n[0].distance(n[1]);
00244   len[1] = n[1].distance(n[2]);
00245   len[2] = n[2].distance(n[0]);
00246   
00247   
00248   perimeter = len[0] + len[1] + len[2];
00249   s = perimeter / 2.0;
00250   
00251   currentArea = sqrt(s * (s - len[0]) * (s - len[1]) * (s - len[2]));
00252 }
00253 
00254 int element::findLongestEdge()
00255 {
00256   int i, longEdge;
00257   node n[3];
00258   double maxlen = 0.0, len[3];
00259 
00260   for (i=0; i<3; i++) 
00261     n[i] = C->theNodes[nodes[i]];
00262   
00263   len[0] = n[0].distance(n[1]);
00264   len[1] = n[1].distance(n[2]);
00265   len[2] = n[2].distance(n[0]);
00266 
00267   for (i=0; i<3; i++) 
00268     if (len[i] > maxlen) {
00269       longEdge = i;
00270       maxlen = len[i];
00271     }
00272   return longEdge;
00273 }
00274 
00275 elemRef element::getNeighbor(int e) const
00276 {
00277   if (edges[e].cid == myRef.cid) { 
00278     
00279     return C->theEdges[edges[e].idx].getNbrRef(myRef);
00280   }
00281   else { 
00282     refMsg *result = mesh[edges[e].cid].getNeighbor(myRef, edges[e].idx);
00283     elemRef ret=*(elemRef *)&result->aRef;
00284     CkFreeMsg(result);
00285     return ret;
00286   }
00287 }
00288 
00289 int element::checkNeighbor(int longEdge)
00290 {
00291   elemRef nbr = getNeighbor(longEdge);
00292 
00293   if (nbr.idx == -1) { 
00294     return -1; 
00295   }
00296   else { 
00297     int result;
00298     result = nbr.checkIfLongEdge(C, edges[longEdge]); 
00299     return result;
00300   }
00301 }
00302 
00303 int element::checkIfLongEdge(edgeRef e)
00304 {
00305   int longEdge = findLongestEdge();
00306   return (edges[longEdge] == e);
00307 }
00308 
00309 void element::refine()
00310 {
00311   int longEdge, test; 
00312   
00313   longEdge = findLongestEdge();
00314 
00315   if (requestResponse) {
00316     
00317     
00318     splitHelp(longEdge); 
00319     return;
00320   }
00321   if (specialRequest) { 
00322     if (getArea() < targetArea) {  
00323       splitResponse(longEdge);  
00324       return;
00325     }
00326     else { 
00327       if ((myRef.idx > specialRequester.idx) || 
00328       ((myRef.idx == specialRequester.idx) && (myRef.cid > specialRequester.cid))) {
00329     
00330     splitResponse(longEdge);
00331     return;
00332       }
00333       else 
00334     specialRequest = pendingRequest = 0;
00335     }
00336   }
00337   if (pendingRequest) 
00338     return;
00339 
00340   
00341   test = checkNeighbor(longEdge);
00342   if (test == -1) 
00343     splitBorder(longEdge);
00344   else if (test == 1) { 
00345     if (!edges[longEdge].locked(C))
00346       splitNeighbors(longEdge);
00347   }
00348   else 
00349     refineNeighbor(longEdge);
00350 }
00351 
00352 void element::splitBorder(int longEdge)
00353 { 
00354   int opnode, othernode, modEdge, otherEdge;
00355   edgeRef modEdgeRef;
00356 
00357   
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368   
00369 
00370   
00371   opnode = (longEdge + 2) % 3;
00372   othernode = longEdge;
00373   modEdge = opnode;
00374   otherEdge = (longEdge + 1) % 3;
00375   modEdgeRef = edges[modEdge];  
00376 
00377   
00378   if (edges[modEdge].lock(C)) { 
00379     if (edges[otherEdge].lock(C)) { 
00380       splitBorderLocal(longEdge, opnode, othernode, modEdge); 
00381       edges[otherEdge].unlock(C); 
00382     }
00383     modEdgeRef.unlock(C); 
00384   }
00385 }
00386 
00387 void element::splitBorderLocal(int longEdge, int opnode, int othernode, 
00388                    int modEdge)
00389 { 
00390   
00391   
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408   int fixnode = 3 - opnode - othernode;
00409   
00410   node m; 
00411   C->theNodes[nodes[othernode]].midpoint(C->theNodes[nodes[fixnode]], &m);
00412 
00413   
00414   int mIdx = C->addNode(m);
00415   edgeRef newEdgeRef = C->addEdge();
00416   edgeRef newLongRef = C->addEdge();
00417   elemRef newElemRef;
00418   if (opnode == 0) {
00419     if (othernode == 1)
00420       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge],
00421                  newLongRef, newEdgeRef);
00422     else 
00423       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newEdgeRef, 
00424                  newLongRef, edges[modEdge]);
00425   }
00426   else if (opnode == 1) {
00427     if (othernode == 0)
00428       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge], 
00429                  newEdgeRef, newLongRef);
00430     else 
00431       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newEdgeRef, 
00432                  edges[modEdge], newLongRef);
00433   }
00434   else { 
00435     if (othernode == 0)
00436       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newLongRef, 
00437                  newEdgeRef, edges[modEdge]);
00438     else 
00439       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newLongRef, 
00440                  edges[modEdge], newEdgeRef);
00441   }
00442 
00443   edges[modEdge].updateElement(C, myRef, newElemRef);
00444   C->theEdges[newEdgeRef.idx].updateElement(nullRef, myRef);
00445   C->theEdges[newEdgeRef.idx].updateElement(nullRef, newElemRef);
00446   C->theEdges[newLongRef.idx].updateElement(nullRef, newElemRef);
00447   
00448   nodes[othernode] = mIdx;
00449   edges[modEdge] = newEdgeRef;
00450   C->theElements[newElemRef.idx].setTargetArea(targetArea);
00451   
00452   
00453   if (C->theClient) C->theClient->split(myRef.idx, longEdge, othernode, 0.5, 
00454                     LOCAL_FIRST);
00455 
00456   tellDepend();  
00457 
00458   calculateArea(); 
00459   C->theElements[newElemRef.idx].calculateArea(); 
00460 }
00461 
00462 void element::splitNeighbors(int longEdge)
00463 {
00464   int opnode, othernode, modEdge, otherEdge;
00465   int nbrLongEdge, nbrOpnode, nbrOthernode, nbrModEdge, nbrOtherEdge;
00466   elemRef nbr = getNeighbor(longEdge);
00467   edgeRef modEdgeRef, nbrModEdgeRef;
00468   
00469   
00470   opnode = (longEdge + 2) % 3;
00471   othernode = longEdge;
00472   modEdge = opnode;
00473   otherEdge = (longEdge + 1) % 3;
00474 
00475   if (nbr.cid == myRef.cid) { 
00476     
00477     nbrLongEdge = C->theElements[nbr.idx].findLongestEdge();
00478     nbrOpnode = (nbrLongEdge + 2) % 3;
00479     nbrOthernode = (nbrOpnode+1) % 3;
00480     nbrModEdge = nbrOpnode;
00481     nbrOtherEdge = (nbrLongEdge + 1) % 3;
00482     if (!(C->theElements[nbr.idx].nodes[nbrOthernode] == nodes[othernode])) {
00483       nbrOthernode = (nbrOpnode+2) % 3;
00484       nbrModEdge = nbrOthernode;
00485       nbrOtherEdge = (nbrLongEdge + 2) % 3;
00486     }
00487     
00488     modEdgeRef = edges[modEdge];
00489     nbrModEdgeRef = C->theElements[nbr.idx].edges[nbrModEdge];
00490     
00491     
00492     if (edges[modEdge].lock(C)) {
00493       if (edges[otherEdge].lock(C)) {
00494     if (C->theElements[nbr.idx].edges[nbrModEdge].lock(C)) {
00495       if (C->theElements[nbr.idx].edges[nbrOtherEdge].lock(C)) {
00496         
00497         splitNeighborsLocal(longEdge, opnode, othernode, modEdge, 
00498                 nbrLongEdge, nbrOpnode, nbrOthernode, 
00499                 nbrModEdge, nbr);
00500         
00501         C->theElements[nbr.idx].edges[nbrOtherEdge].unlock(C);
00502       }
00503       nbrModEdgeRef.unlock(C);
00504     }
00505     edges[otherEdge].unlock(C);
00506       }
00507       modEdgeRef.unlock(C);
00508     }
00509   }
00510   else { 
00511     pendingRequest = 1; 
00512     mesh[nbr.cid].specialRequest(nbr.idx, myRef);
00513   }
00514 }
00515 
00516 void element::splitNeighborsLocal(int longEdge, int opnode, int othernode, 
00517                   int modEdge, int nbrLongEdge, int nbrOpnode,
00518                   int nbrOthernode, int nbrModEdge, 
00519                   const elemRef &nbr)
00520 {
00521   
00522   int fixnode = 3 - opnode - othernode;
00523   node m;
00524   C->theNodes[nodes[othernode]].midpoint(C->theNodes[nodes[fixnode]], &m);
00525 
00526   
00527   int mIdx = C->addNode(m);
00528   edgeRef newEdgeRef = C->addEdge();
00529   edgeRef newLongRef = C->addEdge();
00530   edgeRef newNbrEdgeRef = C->addEdge();
00531   elemRef newElemRef;
00532   if (opnode == 0) {
00533     if (othernode == 1)
00534       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge],
00535                  newLongRef, newEdgeRef);
00536     else 
00537       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newEdgeRef, 
00538                  newLongRef, edges[modEdge]);
00539   }
00540   else if (opnode == 1) {
00541     if (othernode == 0)
00542       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge], 
00543                  newEdgeRef, newLongRef);
00544     else 
00545       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newEdgeRef, 
00546                  edges[modEdge], newLongRef);
00547   }
00548   else { 
00549     if (othernode == 0)
00550       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newLongRef, 
00551                  newEdgeRef, edges[modEdge]);
00552     else 
00553       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newLongRef, 
00554                  edges[modEdge], newEdgeRef);
00555   }
00556   elemRef newNbrRef;
00557   if (nbrOpnode == 0) {
00558     if (nbrOthernode == 1)
00559       newNbrRef = C->addElement(C->theElements[nbr.idx].nodes[0], 
00560                  C->theElements[nbr.idx].nodes[1], mIdx, 
00561                  C->theElements[nbr.idx].edges[nbrModEdge], 
00562                  newLongRef, newNbrEdgeRef);
00563     else 
00564       newNbrRef = C->addElement(C->theElements[nbr.idx].nodes[0], mIdx, 
00565                  C->theElements[nbr.idx].nodes[2], 
00566                  newNbrEdgeRef, newLongRef, 
00567                  C->theElements[nbr.idx].edges[nbrModEdge]);
00568   }
00569   else if (nbrOpnode == 1) {
00570     if (nbrOthernode == 0)
00571       newNbrRef = C->addElement(C->theElements[nbr.idx].nodes[0], 
00572                  C->theElements[nbr.idx].nodes[1], mIdx, 
00573                  C->theElements[nbr.idx].edges[nbrModEdge], 
00574                  newNbrEdgeRef, newLongRef);
00575     else 
00576       newNbrRef = C->addElement(mIdx, C->theElements[nbr.idx].nodes[1], 
00577                  C->theElements[nbr.idx].nodes[2], 
00578                  newNbrEdgeRef, 
00579                  C->theElements[nbr.idx].edges[nbrModEdge], 
00580                  newLongRef);
00581   }
00582   else { 
00583     if (nbrOthernode == 0)
00584       newNbrRef = C->addElement(C->theElements[nbr.idx].nodes[0], mIdx, 
00585                  C->theElements[nbr.idx].nodes[2], newLongRef, 
00586                  newNbrEdgeRef, 
00587                  C->theElements[nbr.idx].edges[nbrModEdge]);
00588     else 
00589       newNbrRef = C->addElement(mIdx, C->theElements[nbr.idx].nodes[1], 
00590                  C->theElements[nbr.idx].nodes[2], newLongRef, 
00591                  C->theElements[nbr.idx].edges[nbrModEdge], 
00592                  newNbrEdgeRef);
00593   }
00594 
00595   
00596   edges[modEdge].updateElement(C, myRef, newElemRef);
00597   C->theEdges[newEdgeRef.idx].updateElement(nullRef, myRef);
00598   C->theEdges[newEdgeRef.idx].updateElement(nullRef, newElemRef);
00599   C->theEdges[newLongRef.idx].updateElement(nullRef, newElemRef);
00600   C->theEdges[newLongRef.idx].updateElement(nullRef, newNbrRef);
00601   C->theEdges[newNbrEdgeRef.idx].updateElement(nullRef, nbr);
00602   C->theEdges[newNbrEdgeRef.idx].updateElement(nullRef, newNbrRef);
00603   C->theElements[nbr.idx].edges[nbrModEdge].updateElement(C, nbr, newNbrRef);
00604   C->theElements[newElemRef.idx].setTargetArea(targetArea);
00605   C->theElements[newNbrRef.idx].setTargetArea(C->theElements[nbr.idx].getTargetArea());
00606   nodes[othernode] = mIdx;
00607   edges[modEdge] = newEdgeRef;
00608   C->theElements[nbr.idx].nodes[nbrOthernode] = mIdx;
00609   C->theElements[nbr.idx].edges[nbrModEdge] = newNbrEdgeRef;
00610 
00611   
00612   if (C->theClient) C->theClient->split(myRef.idx, longEdge, othernode, 0.5,
00613                     LOCAL_FIRST);
00614   if (C->theClient) C->theClient->split(nbr.idx, nbrLongEdge, nbrOthernode, 
00615                     0.5, LOCAL_SECOND);
00616 
00617   
00618   tellDepend();
00619   C->theElements[nbr.idx].tellDepend();
00620     
00621   
00622   
00623   calculateArea();
00624   C->theElements[newElemRef.idx].calculateArea();
00625   C->theElements[newNbrRef.idx].calculateArea();
00626   C->theElements[nbr.idx].calculateArea();  
00627 }
00628 
00629 void element::splitHelp(int longEdge)
00630 {
00631   int othernode, opnode, modEdge, otherEdge;
00632   int newNodeIdx;
00633 
00634   
00635   
00636 
00637   
00638   opnode = (longEdge + 2) % 3;
00639   othernode = longEdge;
00640   modEdge = opnode;
00641   otherEdge = (longEdge + 1) % 3;
00642   if (!(otherNode == C->theNodes[nodes[othernode]])) {
00643     othernode = (longEdge + 1) % 3;
00644     modEdge = othernode;
00645     otherEdge = opnode;
00646   }
00647 
00648   edgeRef modEdgeRef = edges[modEdge];
00649 
00650   
00651   if (!edges[modEdge].lock(C))
00652     return;
00653   if (!edges[otherEdge].lock(C)) {
00654     edges[modEdge].unlock(C);
00655     return;
00656   }
00657 
00658   
00659   newNodeIdx = C->addNode(newNode);
00660   edgeRef newEdgeRef = C->addEdge();
00661   elemRef newElemRef;
00662   if (opnode == 0) {
00663     if (othernode == 1)
00664       newElemRef = C->addElement(nodes[0], nodes[1], newNodeIdx, 
00665                  edges[modEdge], newLongEdgeRef, newEdgeRef);
00666     else 
00667       newElemRef = C->addElement(nodes[0], newNodeIdx, nodes[2], newEdgeRef, 
00668                  newLongEdgeRef, edges[modEdge]);
00669   }
00670   else if (opnode == 1) {
00671     if (othernode == 0)
00672       newElemRef = C->addElement(nodes[0], nodes[1], newNodeIdx, 
00673                  edges[modEdge], newEdgeRef, newLongEdgeRef);
00674     else 
00675       newElemRef = C->addElement(newNodeIdx, nodes[1], nodes[2], newEdgeRef, 
00676                  edges[modEdge], newLongEdgeRef);
00677   }
00678   else { 
00679     if (othernode == 0)
00680       newElemRef = C->addElement(nodes[0], newNodeIdx, nodes[2], 
00681                  newLongEdgeRef, newEdgeRef, edges[modEdge]);
00682     else 
00683       newElemRef = C->addElement(newNodeIdx, nodes[1], nodes[2], 
00684                  newLongEdgeRef, edges[modEdge], newEdgeRef);
00685   }
00686 
00687   C->theEdges[newEdgeRef.idx].updateElement(nullRef, myRef);
00688   C->theEdges[newEdgeRef.idx].updateElement(nullRef, newElemRef);
00689   newLongEdgeRef.updateElement(C, nullRef, newElemRef);
00690   edges[modEdge].updateElement(C, myRef, newElemRef);
00691   C->theElements[newElemRef.idx].setTargetArea(targetArea);
00692   nodes[othernode] = newNodeIdx;
00693   edges[modEdge] = newEdgeRef;
00694 
00695   
00696   if (C->theClient) C->theClient->split(myRef.idx, longEdge, othernode, 0.5,
00697                     BOUND_SECOND);
00698 
00699   tellDepend();  
00700   specialRequest = pendingRequest = requestResponse = 0; 
00701 
00702   
00703   edges[longEdge].unlock(C);
00704   newLongEdgeRef.unlock(C);
00705   edges[otherEdge].unlock(C);
00706   modEdgeRef.unlock(C);
00707 
00708   
00709   calculateArea();
00710   C->theElements[newElemRef.idx].calculateArea();
00711 }
00712 
00713 void element::splitResponse(int longEdge)
00714 {
00715   int opnode, othernode, modEdge, otherEdge;
00716 
00717   
00718 
00719   
00720   opnode = (longEdge + 2) % 3;
00721   othernode = longEdge;
00722   modEdge = opnode;
00723   otherEdge = (longEdge + 1) % 3;
00724   edgeRef modEdgeRef = edges[modEdge];
00725 
00726   
00727   if (!edges[longEdge].lock(C)) return;
00728   if (!edges[modEdge].lock(C)) {
00729     edges[longEdge].unlock(C);
00730     return;
00731   }
00732   if (!edges[otherEdge].lock(C)) {
00733     edges[modEdge].unlock(C);
00734     edges[longEdge].unlock(C);
00735     return;
00736   }
00737 
00738   
00739   int fixnode = 3 - opnode - othernode;
00740   node m;
00741   C->theNodes[nodes[othernode]].midpoint(C->theNodes[nodes[fixnode]], &m);
00742 
00743   
00744   int mIdx = C->addNode(m);
00745   edgeRef newEdgeRef = C->addEdge();
00746   edgeRef newLongRef = C->addEdge();
00747   elemRef newElemRef;
00748   if (opnode == 0) {
00749     if (othernode == 1)
00750       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge],
00751                  newLongRef, newEdgeRef);
00752     else 
00753       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newEdgeRef, 
00754                  newLongRef, edges[modEdge]);
00755   }
00756   else if (opnode == 1) {
00757     if (othernode == 0)
00758       newElemRef = C->addElement(nodes[0], nodes[1], mIdx, edges[modEdge], 
00759                  newEdgeRef, newLongRef);
00760     else 
00761       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newEdgeRef, 
00762                  edges[modEdge], newLongRef);
00763   }
00764   else { 
00765     if (othernode == 0)
00766       newElemRef = C->addElement(nodes[0], mIdx, nodes[2], newLongRef, 
00767                  newEdgeRef, edges[modEdge]);
00768     else 
00769       newElemRef = C->addElement(mIdx, nodes[1], nodes[2], newLongRef, 
00770                  edges[modEdge], newEdgeRef);
00771   }
00772 
00773   edges[modEdge].updateElement(C, myRef, newElemRef);
00774   C->theEdges[newEdgeRef.idx].updateElement(nullRef, myRef);
00775   C->theEdges[newEdgeRef.idx].updateElement(nullRef, newElemRef);
00776   C->theEdges[newLongRef.idx].updateElement(nullRef, newElemRef);
00777 
00778   if (!newLongRef.lock(C)) CkAbort("ERROR locking new long edge.\n");
00779   
00780   mesh[specialRequester.cid].specialRequestResponse(specialRequester.idx,
00781     m.X(), m.Y(), C->theNodes[nodes[othernode]].X(), 
00782     C->theNodes[nodes[othernode]].Y(), newLongRef);
00783 
00784   nodes[othernode] = mIdx;
00785   edges[modEdge] = newEdgeRef;
00786   C->theElements[newElemRef.idx].setTargetArea(targetArea);
00787 
00788   
00789   if (C->theClient) C->theClient->split(myRef.idx, longEdge, othernode, 0.5,
00790                     BOUND_FIRST);
00791 
00792   specialRequest = pendingRequest = requestResponse = 0; 
00793   tellDepend();  
00794 
00795   
00796   edges[otherEdge].unlock(C);
00797   modEdgeRef.unlock(C);
00798 
00799   
00800   calculateArea();
00801   C->theElements[newElemRef.idx].calculateArea();
00802 }
00803 
00804 void element::refineNeighbor(int longEdge)
00805 {
00806   elemRef nbr = getNeighbor(longEdge);
00807   
00808   
00809   if (!nbr.hasDependent(C)) {
00810     double nbrArea = nbr.getArea(C);
00811     nbr.setDependent(C, myRef.idx, myRef.cid); 
00812     depend = 1;  
00813     if (nbr.cid == myRef.cid) 
00814       
00815       C->theElements[nbr.idx].setTargetArea(nbrArea); 
00816     else 
00817       mesh[nbr.cid].refineElement(nbr.idx, nbrArea);
00818   }
00819   
00820   
00821   
00822   
00823   
00824 }
00825 
00826 void element::updateEdges(edgeRef e0, edgeRef e1, edgeRef e2)
00827 {
00828   edges[0] = e0;
00829   edges[1] = e1;
00830   edges[2] = e2;
00831 }
00832 
00833 
00834 chunk::chunk(chunkMsg *m)
00835   : TCharmClient1D(m->myThreads), numElements(0), numEdges(0), numNodes(0), 
00836     sizeElements(0), sizeEdges(0), sizeNodes(0),
00837     debug_counter(0), refineInProgress(0), modified(0),
00838     meshLock(0), meshExpandFlag(0), theClient(NULL)
00839 {
00840   refineResultsStorage=NULL;
00841   cid = thisIndex;
00842   numChunks = m->nChunks;
00843   CkFreeMsg(m);
00844   tcharmClientInit();
00845   thread->resume();
00846 }
00847 
00848 void chunk::refineElement(int i, double area)
00849 {
00850   
00851   accessLock();
00852   theElements[i].setTargetArea(area);
00853   releaseLock();
00854   modified = 1;  
00855   if (!refineInProgress) { 
00856     refineInProgress = 1;
00857     mesh[cid].refiningElements(); 
00858   }
00859 }
00860 
00861 void chunk::refiningElements()
00862 {
00863   int i;
00864   
00865   CkPrintf("[tmr] Chunk %d: refiningElements\n", cid);
00866   while (modified) { 
00867     
00868     
00869     i = 0;
00870     modified = 0;
00871     CkPrintf("[tmr] Chunk %d: Entering internal refinement loop...\n", cid);
00872     while (i < numElements) { 
00873       if (theElements[i].getCachedArea() < 0.0) 
00874         theElements[i].calculateArea();
00875       if ((!theElements[i].hasDependency() &&
00876       (((theElements[i].getTargetArea() <= theElements[i].getCachedArea()) 
00877         && (theElements[i].getTargetArea() >= 0.0)) 
00878        || theElements[i].isSpecialRequest() 
00879        || theElements[i].isPendingRequest()))
00880       || theElements[i].isRequestResponse()) {
00881     
00882     
00883     
00884     modified = 1; 
00885     theElements[i].refine(); 
00886       }
00887       i++;
00888     }
00889     
00890     adjustMesh();
00891     CthYield(); 
00892   }
00893   
00894   refineInProgress = 0;  
00895   CkPrintf("[tmr] Chunk %d: DONE refiningElements\n", cid);
00896 }
00897 
00898 
00899 void chunk::updateElement(int i, objRef oldval, objRef newval)
00900 {
00901   accessLock();
00902   theEdges[i].updateElement(elemRef(oldval.cid, oldval.idx), 
00903                 elemRef(newval.cid, newval.idx));
00904   releaseLock();
00905 }
00906 
00907 
00908 void chunk::specialRequest(int requestee, elemRef requester)
00909 {
00910   accessLock();
00911   theElements[requestee].setSpecialRequest(requester);
00912   releaseLock();
00913   
00914   modified = 1;
00915   if (!refineInProgress) {
00916     refineInProgress = 1;
00917     mesh[cid].refiningElements();
00918   }
00919 }
00920 
00921 void chunk::specialRequestResponse(int i, double newNodeX, double newNodeY, 
00922                    double otherNodeX, double otherNodeY, 
00923                    edgeRef newLongEdgeRef)
00924 {
00925   node newNode(newNodeX, newNodeY);
00926   node otherNode(otherNodeX, otherNodeY);
00927   accessLock();
00928   theElements[i].setRequestResponse(newNode, otherNode, newLongEdgeRef);
00929   releaseLock();
00930   
00931   modified = 1;
00932   if (!refineInProgress) {
00933     refineInProgress = 1;
00934     mesh[cid].refiningElements();
00935   }
00936 }
00937 
00938 doubleMsg *chunk::getArea(int i)
00939 {
00940   doubleMsg *dm = new doubleMsg;
00941   accessLock();
00942   dm->aDouble = theElements[i].getArea();
00943   releaseLock();
00944   return dm;
00945 }
00946 
00947 intMsg *chunk::lock(int i)
00948 {
00949   intMsg *rm = new intMsg;
00950   accessLock();
00951   if (theEdges[i].locked())
00952     rm->anInt = 0;
00953   else {
00954     theEdges[i].lock();
00955     rm->anInt = 1;
00956   }
00957   releaseLock();
00958   return rm;
00959 }
00960 
00961 void chunk::unlock(int i)
00962 {
00963   accessLock();
00964   theEdges[i].unlock();
00965   releaseLock();
00966 }
00967 
00968 
00969 intMsg *chunk::locked(int i)
00970 {
00971   intMsg *rm = new intMsg;
00972   accessLock();
00973   rm->anInt = theEdges[i].locked();
00974   releaseLock();
00975   return rm;
00976 }
00977 
00978 intMsg *chunk::checkElement(objRef oR, int i)
00979 {
00980   intMsg *im = new intMsg;
00981   edgeRef eRef(oR.cid, oR.idx);
00982 
00983   accessLock();
00984   im->anInt = theElements[i].checkIfLongEdge(eRef);
00985   releaseLock();
00986   return im;
00987 }
00988 
00989 refMsg *chunk::getNeighbor(objRef oR, int i)
00990 {
00991   refMsg *rm = new refMsg;
00992   elemRef er, ar(oR.cid, oR.idx);
00993   accessLock();
00994   er = theEdges[i].getNbrRef(ar);
00995   releaseLock();
00996   rm->aRef = er;
00997   return rm;
00998 }
00999 
01000 void chunk::setTargetArea(int i, double area)
01001 {
01002   accessLock();
01003   theElements[i].setTargetArea(area);
01004   releaseLock();
01005   modified = 1;
01006   if (!refineInProgress) {
01007     refineInProgress = 1;
01008     mesh[cid].refiningElements();
01009   }
01010 }
01011 
01012 void chunk::updateEdges(int i, edgeRef e0, edgeRef e1, edgeRef e2)
01013 {
01014   accessLock();
01015   theElements[i].updateEdges(e0, e1, e2);
01016   releaseLock();
01017 }
01018 
01019 void chunk::setDependent(objRef oR, int i)
01020 {
01021   accessLock();
01022   theElements[i].setDependent(oR.cid, oR.idx);
01023   releaseLock();
01024   modified = 1;
01025   if (!refineInProgress) {
01026     refineInProgress = 1;
01027     mesh[cid].refiningElements();
01028   }
01029 }
01030 
01031 intMsg *chunk::hasDependent(int i)
01032 {
01033   intMsg *result = new intMsg;
01034   accessLock();
01035   result->anInt = theElements[i].hasDependent();
01036   releaseLock();
01037   return result;
01038 }
01039 
01040 void chunk::unsetDependency(int i)
01041 {
01042   accessLock();
01043   theElements[i].unsetDependency();
01044   releaseLock();
01045   modified = 1;
01046   if (!refineInProgress) {
01047     refineInProgress = 1;
01048     mesh[cid].refiningElements();
01049   }
01050 }
01051 
01052 
01053 
01054 void chunk::accessLock()
01055 {
01056   while (meshExpandFlag)
01057     CthYield();
01058   meshLock--;
01059 }
01060 
01061 void chunk::releaseLock()
01062 {
01063   meshLock++;
01064 }
01065 
01066 void chunk::adjustFlag()
01067 {
01068   meshExpandFlag = 1;
01069 }
01070 
01071 void chunk::adjustLock()
01072 {
01073   while (meshLock != 0)
01074     CthYield();
01075   meshLock = 1;
01076 }
01077 
01078 void chunk::adjustRelease()
01079 {
01080   meshLock = meshExpandFlag = 0;
01081 }
01082 
01083 void chunk::adjustMesh()
01084 {
01085   if ((sizeElements < numElements) || (sizeNodes < numNodes) || (sizeEdges < numEdges))
01086     CkPrintf("[tmr] WARNING!\n\n     Mesh overrun! Data is probably corrupted!!!\n");
01087   if (sizeElements <= numElements*4) {
01088     adjustFlag();
01089     adjustLock();
01090     CkPrintf("[tmr] [%d] Adjusting mesh size...\n", cid);
01091     sizeElements = numElements*4;
01092     sizeEdges = numEdges*12;
01093     sizeNodes = numNodes*12;
01094     theElements.resize(sizeElements);
01095     theEdges.resize(sizeEdges);
01096     theNodes.resize(sizeNodes);
01097     CkPrintf("[tmr] [%d] Done adjusting mesh size...\n", cid);
01098     adjustRelease();
01099   }
01100 }
01101 
01102 int chunk::addNode(node n)
01103 {
01104   theNodes[numNodes] = n;
01105   theNodes[numNodes].init(this);
01106   numNodes++;
01107   return numNodes-1;
01108 }
01109 
01110 
01111 edgeRef chunk::addEdge()
01112 {
01113   theEdges[numEdges].init(numEdges, this);
01114   edgeRef eRef(cid, numEdges);
01115   numEdges++;
01116   return eRef;
01117 }
01118 
01119 elemRef chunk::addElement(int n1, int n2, int n3)
01120 {
01121   int n[3] = {n1, n2, n3};
01122   elemRef eRef(cid, numElements);
01123   theElements[numElements].init(n, numElements, this);
01124   theElements[numElements].calculateArea();
01125   numElements++;
01126   modified = 1;
01127   if (!refineInProgress) {
01128     refineInProgress = 1;
01129     mesh[cid].refiningElements();
01130   }
01131   return eRef;
01132 }
01133 
01134 elemRef chunk::addElement(int n1, int n2, int n3,
01135               edgeRef er1, edgeRef er2, edgeRef er3)
01136 {
01137   int n[3] = {n1, n2, n3};
01138   edgeRef e[3] = {er1, er2, er3}; 
01139 
01140   elemRef eRef(cid, numElements);
01141   theElements[numElements].init(n, e, numElements, this);
01142   theElements[numElements].calculateArea();
01143   numElements++;
01144   modified = 1;
01145   if (!refineInProgress) {
01146     refineInProgress = 1;
01147     mesh[cid].refiningElements();
01148   }
01149   return eRef;
01150 }
01151 
01152 
01153 
01154 void chunk::print()
01155 {
01156   accessLock();
01157   debug_print(debug_counter);
01158   debug_counter++;
01159   releaseLock();
01160 }
01161 
01162 void chunk::debug_print(int c)
01163 {
01164   FILE *fp;
01165   char filename[30];
01166   int i, j;
01167 
01168   memset(filename, 0, 30);
01169   sprintf(filename, "mesh_debug_%d.%d", cid, c);
01170   fp = fopen(filename, "w");
01171 
01172   fprintf(fp, "%d %d\n", cid, numElements);
01173   for (i=0; i<numElements; i++) {
01174     for (j=0; j<3; j++)
01175       fprintf(fp, "%f %f   ", theNodes[theElements[i].nodes[j]].X(), 
01176           theNodes[theElements[i].nodes[j]].Y());
01177     fprintf(fp, "%d %f\n", i, theElements[i].getTargetArea());
01178     for (j=0; j<3; j++) {
01179       fprintf(fp, "%d  ", ((theElements[i].getEdge(j).locked(this))?2:0));
01180     }
01181     fprintf(fp, "\n");
01182   }
01183   fclose(fp);
01184 }
01185 
01186 void chunk::out_print()
01187 {
01188   FILE *fp;
01189   char filename[30];
01190   int i;
01191 
01192   memset(filename, 0, 30);
01193   sprintf(filename, "mesh.out");
01194   fp = fopen(filename, "a");
01195 
01196   if (cid == 0)
01197     fprintf(fp, "%d\n", numChunks);
01198   fprintf(fp, " %d %d %d %d\n", cid, numNodes, numEdges, numElements);
01199   for (i=0; i<numNodes; i++)
01200     fprintf(fp, "    %f %f\n", theNodes[i].X(), theNodes[i].Y());
01201   for (i=0; i<numEdges; i++) {
01202     fprintf(fp, "   ");
01203     fprintf(fp, " %d %d ", theEdges[i].elements[0].idx, theEdges[i].elements[0].cid);
01204     fprintf(fp, " %d %d\n", theEdges[i].elements[1].idx, theEdges[i].elements[1].cid);
01205   }
01206   for (i=0; i<numElements; i++) {
01207     fprintf(fp, " %d %d ", theElements[i].nodes[0], cid);
01208     fprintf(fp, " %d %d ", theElements[i].nodes[1], cid);
01209     fprintf(fp, " %d %d ", theElements[i].nodes[2], cid);
01210     fprintf(fp, "   ");
01211     fprintf(fp, " %d %d ", theElements[i].edges[0].idx, theElements[i].edges[0].cid);
01212     fprintf(fp, " %d %d ", theElements[i].edges[1].idx, theElements[i].edges[1].cid);
01213     fprintf(fp, " %d %d\n", theElements[i].edges[2].idx, theElements[i].edges[2].cid);
01214   }
01215   fprintf(fp, "\n");
01216   fclose(fp);
01217 }
01218 
01219 void chunk::updateNodeCoords(int nNode, double *coord, int nEl)
01220 {
01221   int i;
01222 
01223 #if 1
01224   
01225   if (nEl != numElements || nNode != numNodes) {
01226     CkPrintf("ERROR: inconsistency in REFINE2D's updateNodeCoords on chunk %d:\n"
01227        "  your nEl (%d); my numElements (%d)\n"
01228        "  your nNode (%d); my numNodes (%d)\n",
01229        cid, nEl, numElements, nNode,numNodes);
01230     CkAbort("User code/library numbering inconsistency in REFINE2D");
01231   }
01232 #endif  
01233   
01234   
01235   for (i=0; i<numNodes; i++){
01236     theNodes[i].init(coord[2*i], coord[2*i + 1]);
01237     CkPrintf("[tmr] Chunk %d Node %d %.8lf %.8lf \n",cid,i,theNodes[i].X(),theNodes[i].Y());
01238   }  
01239     
01240   
01241   for (i=0; i<numElements; i++){
01242     theElements[i].calculateArea();
01243     CkPrintf("[tmr] Chunk %d Element %d area = %.8lf \n",cid,i, theElements[i].getArea());
01244   } 
01245   sanityCheck();
01246 }
01247 
01248 void chunk::multipleRefine(double *desiredArea, refineClient *client)
01249 {
01250   int i;
01251   theClient = client; 
01252 
01253   CkPrintf("[tmr] Chunk %d: multipleRefine\n", cid);
01254   
01255   for (i=0; i<numElements; i++)
01256     if (desiredArea[i] < theElements[i].getArea()) {
01257       theElements[i].setTargetArea(desiredArea[i]);
01258       CkPrintf("[tmr] Chunk %d: Element %d to be refined from %.8lf to below %.8lf \n",
01259            cid, i, theElements[i].getArea(), desiredArea[i]);
01260     }
01261   
01262   if (CkMyPe() == 0)
01263     for (i=0; i<numChunks; i++) 
01264       mesh[i].out_print();
01265 
01266   
01267   modified = 1;
01268   if (!refineInProgress) {
01269     refineInProgress = 1;
01270     mesh[cid].refiningElements();
01271   }
01272 }
01273 
01274 
01275 
01276 void chunk::sanityCheck(void)
01277 {
01278   int i;
01279   if (numElements<0 || (int)theElements.size()<numElements)
01280     CkAbort("REFINE2D chunk elements insane!");
01281   if (numEdges<0 || (int)theEdges.size()<numEdges)
01282     CkAbort("REFINE2D chunk edges insane!");
01283   if (numNodes<0 || (int)theNodes.size()<numNodes)
01284     CkAbort("REFINE2D chunk nodes insane!");
01285   for (i=0;i<numElements;i++) {
01286     theElements[i].sanityCheck(this,elemRef(cid,i));
01287   }
01288   for (i=0;i<numEdges;i++) {
01289     theEdges[i].sanityCheck(this,edgeRef(cid,i));
01290   }
01291 }
01292 
01293 void objRef::sanityCheck(chunk *C)
01294 {
01295   if (isNull()) 
01296     CkAbort("REFINE2D objRef is unexpectedly null");
01297 }
01298 void element::sanityCheck(chunk *c,elemRef shouldRef)
01299 {
01300   if (myRef!=shouldRef)
01301     CkAbort("REFINE2D elem has wrong ref");
01302   
01303   for (int i=0;i<3;i++) {
01304     
01305     edges[i].sanityCheck(c);
01306   }
01307 }
01308 void edge::sanityCheck(chunk *c,edgeRef shouldRef)
01309 {
01310   if (myRef!=shouldRef)
01311     CkAbort("REFINE2D edge has wrong ref");
01312   
01313   int nonNullElements=0;
01314   for (int i=0;i<2;i++) {
01315     
01316     if (!elements[i].isNull()) {
01317       elements[i].sanityCheck(c);
01318       nonNullElements++;
01319     }
01320   }
01321   if (!(nonNullElements==1 || nonNullElements==2))
01322     CkAbort("REFINE2D edge has unexpected number of neighbors!");
01323 }
01324   
01325 
01326 
01327 
01328 void chunk::allocMesh(int nEl)
01329 {
01330   sizeElements = nEl * 2;
01331   sizeNodes = sizeEdges = sizeElements * 3;
01332   theElements.resize(sizeElements);
01333   theNodes.resize(sizeNodes);
01334   theEdges.resize(sizeEdges);
01335   for (int i=0; i<sizeElements; i++) {
01336     theElements[i].init(); 
01337     theEdges[i].init();
01338   }
01339 }
01340 
01341 void chunk::newMesh(int nEl, int nGhost, const int *conn_, const int *gid_, int idxOffset)
01342 {
01343   int i, j;
01344 
01345   CkPrintf("[tmr] newMesh on chunk %d...\n", cid);
01346   numElements = nEl;
01347   numGhosts = nGhost;
01348   allocMesh(nEl);
01349   int *conn = new int[3*numGhosts];
01350   int *gid = new int[2*numGhosts];
01351   
01352   
01353   for (i=0; i<numElements; i++) {
01354     int nodes[3];
01355     edgeRef edges[3];
01356     for (j=0; j<3; j++) {
01357       int c=conn_[i*3+j]-idxOffset;
01358       conn[i*3 + j]=c;
01359       nodes[j] = c;
01360       edges[j].init();
01361     }
01362     theElements[i].init(nodes, edges, i, this);
01363     gid[i*2] = cid;
01364     gid[i*2 + 1] = i;
01365   }
01366 
01367   
01368   for (i=nEl; i<nGhost; i++) {
01369     for (j=0; j<3; j++)
01370       conn[i*3+j] = conn_[i*3+j]-idxOffset;
01371     gid[i*2+0] = gid_[i*2]-idxOffset;
01372     gid[i*2+1] = gid_[i*2 + 1]-idxOffset;
01373   }
01374 
01375 
01376   
01377   
01378   
01379   int n1localIdx, n2localIdx, newEdge;
01380 
01381   deriveNodes(); 
01382   
01383   for (i=0; i<numElements; i++) {
01384     elemRef myRef(cid,i);
01385     for (j=0; j<3; j++) {
01386       n1localIdx = j;
01387       n2localIdx = (j+1) % 3;
01388 
01389       
01390       if (theElements[i].edges[j] == nullRef) { 
01391     
01392     elemRef nbrRef;
01393     int edgeIdx = getNbrRefOnEdge(theElements[i].nodes[n1localIdx], 
01394                       theElements[i].nodes[n2localIdx], 
01395                       conn, numGhosts, gid, i, &nbrRef); 
01396     if (edgeLocal(myRef, nbrRef)) { 
01397       newEdge = addNewEdge();
01398       
01399       theEdges[newEdge].updateElement(nullRef, myRef);
01400       theEdges[newEdge].updateElement(nullRef, nbrRef);
01401       
01402       theElements[i].updateEdge(j, theEdges[newEdge].getRef());
01403       
01404       if (nbrRef.cid==cid) 
01405         theElements[nbrRef.idx].updateEdge(edgeIdx,
01406                            theEdges[newEdge].getRef());
01407       else if (nbrRef.cid != -1) 
01408         mesh[nbrRef.cid].addRemoteEdge(nbrRef.idx, edgeIdx, 
01409                        theEdges[newEdge].getRef());
01410     }
01411     
01412       }
01413     }
01414   }
01415   delete[] conn;
01416   delete[] gid;
01417   CkPrintf("[tmr] Finished newMesh on chunk %d...\n", cid);
01418 }
01419 
01420 void chunk::deriveNodes()
01421 {
01422   int i, j;
01423   int aNode;
01424 
01425   numNodes = 0;
01426   for (i=0; i<numElements; i++) {
01427     for (j=0; j<3; j++) {
01428       aNode = theElements[i].nodes[j];
01429       if (aNode >= 0) {
01430     theNodes[aNode].init(this);
01431     if ((aNode + 1) > numNodes)
01432       numNodes = aNode + 1;
01433       }
01434       else CkAbort("[tmr] ERROR: negative node id found in conn...\n");
01435     }
01436   }
01437 }
01438 
01439 void chunk::addRemoteEdge(int elem, int localEdge, edgeRef er)
01440 {
01441   while (sizeElements == 0) CthYield();
01442   theElements[elem].updateEdge(localEdge, er);
01443 }
01444 
01445 int chunk::edgeLocal(elemRef e1, elemRef e2)
01446 {
01447   if (e1.cid==-1 || e2.cid==-1) 
01448     return 1; 
01449   if (e1.cid == e2.cid)
01450     return 1; 
01451   if (e1.idx > e2.idx)
01452     return 1;
01453   else if ((e1.idx == e2.idx) && (e1.cid > e2.cid))
01454     return 1;
01455   else return 0;
01456 }
01457 
01458 int chunk::addNewEdge()
01459 {
01460   theEdges[numEdges].init(numEdges, this);
01461   numEdges++;
01462   return numEdges-1;
01463 }
01464 
01465 int chunk::getNbrRefOnEdge(int n1, int n2, int *conn, int nGhost, int *gid, 
01466                int idx, elemRef *er)
01467 {
01468   int i, e;
01469   er->init();
01470   for (i=idx+1; i<nGhost; i++)
01471     if ((e = hasEdge(n1, n2, conn, i)) != -1) {
01472       er->init(gid[i*2], gid[i*2+1]);
01473       return e;
01474     }
01475   return -1;
01476 }
01477 
01478 int chunk::hasEdge(int n1, int n2, int *conn, int idx) 
01479 {
01480   for (int i=0; i<3; i++) {
01481     int a=i;
01482     int b=(i+1)%3;
01483     if (((conn[idx*3+a] == n1) && (conn[idx*3+b] == n2)) ||
01484     ((conn[idx*3+b] == n1) && (conn[idx*3+a] == n2)))
01485       return i;
01486   }
01487   return -1;
01488     
01489 }
01490 
01491 #include "refine.def.h"