00001 
00002 
00003 
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include "tri.h"
00007 
00008 
00009 
00010 
00011 CProxy_chunk mesh;
00012 CtvDeclare(chunk *, _refineChunk);
00013 
00014 void refineChunkInit(void) {
00015   CtvInitialize(chunk *, _refineChunk);
00016 }
00017 
00018 chunk::chunk(chunkMsg *m)
00019   : TCharmClient1D(m->myThreads), sizeElements(0), sizeEdges(0), sizeNodes(0),
00020     firstFreeElement(0), firstFreeEdge(0), firstFreeNode(0),
00021     edgesSent(0), edgesRecvd(0), first(0),
00022     coarsenElements(NULL), refineElements(NULL), refineStack(NULL),
00023     refineHeapSize(0), coarsenHeapSize(0), refineTop(0),
00024     additions(0), debug_counter(0), refineInProgress(0), coarsenInProgress(0),
00025     meshLock(0), meshExpandFlag(0), 
00026     numElements(0), numEdges(0), numNodes(0), numGhosts(0), theClient(NULL),
00027     elementSlots(0), edgeSlots(0), nodeSlots(0), lock(0), lockCount(0),
00028     lockHolderIdx(-1), lockHolderCid(-1), lockPrio(-1.0), lockList(NULL)
00029 {
00030   refineResultsStorage=NULL;
00031   cid = thisIndex;
00032   numChunks = m->nChunks;
00033   CkFreeMsg(m);
00034   tcharmClientInit();
00035   thread->resume();
00036 }
00037 
00038 void chunk::addRemoteEdge(int elem, int localEdge, edgeRef er)
00039 {
00040   accessLock();
00041   CkAssert(localEdge >=0);
00042   CkAssert(localEdge < 3);
00043   CkAssert(er.cid > -1);
00044   CkAssert(er.idx > -1);
00045   if ((theElements[elem].edges[localEdge].cid > -1) &&
00046       (theElements[elem].edges[localEdge].idx > -1)){
00047     CkPrintf("TMRC2D: [%d] WARNING: addRemoteEdge replacing non-null edgeRef!\n", cid);
00048   } 
00049   theElements[elem].set(localEdge, er);
00050 #ifdef TDEBUG3
00051   CkPrintf("TMRC2D: [%d] addRemoteEdge on element %d", cid, elem);
00052 #endif
00053   edgesRecvd++;
00054   releaseLock();
00055 }
00056 
00057 void chunk::refineElement(int idx, double area)
00058 { 
00059   if (!theElements[idx].isPresent()) return;
00060   accessLock();
00061   theElements[idx].resetTargetArea(area);
00062   refineStack[refineTop].elID = idx;
00063   refineStack[refineTop].len = -1.0;
00064   refineTop++;
00065   int pos = refineHeapSize;
00066   while (pos >= 1) {
00067     if (refineElements[pos].elID == idx)
00068       refineElements[pos].elID = -1;
00069     pos--;
00070   }
00071   releaseLock();
00072   if (!refineInProgress) { 
00073     refineInProgress = 1;
00074     mesh[cid].refiningElements(); 
00075   }
00076 }
00077 
00078 void chunk::refiningElements()
00079 {
00080   int i;
00081   while (refineHeapSize>0 || refineTop > 0) { 
00082     if (refineTop>0) {
00083       refineTop--;
00084       i=refineStack[refineTop].elID;
00085     }
00086     else
00087       i=Delete_Min(0);
00088     if ((i != -1) && theElements[i].isPresent()) {
00089       
00090       theElements[i].refine(); 
00091       adjustMesh();
00092     }
00093     CthYield(); 
00094   }
00095   sanityCheck(); 
00096   refineInProgress = 0; 
00097   
00098 }
00099 
00100 
00101 void chunk::coarsenElement(int idx, double area)
00102 { 
00103   if (!theElements[idx].isPresent()) return;
00104   double theArea;
00105   accessLock();
00106   theArea = theElements[idx].getArea();
00107   if (area > theElements[idx].getTargetArea())
00108     theElements[idx].resetTargetArea(area);
00109   Insert(idx, -1.0, 1);
00110   int pos = coarsenHeapSize;
00111   while (pos > 1) {
00112     if (coarsenElements[pos].elID == idx)
00113       coarsenElements[pos].elID = -1;
00114     pos--;
00115   }
00116   releaseLock();
00117   if (!coarsenInProgress) { 
00118     coarsenInProgress = 1;
00119     mesh[cid].coarseningElements(); 
00120   }
00121 }
00122 
00123 void chunk::coarseningElements()
00124 {
00125   int i;
00126   double area, qFactor, targetArea;
00127   while (coarsenHeapSize > 0) { 
00128     i=Delete_Min(1);
00129     CkPrintf("Loop at element %d\n", i);
00130     if ((i != -1) && theElements[i].isPresent()) {
00131       CkPrintf("Checking element %d\n", i);
00132       area = theElements[i].getArea();
00133       targetArea = theElements[i].getTargetArea();
00134       qFactor = theElements[i].getAreaQuality();
00135       if ((theElements[i].getTargetArea()*COARSEN_PRECISION > area) || 
00136       (area == 0.0) || (qFactor < QUALITY_MIN)) { 
00137     CkPrintf("Coarsening element %d\n", i);
00138     theElements[i].coarsen(); 
00139       }
00140     }
00141     CthYield(); 
00142   }
00143   coarsenInProgress = 0;  
00144   if (coarsenElements) delete [] coarsenElements;
00145   coarsenElements = new elemHeap[numElements+1];
00146   coarsenElements[0].elID=-1;
00147   coarsenElements[0].len=-2.0;
00148   for (i=0; i<elementSlots; i++) {
00149     if (theElements[i].isPresent() && (theElements[i].nonCoarsenCount<1)) {
00150       area = theElements[i].getArea();
00151       if (area == 0.0) {
00152     CkPrintf("Element[%d] has area %1.10e!\n", i, area);
00153       }
00154       targetArea = theElements[i].getTargetArea();
00155       double shortEdgeLen, angle;
00156       shortEdgeLen=theElements[i].getShortestEdge(&angle);
00157       qFactor = theElements[i].getAreaQuality();
00158       if ((targetArea*COARSEN_PRECISION > area) || (qFactor < QUALITY_MIN)) {
00159     CkPrintf("Element[%d] has area %1.10e target %1.10e qFactor %1.10e\n", i, area, targetArea, qFactor);
00160     Insert(i, shortEdgeLen*qFactor, 1);
00161       }
00162     }
00163   }
00164   sanityCheck(); 
00165   if ((coarsenHeapSize>0) && !coarsenInProgress) {
00166     coarsenInProgress = 1;
00167     mesh[cid].coarseningElements();
00168   }
00169 }
00170 
00171 
00172 intMsg *chunk::safeToMoveNode(int idx, double x, double y)
00173 {
00174   node foo(x, y);
00175   intMsg *im = new intMsg;
00176   accessLock();
00177   im->anInt = theNodes[idx].safeToMove(foo);
00178   releaseLock();
00179   return im;
00180 }
00181 
00182 splitOutMsg *chunk::split(int idx, elemRef e, int oIdx, int fIdx)
00183 {
00184   splitOutMsg *som = new splitOutMsg;
00185   accessLock();
00186   som->result = theEdges[idx].split(&(som->n), &(som->e), oIdx, fIdx, e, 
00187                     &(som->local), &(som->first), 
00188                     &(som->nullNbr));
00189   releaseLock();
00190   return som;
00191 }
00192 
00193 void chunk::collapse(int idx, elemRef e, int kIdx, int dIdx, elemRef kNbr, 
00194              elemRef dNbr, edgeRef kEdge, edgeRef dEdge, node newN, 
00195              double frac)
00196 {
00197   accessLock();
00198   theEdges[idx].collapse(e, kIdx, dIdx, kNbr, dNbr, kEdge, dEdge, newN, frac);
00199   releaseLock();
00200 }
00201 
00202 splitOutMsg *chunk::flipPreventE(int idx, elemRef e, int kIdx, int dIdx,
00203                  elemRef kNbr, elemRef dNbr, edgeRef kEdge, 
00204                  edgeRef dEdge, node newN)
00205 {
00206   splitOutMsg *som = new splitOutMsg;
00207   accessLock();
00208   som->result = theEdges[idx].flipPrevent(e, kIdx, dIdx, kNbr, dNbr, kEdge, 
00209                       dEdge, newN);
00210   releaseLock();
00211   return som;
00212 }
00213 
00214 void chunk::nodeReplaceDelete(int kIdx, int dIdx, node nn, int shared, 
00215                   int *chk, int *idx)
00216 {
00217   int *jChk, *jIdx;
00218   int jShared;
00219   accessLock();
00220   if (dIdx == -1) { 
00221     if (kIdx != -1) {
00222       theNodes[kIdx].set(nn.X(), nn.Y());
00223       theNodes[kIdx].boundary = nn.boundary;
00224       theNodes[kIdx].fixed = nn.fixed;
00225       jShared = joinCommLists(kIdx, shared, chk, idx, jChk, jIdx);
00226       theClient->nodeUpdate(kIdx, nn.X(), nn.Y(), nn.boundary, jShared, jChk, 
00227                 jIdx);
00228 #ifdef TDEBUG1
00229       CkPrintf("TMRC2D: [%d] (a)theClient->nodeUpdate(%d, %2.10f, %2.10f, %d)\n", cid, kIdx, nn.X(), nn.Y(), nn.boundary);
00230 #endif
00231     }
00232     return;
00233   }
00234   else if (kIdx == -1) {
00235     theNodes[dIdx].set(nn.X(), nn.Y());
00236     theNodes[dIdx].boundary = nn.boundary;
00237     theNodes[dIdx].fixed = nn.fixed;
00238     jShared = joinCommLists(dIdx, shared, chk, idx, jChk, jIdx);
00239     theClient->nodeUpdate(dIdx, nn.X(), nn.Y(), nn.boundary, jShared, jChk, 
00240               jIdx);
00241 #ifdef TDEBUG1
00242     CkPrintf("TMRC2D: [%d] (b)theClient->nodeUpdate(%d, %2.10f, %2.10f, %d)\n", cid, dIdx, nn.X(), nn.Y(), nn.boundary);
00243 #endif
00244   }
00245   else {
00246     removeNode(dIdx);
00247     theNodes[kIdx].set(nn.X(), nn.Y());
00248     theNodes[kIdx].boundary = nn.boundary;
00249     theNodes[kIdx].fixed = nn.fixed;
00250     jShared = joinCommLists(kIdx, shared, chk, idx, jChk, jIdx);
00251     theClient->nodeUpdate(kIdx, nn.X(), nn.Y(), nn.boundary, jShared, jChk, 
00252               jIdx);
00253 #ifdef TDEBUG1
00254     CkPrintf("TMRC2D: [%d] (c)theClient->nodeUpdate(%d, %2.10f, %2.10f, %d)\n", cid, kIdx, nn.X(), nn.Y(), nn.boundary);
00255 #endif
00256     for (int j=0; j<elementSlots; j++) {
00257       if (theElements[j].isPresent()) {
00258     CkAssert(theElements[j].nodes[0] != theElements[j].nodes[1]);
00259     CkAssert(theElements[j].nodes[0] != theElements[j].nodes[2]);
00260     CkAssert(theElements[j].nodes[2] != theElements[j].nodes[1]);
00261     for (int k=0; k<3; k++) {
00262       if (theElements[j].nodes[k] == dIdx) {
00263 #ifdef FLIPTEST
00264         if(theElements[j].nodes[(k+1)%3] == kIdx || theElements[j].nodes[(k+2)%3] == kIdx) break; 
00265         if(theElements[j].flipInverseTest(&(theNodes[dIdx]),&nn)) {
00266           
00267         }
00268 #endif
00269         theElements[j].nonCoarsenCount = 0;
00270         theElements[j].nodes[k] = kIdx;
00271         theClient->nodeReplaceDelete(j, k, dIdx, kIdx);
00272 #ifdef TDEBUG1
00273         CkPrintf("TMRC2D: [%d] theClient->nodeReplaceDelete(%d, %d, %d, %d)\n", cid, j, k, dIdx, kIdx);
00274 #endif
00275       }
00276       if (theElements[j].nodes[k] == kIdx) {
00277         theElements[j].nonCoarsenCount = 0;
00278       }
00279     }
00280     CkAssert(theElements[j].nodes[0] != theElements[j].nodes[1]);
00281     CkAssert(theElements[j].nodes[0] != theElements[j].nodes[2]);
00282     CkAssert(theElements[j].nodes[2] != theElements[j].nodes[1]);
00283       }
00284     }
00285     for (int j=0; j<edgeSlots; j++) {
00286       if (theEdges[j].isPresent()) {
00287     for (int k=0; k<2; k++) {
00288       if (theEdges[j].nodes[k] == dIdx) {
00289         theEdges[j].nodes[k] = kIdx;
00290 #ifdef TDEBUG1
00291         CkPrintf("TMRC2D: [%d] Edge %d node %d replaced with %d\n", cid, j,
00292              dIdx, kIdx);
00293 #endif
00294       }
00295     }
00296       }
00297     }
00298   }
00299   releaseLock();
00300 }
00301 
00302 boolMsg *chunk::flipPrevent(int kIdx, int dIdx, node nn, int shared, int *chk, int *idx)
00303 {
00304   boolMsg *bm = new boolMsg;
00305   bm->aBool = false;
00306   for (int j=0; j<elementSlots; j++) {
00307     if (theElements[j].isPresent()) {
00308       CkAssert(theElements[j].nodes[0] != theElements[j].nodes[1]);
00309       CkAssert(theElements[j].nodes[1] != theElements[j].nodes[2]);
00310       CkAssert(theElements[j].nodes[2] != theElements[j].nodes[0]);
00311       for (int k=0; k<3; k++) {
00312     if (theElements[j].nodes[k] == dIdx) {
00313       if(theElements[j].nodes[(k+1)%3] == kIdx || theElements[j].nodes[(k+2)%3] == kIdx) break; 
00314       if(theElements[j].flipInverseTest(&(theNodes[dIdx]),&nn)) {
00315         
00316         bm->aBool = true;
00317         
00318         return bm;
00319       }
00320     }
00321     if (theElements[j].nodes[k] == kIdx) {
00322       if(theElements[j].nodes[(k+1)%3] == dIdx || theElements[j].nodes[(k+2)%3] == dIdx) break; 
00323       if(theElements[j].flipInverseTest(&(theNodes[kIdx]),&nn)) {
00324         
00325         bm->aBool = true;
00326         
00327         return bm;
00328       }
00329     }
00330       }
00331     }
00332   }
00333   return bm;
00334 }
00335 
00336 void chunk::incnonCoarsen(int idx) {
00337   accessLock();
00338   theElements[idx].incnonCoarsen();
00339   releaseLock();
00340   return;
00341 }
00342 
00343 void chunk::resetnonCoarsen(int idx) {
00344   accessLock();
00345   theElements[idx].resetnonCoarsen();
00346   releaseLock();
00347   return;
00348 }
00349 
00350 intMsg *chunk::isPending(int idx, objRef e)
00351 {
00352   intMsg *im = new intMsg;
00353   elemRef eR(e.cid, e.idx);
00354   accessLock();
00355   im->anInt = theEdges[idx].isPending(eR);
00356   releaseLock();
00357   return im;
00358 }
00359 
00360 void chunk::checkPending(int idx, objRef aRef)
00361 {
00362   elemRef eRef;
00363   eRef.idx = aRef.idx; eRef.cid = aRef.cid;
00364   accessLock();
00365   theEdges[idx].checkPending(eRef);
00366   releaseLock();
00367 }
00368 
00369 void chunk::checkPending(int idx, objRef aRef1, objRef aRef2)
00370 {
00371   elemRef eRef1, eRef2;
00372   eRef1.idx = aRef1.idx; eRef1.cid = aRef1.cid;
00373   eRef2.idx = aRef2.idx; eRef2.cid = aRef2.cid;
00374   accessLock();
00375   theEdges[idx].checkPending(eRef1, eRef2);
00376   releaseLock();
00377 }
00378 
00379 void chunk::updateElement(int idx, objRef oldval, objRef newval, int b)
00380 {
00381   elemRef ov, nv;
00382   ov.idx = oldval.idx;   ov.cid = oldval.cid; 
00383   nv.idx = newval.idx;   nv.cid = newval.cid; 
00384   accessLock();
00385   theEdges[idx].update(ov, nv);
00386 #ifdef TDEBUG1
00387     CkPrintf("TMRC2D: [%d] Update edge %d replaced element %d with %d\n", cid,
00388          idx, ov.idx, nv.idx);
00389 #endif
00390   if (theEdges[idx].getBoundary() < b)
00391     theEdges[idx].setBoundary(b);
00392   if ((theEdges[idx].getBoundary() > 0) && (b > 0))
00393     CkPrintf("TMRC2D: [%d] WARNING! chunk::updateElement collapsed two different boundaries together on one edge.\n", cid);
00394   releaseLock();
00395 }
00396 
00397 void chunk::updateElementEdge(int idx, objRef oldval, objRef newval)
00398 {
00399   edgeRef ov, nv;
00400   ov.idx = oldval.idx;   ov.cid = oldval.cid; 
00401   nv.idx = newval.idx;   nv.cid = newval.cid; 
00402   accessLock();
00403   theElements[idx].update(ov, nv);
00404   releaseLock();
00405 }
00406 
00407 void chunk::updateReferences(int idx, objRef oldval, objRef newval)
00408 {
00409   CkPrintf("TMRC2D: [%d] WARNING! chunk::updateReferences called but not implemented!\n", cid);
00410   
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 }
00421 
00422 doubleMsg *chunk::getArea(int n)
00423 {
00424   doubleMsg *dm = new doubleMsg;
00425   accessLock();
00426   dm->aDouble = theElements[n].getArea();
00427   releaseLock();
00428   return dm;
00429 }
00430 
00431 void chunk::resetEdge(int n)
00432 {
00433   accessLock();
00434   theEdges[n].reset();
00435   releaseLock();
00436 }
00437 
00438 refMsg *chunk::getNbr(int idx, objRef aRef)
00439 {
00440   refMsg *rm = new refMsg;
00441   elemRef er, ar;
00442   ar.cid = aRef.cid; ar.idx = aRef.idx;
00443   accessLock();
00444   er = theEdges[idx].getNot(ar);
00445   releaseLock();
00446   rm->aRef = er;
00447   return rm;
00448 }
00449 
00450 void chunk::setTargetArea(int idx, double aDouble)
00451 {
00452   accessLock();
00453   theElements[idx].setTargetArea(aDouble);
00454   releaseLock();
00455   if (!refineInProgress) {
00456     refineInProgress = 1;
00457     mesh[cid].refiningElements();
00458   }
00459 }
00460 
00461 void chunk::resetTargetArea(int idx, double aDouble)
00462 {
00463   accessLock();
00464   theElements[idx].resetTargetArea(aDouble);
00465   releaseLock();
00466 }
00467 
00468 void chunk::reportPos(int idx, double x, double y)
00469 {
00470   node z(x, y);
00471   accessLock();
00472   theNodes[idx].reportPos(z);
00473   releaseLock();
00474 }
00475 
00476 
00477 
00478 void chunk::accessLock()
00479 {
00480   while (meshExpandFlag && (meshLock==0))
00481     CthYield();
00482   meshLock--;
00483 }
00484 
00485 void chunk::releaseLock()
00486 {
00487   meshLock++;
00488 }
00489 
00490 void chunk::adjustFlag()
00491 {
00492   meshExpandFlag = 1;
00493 }
00494 
00495 void chunk::adjustLock()
00496 {
00497   while (meshLock != 0)
00498     CthYield();
00499   meshLock = 1;
00500 }
00501 
00502 void chunk::adjustRelease()
00503 {
00504   meshLock = meshExpandFlag = 0;
00505 }
00506 
00507 void chunk::allocMesh(int nEl)
00508 {
00509   int i;
00510   sizeElements = nEl * 2;
00511   sizeNodes = sizeEdges = sizeElements * 3;
00512   elementSlots = nEl;
00513   firstFreeElement = nEl;
00514   theElements.resize(sizeElements);
00515   theNodes.resize(sizeNodes);
00516   theEdges.resize(sizeEdges);
00517   for (i=0; i<sizeElements; i++)
00518     theElements[i].set(); 
00519   for (i=0; i<sizeNodes; i++) {
00520     theNodes[i].present = 0; 
00521     theEdges[i].present = 0; 
00522   }
00523   conn = new int[3*numGhosts];
00524   gid = new int[2*numGhosts];
00525 }
00526 
00527 void chunk::adjustMesh()
00528 {
00529   int i;
00530   if (sizeElements <= elementSlots+100) {
00531     adjustFlag();
00532     adjustLock();
00533 #ifdef TDEBUG1
00534     CkPrintf("TMRC2D: [%d] Adjusting mesh size...\n", cid);
00535 #endif
00536     sizeElements += 100;
00537     sizeEdges += 300;
00538     sizeNodes += 300;
00539     theElements.resize(sizeElements);
00540     theEdges.resize(sizeEdges);
00541     theNodes.resize(sizeNodes);
00542     for (i=elementSlots; i<sizeElements; i++)
00543       theElements[i].present = 0;
00544     for (i=nodeSlots; i<sizeNodes; i++)
00545       theNodes[i].present = 0;
00546     for (i=edgeSlots; i<sizeEdges; i++)
00547       theEdges[i].present = 0;
00548 #ifdef TDEBUG1
00549     CkPrintf("TMRC2D: [%d] Done adjusting mesh size...\n", cid);
00550 #endif
00551     adjustRelease();
00552   }
00553 }
00554 
00555 intMsg *chunk::addNode(node n, int b1, int b2, int internal)
00556 {
00557   intMsg *im = new intMsg;
00558   im->anInt = firstFreeNode;
00559   theNodes[firstFreeNode] = n;
00560   theNodes[firstFreeNode].present = 1;
00561   if ((b1 == 0) || (b2 == 0) || internal) theNodes[firstFreeNode].boundary = 0;
00562   else if (b1 < b2) theNodes[firstFreeNode].boundary = b1; 
00563   else theNodes[firstFreeNode].boundary = b2;
00564   numNodes++;
00565   firstFreeNode++;
00566   if (firstFreeNode-1 == nodeSlots)  nodeSlots++;
00567   else  while (theNodes[firstFreeNode].isPresent()) firstFreeNode++;
00568   return im;
00569 }
00570 
00571 edgeRef chunk::addEdge(int n1, int n2, int b)
00572 {
00573 #ifdef TDEBUG1  
00574   CkPrintf("TMRC2D: [%d] Adding edge %d between nodes %d and %d\n", 
00575        cid, numEdges, n1, n2);
00576 #endif
00577   edgeRef eRef(cid, firstFreeEdge);
00578   theEdges[firstFreeEdge].set(firstFreeEdge, cid, this);
00579   theEdges[firstFreeEdge].reset();
00580   theEdges[firstFreeEdge].setNodes(n1, n2);
00581   theEdges[firstFreeEdge].setBoundary(b);
00582   numEdges++;
00583   firstFreeEdge++;
00584   if (firstFreeEdge-1 == edgeSlots)  edgeSlots++;
00585   else  while (theEdges[firstFreeEdge].isPresent()) firstFreeEdge++;
00586   return eRef;
00587 }
00588 
00589 edgeRef chunk::addEdge(int n1, int n2, const int *edgeBounds, const int *edgeConn, int nEdges)
00590 {
00591   int i=0;
00592 #ifdef TDEBUG1  
00593   CkPrintf("TMRC2D: [%d] Adding edge %d between nodes %d and %d\n", 
00594        cid, nEdges, n1, n2);
00595 #endif
00596   while (i<nEdges && !(n1==edgeConn[2*i] && n2==edgeConn[2*i+1]) || (n2==edgeConn[2*i] && n1==edgeConn[2*i+1]))
00597     i++;
00598   theEdges[i].set(i, cid, this);
00599   theEdges[i].reset();
00600   theEdges[i].setNodes(n1, n2);
00601   theEdges[i].setBoundary(edgeBounds[i]);
00602   edgeRef eRef(cid, i);
00603   numEdges++;
00604   while (theEdges[firstFreeEdge].isPresent()) firstFreeEdge++;
00605   return eRef;
00606 }
00607 
00608 
00609 elemRef chunk::addElement(int n1, int n2, int n3)
00610 {
00611   elemRef eRef(cid, firstFreeElement);
00612   theElements[firstFreeElement].set(cid, firstFreeElement, this);
00613   theElements[firstFreeElement].set(n1, n2, n3);
00614   theElements[firstFreeElement].calculateArea();
00615   numElements++;
00616   firstFreeElement++;
00617   if (firstFreeElement-1 == elementSlots)  elementSlots++;
00618   else  while (theElements[firstFreeElement].isPresent()) firstFreeElement++;
00619   if (!refineInProgress) {
00620     refineInProgress = 1;
00621     mesh[cid].refiningElements();
00622   }
00623   return eRef;
00624 }
00625 
00626 elemRef chunk::addElement(int n1, int n2, int n3,
00627               edgeRef er1, edgeRef er2, edgeRef er3)
00628 {
00629 #ifdef TDEBUG1
00630   CkPrintf("TMRC2D: [%d] New element %d added with nodes %d, %d and %d\n", 
00631        cid, firstFreeElement, n1, n2, n3);
00632 #endif
00633   elemRef eRef(cid, firstFreeElement);
00634   theElements[firstFreeElement].set(cid, firstFreeElement, this);
00635   theElements[firstFreeElement].set(n1, n2, n3, er1, er2, er3);
00636   theElements[firstFreeElement].calculateArea();
00637   numElements++;
00638   firstFreeElement++;
00639   if (firstFreeElement-1 == elementSlots)  elementSlots++;
00640   else  while (theElements[firstFreeElement].isPresent()) firstFreeElement++;
00641   if (!refineInProgress) {
00642     refineInProgress = 1;
00643     mesh[cid].refiningElements();
00644   }
00645   return eRef;
00646 }
00647 
00648 void chunk::removeNode(int n)
00649 {
00650 #ifdef TDEBUG1
00651   CkPrintf("TMRC2D: [%d] Removing node %d\n", cid, n);
00652 #endif
00653   if (theNodes[n].present) {
00654     theNodes[n].present = 0;
00655     theNodes[n].reset();
00656     if (n < firstFreeNode) firstFreeNode = n;
00657     else if ((n == firstFreeNode) && (firstFreeNode == nodeSlots)) {
00658       firstFreeNode--; nodeSlots--;
00659     }
00660     numNodes--;
00661   }
00662 }
00663 
00664 void chunk::removeEdge(int n)
00665 {
00666 #ifdef TDEBUG1
00667   CkPrintf("TMRC2D: [%d] Removing edge %d\n", cid, n);
00668 #endif
00669   if (theEdges[n].present) {
00670     theEdges[n].reset();
00671     theEdges[n].present = 0;
00672     theEdges[n].elements[0].reset();
00673     theEdges[n].elements[1].reset();
00674     theEdges[n].nodes[0] = theEdges[n].nodes[1] = -1;
00675     if (n < firstFreeEdge) firstFreeEdge = n;
00676     else if ((n == firstFreeEdge) && (firstFreeEdge == edgeSlots)) {
00677       firstFreeEdge--; edgeSlots--;
00678     }
00679     numEdges--;
00680   }
00681   else {
00682     CkPrintf("TMRC2D: [%d] WARNING: chunk::removeEdge(%d): edge not present\n", cid, n);
00683   } 
00684 }
00685 
00686 void chunk::removeElement(int n)
00687 {
00688 #ifdef TDEBUG1
00689   CkPrintf("TMRC2D: [%d] Removing element %d\n", cid, n);
00690 #endif
00691   if (theElements[n].present) {
00692     theElements[n].present = 0;
00693     theElements[n].clear();
00694     if (n < firstFreeElement) firstFreeElement = n;
00695     else if ((n == firstFreeElement) && (firstFreeElement == elementSlots)) {
00696       firstFreeElement--; elementSlots--;
00697     }
00698     numElements--;
00699   }
00700   else {
00701     CkPrintf("TMRC2D: [%d] WARNING: chunk::removeElement(%d): element not present\n", cid, n);
00702   } 
00703 }
00704 
00705 
00706 
00707 void chunk::print()
00708 {
00709   accessLock();
00710   debug_print(debug_counter);
00711   debug_counter++;
00712   releaseLock();
00713 }
00714 
00715 void chunk::debug_print(int c)
00716 {
00717   FILE *fp;
00718   char filename[30];
00719   int i, j;
00720   node n;
00721 
00722   memset(filename, 0, 30);
00723   sprintf(filename, "mesh_debug_%d.%d", cid, c);
00724   fp = fopen(filename, "w");
00725 
00726   fprintf(fp, "%d %d\n", cid, numElements);
00727   for (i=0; i<elementSlots; i++) {
00728     if (theElements[i].isPresent()) {
00729       for (j=0; j<3; j++) {
00730     n = theNodes[theElements[i].getNode(j)];
00731     fprintf(fp, "%f %f   ", n.X(), n.Y());
00732       }
00733       fprintf(fp, "%d %f\n", i, theElements[i].getTargetArea());
00734       for (j=0; j<3; j++) {
00735     fprintf(fp, "0  ");
00736       }
00737       fprintf(fp, "\n");
00738     }
00739   }
00740   fclose(fp);
00741 }
00742 
00743 void chunk::out_print()
00744 {
00745   FILE *fp;
00746   char filename[30];
00747   int i;
00748 
00749   memset(filename, 0, 30);
00750   sprintf(filename, "mesh.out");
00751   fp = fopen(filename, "a");
00752 
00753   if (cid == 0)
00754     fprintf(fp, "%d\n", numChunks);
00755   fprintf(fp, " %d %d %d %d\n", cid, numNodes, numEdges, numElements);
00756   for (i=0; i<numNodes; i++)
00757     fprintf(fp, "    %f %f\n", theNodes[i].X(), theNodes[i].Y());
00758   for (i=0; i<numEdges; i++) {
00759     fprintf(fp, " %d %d ", theEdges[i].elements[0].idx, theEdges[i].elements[0].cid);
00760     fprintf(fp, " %d %d\n", theEdges[i].elements[1].idx, theEdges[i].elements[1].cid);
00761   }
00762   for (i=0; i<numElements; i++) {
00763     if (theElements[i].isPresent()) {
00764       fprintf(fp, " %d ", theElements[i].nodes[0]);
00765       fprintf(fp, " %d ", theElements[i].nodes[1]);
00766       fprintf(fp, " %d ", theElements[i].nodes[2]);
00767       fprintf(fp, "   ");
00768       fprintf(fp, " %d %d ", theElements[i].edges[0].idx, theElements[i].edges[0].cid);
00769       fprintf(fp, " %d %d ", theElements[i].edges[1].idx, theElements[i].edges[1].cid);
00770       fprintf(fp, " %d %d\n", theElements[i].edges[2].idx, theElements[i].edges[2].cid);
00771     }
00772   }
00773   fprintf(fp, "\n");
00774   fclose(fp);
00775 }
00776 
00777 void chunk::updateNodeCoords(int nNode, double *coord, int nEl)
00778 {
00779   int i;
00780 #ifdef TDEBUG2
00781   CkPrintf("TMRC2D: [%d] updateNodeCoords...\n", cid);
00782 #endif
00783   if (first) {
00784     CkWaitQD();
00785     first = 0;
00786   }
00787 #ifdef TDEBUG3
00788   CkPrintf("TMRC2D: [%d] In updateNodeCoords after CkWaitQD: edges sent=%d edge recvd=%d\n", cid, edgesSent, edgesRecvd);
00789 #endif
00790 #ifdef TDEBUG1
00791   sanityCheck(); 
00792   validCheck();
00793 #endif
00794   
00795   if (nEl != numElements) {
00796     CkPrintf("TMRC2D: [%d] ERROR: nEl=%d passed in updateNodeCoords does not match TMRC2D numElements=%d!\n", cid, nEl, numElements);
00797     CkAssert(nEl == numElements);
00798   }
00799   if (nNode != numNodes) {
00800     CkPrintf("TMRC2D: [%d] ERROR: nNode=%d passed in updateNodeCoords does not match TMRC2D numNodes=%d!\n", cid, nNode, numNodes);
00801     CkAssert(nNode == numNodes);
00802   } 
00803   
00804   for (i=0; i<nodeSlots; i++)
00805     if (theNodes[i].isPresent()) {
00806       theNodes[i].set(coord[2*i], coord[2*i + 1]);
00807 #ifdef TDEBUG3      
00808       if (theNodes[i].boundary) {
00809     CkPrintf("TMRC2D: [%d] Node %d on boundary!\n", cid, i);
00810       } 
00811 #endif
00812     }
00813   
00814   for (i=0; i<elementSlots; i++) 
00815     if (theElements[i].isPresent())  theElements[i].calculateArea();
00816 #ifdef TDEBUG1
00817   sanityCheck(); 
00818   dump();
00819 #endif
00820 #ifdef TDEBUG2
00821   CkPrintf("TMRC2D: [%d] updateNodeCoords DONE.\n", cid);
00822 #endif
00823 }
00824 
00825 void chunk::multipleRefine(double *desiredArea, refineClient *client)
00826 {
00827   int i;
00828   double area;
00829 #ifdef TDEBUG2
00830   CkPrintf("TMRC2D: [%d] multipleRefine....\n", cid);
00831 #endif
00832 #ifdef TDEBUG1
00833   sanityCheck(); 
00834 #endif
00835   CmiMemoryCheck();
00836   theClient = client; 
00837   
00838   if (refineStack) delete [] refineStack;
00839   refineStack=new elemHeap[numElements];
00840   if (refineElements) delete [] refineElements;
00841   refineElements = new elemHeap[numElements+1];
00842   for (i=0; i<elementSlots; i++) { 
00843     if (theElements[i].isPresent()) {
00844       area = theElements[i].getArea();
00845       if (area == 0.0) {
00846     CkPrintf("Element[%d] has area %1.10e!\n", i, area);
00847       }
00848       
00849       if (desiredArea[i] < REFINE_PRECISION*area) {
00850     theElements[i].resetTargetArea(desiredArea[i]);
00851     double qFactor=theElements[i].getAreaQuality();
00852     Insert(i, qFactor, 0);
00853     CkPrintf("Element[%d] has area %1.10e target %1.10e qFactor %1.10e\n", i, area, desiredArea[i], qFactor);
00854 #ifdef TDEBUG2
00855     CkPrintf("TMRC2D: [%d] Setting target on element %d to %1.10e with largeEdge %1.10e\n", cid, i, desiredArea[i], qFactor);
00856 #endif
00857       }
00858     }
00859   }
00860   
00861   if (!refineInProgress) {
00862    refineInProgress = 1;
00863    mesh[cid].refiningElements();
00864   }
00865 #ifdef TDEBUG2
00866   CkPrintf("TMRC2D: [%d] multipleRefine DONE.\n", cid);
00867 #endif
00868   CkWaitQD();
00869   CmiMemoryCheck();
00870 }
00871 
00872 void chunk::multipleCoarsen(double *desiredArea, refineClient *client)
00873 {
00874   int i;
00875   double precThrshld, area, qFactor;
00876   CmiMemoryCheck();
00877 #ifdef TDEBUG2
00878   CkPrintf("TMRC2D: [%d] multipleCoarsen....\n", cid);
00879 #endif
00880 #ifdef TDEBUG1
00881   sanityCheck(); 
00882 #endif
00883   theClient = client; 
00884   if (coarsenElements) delete [] coarsenElements;
00885   coarsenElements = new elemHeap[numElements+1];
00886   coarsenElements[0].len=-2.0;
00887   coarsenElements[0].elID=-1;
00888   for (i=0; i<elementSlots; i++) { 
00889     if (theElements[i].isPresent()) {
00890       area = theElements[i].getArea();
00891       if (area == 0.0) {
00892     CkPrintf("Element[%d] has area %1.10e!\n", i, area);
00893       }
00894       double shortEdgeLen, angle;
00895       shortEdgeLen = theElements[i].getShortestEdge(&angle);
00896       qFactor = theElements[i].getAreaQuality();
00897       theElements[i].nonCoarsenCount = 0;
00898       
00899       theElements[i].resetTargetArea(desiredArea[i]);
00900       if ((desiredArea[i]*COARSEN_PRECISION > area) || (area == 0.0) || 
00901       (qFactor<QUALITY_MIN)) {
00902     Insert(i, shortEdgeLen*qFactor, 1);
00903     CkPrintf("Element[%d] has area %1.10e target %1.10e qFactor %1.10e\n", i, area, desiredArea[i], qFactor);
00904 #ifdef TDEBUG2
00905     CkPrintf("TMRC2D: [%d] Setting target on element %d to %1.10e with shortEdge %1.10e\n", cid, i, desiredArea[i], qFactor);
00906 #endif
00907       }
00908     }
00909   }
00910   
00911   
00912   if (!coarsenInProgress) {
00913    coarsenInProgress = 1;
00914    mesh[cid].coarseningElements();
00915   }
00916 #ifdef TDEBUG2
00917   CkPrintf("TMRC2D: [%d] multipleCoarsen DONE.\n", cid);
00918 #endif
00919   CkWaitQD();
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928 
00929 
00930   CmiMemoryCheck();
00931 }
00932 
00933 void chunk::newMesh(int meshID_,int nEl, int nGhost, const int *conn_, 
00934             const int *gid_, int nnodes, const int *boundaries, int nEdges, 
00935             const int *edgeConn, const int *edgeBounds, int idxOffset)
00936 {
00937   int i, j;
00938 #ifdef TDEBUG2
00939   CkPrintf("TMRC2D: [%d] In newMesh...\n", cid);
00940 #endif
00941   meshID = meshID_;
00942 
00943   meshPtr = FEM_Mesh_lookup(meshID, "chunk::newMesh");
00944   numElements=nEl;
00945   numGhosts = nGhost;
00946   allocMesh(nEl);
00947   int *conn = new int[3*numGhosts];
00948   int *gid = new int[2*numGhosts];
00949 
00950   
00951   for (i=0; i<numElements; i++) {
00952     int nodes[3];
00953     edgeRef edges[3];
00954      for (j=0; j<3; j++) {
00955       int c=conn_[i*3+j]-idxOffset;
00956       conn[i*3 + j] = c;
00957       nodes[j] = c;
00958       edges[j].reset();
00959      }
00960     theElements[i].set(cid, i, this);
00961     theElements[i].set(nodes, edges);
00962     gid[i*2] = cid;
00963     gid[i*2 + 1] = i;
00964   }
00965 
00966   
00967   for (i=nEl; i<nGhost; i++) {
00968     for (j=0; j<3; j++)
00969       conn[i*3+j] = conn_[i*3+j]-idxOffset;
00970     gid[i*2+0] = gid_[i*2]-idxOffset;
00971     gid[i*2+1] = gid_[i*2 + 1]-idxOffset;
00972   }
00973 
00974   MPI_Barrier(MPI_COMM_WORLD);
00975   
00976   if (boundaries) {
00977     numNodes = nnodes;
00978 #ifdef TDEBUG1
00979     CkPrintf("TMRC2D: [%d] Received non-NULL boundaries... adding...\n", cid);
00980 #endif
00981     for (i=0; i<numNodes; i++) {
00982       theNodes[i].boundary = boundaries[i];
00983 #ifdef TDEBUG3
00984       if (theNodes[i].boundary) 
00985     CkPrintf("TMRC2D: [%d] Node %d has boundary %d.\n", cid, i, theNodes[i].boundary);
00986 #endif
00987     }
00988     deriveEdges(conn, gid, edgeBounds, edgeConn, nEdges);
00989     CkAssert(nnodes == numNodes);
00990   }
00991   else {
00992     deriveEdges(conn, gid, edgeBounds, edgeConn, nEdges);
00993     CkAssert(nnodes == numNodes);
00994     deriveBoundaries(conn, gid);
00995   }
00996   delete[] conn;
00997   delete[] gid;
00998 #ifdef TDEBUG2
00999   CkPrintf("TMRC2D: [%d] newMesh DONE; chunk created with %d elements.\n", 
01000        cid, numElements);
01001 #endif
01002 }
01003 
01004 void chunk::deriveEdges(int *conn, int *gid, const int *edgeBounds, const int *edgeConn, int nEdges)
01005 {
01006   
01007   
01008   int i, j, n1localIdx, n2localIdx;
01009   edgeRef newEdge;
01010 
01011   deriveNodes(); 
01012 #ifdef TDEBUG2
01013   CkPrintf("TMRC2D: [%d] Deriving edges...\n", cid);
01014 #endif
01015   for (i=0; i<elementSlots; i++) {
01016 #ifdef TDEBUG3
01017     CkPrintf("TMRC2D: [%d] Deriving edges for element %d...\n", cid, i);
01018 #endif
01019     elemRef myRef(cid,i);
01020     for (j=0; j<3; j++) {
01021       n1localIdx = j;
01022       n2localIdx = (j+1) % 3;
01023 #ifdef TDEBUG3
01024     CkPrintf("TMRC2D: [%d] Deriving edges for element %d between %d,%d (real nodes %d,%d)...\n", cid, i, n1localIdx, n2localIdx, theElements[i].nodes[n1localIdx], theElements[i].nodes[n2localIdx]);
01025 #endif
01026       
01027       if (theElements[i].edges[j] == nullRef) { 
01028     
01029 #ifdef TDEBUG3
01030     CkPrintf("TMRC2D: [%d] Edge between nodes %d,%d doesn't exist yet...\n", cid, theElements[i].nodes[n1localIdx], theElements[i].nodes[n2localIdx]);
01031 #endif
01032     elemRef nbrRef;
01033     int edgeIdx = getNbrRefOnEdge(theElements[i].nodes[n1localIdx], 
01034                       theElements[i].nodes[n2localIdx], 
01035                       conn, numGhosts, gid, i, &nbrRef);
01036     FEM_Node *mNodes = &(meshPtr->node);
01037     int nIdx1 = theElements[i].nodes[n1localIdx];
01038     int nIdx2 = theElements[i].nodes[n2localIdx];
01039     if ((theNodes[nIdx1].boundary < theNodes[nIdx2].boundary) && 
01040         (theNodes[nIdx1].boundary != 0))    {
01041       theNodes[nIdx2].fixed = 1;
01042 #ifdef TDEBUG2
01043       CkPrintf("TMRC2D: [%d] Corner detected, fixing node %d\n", 
01044            cid, nIdx2);
01045 #endif
01046       FEM_Comm_Rec *nRec = (FEM_Comm_Rec*)(mNodes->shared.getRec(nIdx2));
01047       if (nRec) {
01048         int count = nRec->getShared();
01049         for (i=0; i<count; i++) {
01050           mesh[nRec->getChk(i)].fixNode(nRec->getIdx(i), cid);
01051         }
01052       }
01053     }
01054     if ((theNodes[nIdx2].boundary < theNodes[nIdx1].boundary) && 
01055         (theNodes[nIdx2].boundary != 0)) {
01056       theNodes[nIdx1].fixed = 1;
01057 #ifdef TDEBUG2
01058       CkPrintf("TMRC2D: [%d] Corner detected, fixing node %d\n", 
01059            cid, nIdx1);
01060 #endif
01061       FEM_Comm_Rec *nRec = (FEM_Comm_Rec*)(mNodes->shared.getRec(nIdx1));
01062       if (nRec) {
01063         int count = nRec->getShared();
01064         for (i=0; i<count; i++) {
01065           mesh[nRec->getChk(i)].fixNode(nRec->getIdx(i), cid);
01066         }
01067       }
01068     }
01069     if (edgeLocal(myRef, nbrRef)) { 
01070       if (!edgeBounds)
01071         newEdge = addEdge(nIdx1, nIdx2, 0);
01072       else
01073         newEdge = addEdge(nIdx1, nIdx2, edgeBounds, edgeConn, nEdges);
01074 #ifdef TDEBUG3
01075       CkPrintf("TMRC2D: [%d] New edge (%d,%d) added between nodes %d and %d and elements %d and %d on chunk %d\n", cid, newEdge.cid, newEdge.idx, nIdx1, nIdx2, i, nbrRef.idx, nbrRef.cid);
01076 #endif
01077       
01078       theEdges[newEdge.idx].update(nullRef, myRef);
01079       theEdges[newEdge.idx].update(nullRef, nbrRef);
01080       
01081       theElements[i].set(j, newEdge);
01082       
01083       if (nbrRef.cid==cid) 
01084         theElements[nbrRef.idx].set(edgeIdx, newEdge);
01085       else if (nbrRef.cid != -1) { 
01086         mesh[nbrRef.cid].addRemoteEdge(nbrRef.idx, edgeIdx, newEdge);
01087         edgesSent++;
01088       }
01089     }
01090         else { 
01091 #ifdef TDEBUG3
01092       CkPrintf("TMRC2D: [%d] Edge between nodes %d,%d to be created elsewhere...\n", cid, theElements[i].nodes[n1localIdx], theElements[i].nodes[n2localIdx]);
01093 #endif
01094       
01095       theElements[i].edges[j].idx = theElements[i].edges[j].cid = -2;
01096     }
01097       }
01098 #ifdef TDEBUG3
01099       else { 
01100     CkPrintf("TMRC2D: [%d] Edge between nodes %d,%d exists at %d\n", cid, theElements[i].nodes[n1localIdx], theElements[i].nodes[n2localIdx], theElements[i].edges[j].idx);
01101       }
01102 #endif
01103     }
01104   }
01105   nodeSlots = numNodes;
01106   firstFreeNode = numNodes;
01107   edgeSlots = numEdges;
01108   firstFreeEdge = numEdges;
01109 #ifdef TDEBUG2
01110   CkPrintf("TMRC2D: [%d] Done deriving edges...\n", cid);
01111 #endif
01112 }
01113 
01114 void chunk::deriveNodes()
01115 {
01116   int i, j;
01117   int aNode;
01118 
01119 #ifdef TDEBUG2
01120   CkPrintf("TMRC2D: [%d] Deriving nodes...\n", cid);
01121 #endif
01122   numNodes = 0;
01123   for (i=0; i<elementSlots; i++) {
01124     for (j=0; j<3; j++) {
01125       aNode = theElements[i].nodes[j];
01126       CkAssert(aNode > -1);
01127       if ((aNode + 1) > numNodes)
01128     numNodes = aNode + 1;
01129       theNodes[aNode].present = 1;
01130     }
01131   }
01132 #ifdef TDEBUG3
01133   CkPrintf("TMRC2D: [%d] NumNodes = %d; max node idx = %d\n", 
01134        cid, numNodes, numNodes-1);
01135 #endif
01136 #ifdef TDEBUG2
01137   CkPrintf("TMRC2D: [%d] Done deriving nodes.\n", cid);
01138 #endif
01139 }
01140 
01141 int chunk::edgeLocal(elemRef e1, elemRef e2)
01142 {
01143   return ((e1.cid==-1 || e2.cid==-1) || (e1.cid > e2.cid) ||
01144       ((e1.cid == e2.cid) && (e1.idx < e2.idx)));
01145 }
01146 
01147 int chunk::getNbrRefOnEdge(int n1, int n2, int *conn, int nGhost, int *gid, 
01148                int idx, elemRef *er)
01149 {
01150   int i, e;
01151   er->set(-1, -1);
01152   for (i=0; i<nGhost; i++) {
01153     if (i != idx) {
01154       if ((e = hasEdge(n1, n2, conn, i)) != -1) {
01155     er->set(gid[i*2], gid[i*2+1]);
01156     return e;
01157       }
01158     }
01159   }
01160   return -1;
01161 }
01162 
01163 int chunk::hasEdge(int n1, int n2, int *conn, int idx) 
01164 {
01165   int i, j;
01166   for (i=0; i<3; i++) {
01167     j = (i+1) % 3;
01168     if (((conn[idx*3+i] == n1) && (conn[idx*3+j] == n2)) ||
01169     ((conn[idx*3+j] == n1) && (conn[idx*3+i] == n2)))
01170       return i;
01171   }
01172   return -1;
01173 }
01174 
01175 void chunk::deriveBoundaries(int *conn, int *gid)
01176 {
01177   int edgeIdx;
01178   elemRef nbrRef;
01179   CkPrintf("TMRC2D: [%d] WARNING! Null list of boundary flags passed to newMesh...\n ...I hope you didn't want coarsening to work!\n", cid);
01180   CkPrintf("TMRC2D: [%d] WARNING! Attempting to derive single boundary information -- corners will be ignored!\n", cid);
01181   for (int i=0; i<numElements; i++) {
01182     for (int j=0; j<3; j++) {
01183       edgeIdx = getNbrRefOnEdge(theElements[i].nodes[j], 
01184                 theElements[i].nodes[(j+1)%3], 
01185                 conn, numGhosts, gid, i, &nbrRef); 
01186       if ((nbrRef.idx == -1) && (nbrRef.cid == -1)) {
01187 #ifdef TDEBUG2
01188     CkPrintf("TMRC2D: [%d] Marking node %d as a boundary.\n", 
01189          cid, theElements[i].nodes[j]);
01190     CkPrintf("TMRC2D: [%d] Marking node %d as a boundary.\n", 
01191          cid, theElements[i].nodes[(j+1)%3]);
01192 #endif
01193     theNodes[theElements[i].nodes[j]].boundary = 1;
01194     theNodes[theElements[i].nodes[(j+1)%3]].boundary = 1;
01195       }
01196     }
01197   }
01198 }
01199 
01200 void chunk::tweakMesh()
01201 {
01202   CkPrintf("TMRC2D: [%d] WARNING! chunk::tweakMesh called but not implemented!\n", cid);
01203   
01204 
01205 
01206 
01207 }
01208 
01209 void chunk::improveChunk()
01210 {
01211   CkPrintf("TMRC2D: [%d] WARNING! chunk::improveChunk called but not implemented!\n", cid);
01212   
01213 
01214 
01215 
01216 
01217 
01218 
01219 }
01220 
01221 void chunk::improve()
01222 {
01223   CkPrintf("TMRC2D: [%d] WARNING! chunk::improve called but not implemented!\n", cid);
01224   
01225 
01226 
01227 
01228 
01229 
01230 }
01231 
01232 void chunk::sanityCheck(void)
01233 {
01234   CkPrintf("TMRC2D: [%d] running sanity check...\n", cid);
01235   int i;
01236   if (numElements<0 || (int)theElements.size()<numElements)
01237         CkAbort("sc-> TMRC2D: numElements or vector size insane!");
01238   if (numEdges<0 || (int)theEdges.size()<numEdges)
01239         CkAbort("sc-> TMRC2D: numEdges or vector size insane!");
01240   if (numNodes<0 || (int)theNodes.size()<numNodes)
01241         CkAbort("sc-> TMRC2D: numNodes or vector size insane!");
01242   i=0; 
01243   while (theElements[i].isPresent()) i++;
01244   CkAssert(firstFreeElement == i);
01245   i=0; 
01246   while (theEdges[i].isPresent()) i++;
01247   CkAssert(firstFreeEdge == i);
01248   i=0; 
01249   while (theNodes[i].isPresent()) i++;
01250   CkAssert(firstFreeNode == i);
01251   for (i=0; i<elementSlots; i++) 
01252     if (theElements[i].isPresent())
01253       theElements[i].sanityCheck(this, elemRef(cid,i), nodeSlots);
01254   for (i=0; i<edgeSlots; i++)
01255     if (theEdges[i].isPresent())
01256       theEdges[i].sanityCheck(this, edgeRef(cid,i));
01257   for (i=0; i<nodeSlots; i++)
01258     if (theNodes[i].isPresent())
01259       theNodes[i].sanityCheck(cid, i);
01260   CkPrintf("TMRC2D: [%d] sanity check PASSED.\n", cid);
01261 }
01262 
01263 void chunk::dump()
01264 {
01265   int i;
01266   CkPrintf("TMRC2D: [%d] has %d elements, %d nodes and %d edges:\n", 
01267        cid, numElements, numNodes, numEdges);
01268   for (i=0; i<elementSlots; i++) 
01269     if (theElements[i].isPresent()){
01270       CkPrintf("TMRC2D: [%d] Element %d nodes %d %d %d edges [%d,%d] [%d,%d] [%d,%d]\n", cid, i, theElements[i].nodes[0], theElements[i].nodes[1], theElements[i].nodes[2], theElements[i].edges[0].cid, theElements[i].edges[0].idx, theElements[i].edges[1].cid, theElements[i].edges[1].idx, theElements[i].edges[2].cid, theElements[i].edges[2].idx);
01271         }   
01272   for (i=0; i<nodeSlots; i++)
01273     if (theNodes[i].isPresent()) {
01274       CkPrintf("TMRC2D: [%d] Node %d has coordinates (%f,%f)\n", 
01275            cid, i, theNodes[i].X(), theNodes[i].Y());
01276     }        
01277   for (i=0; i<edgeSlots; i++)
01278     if (theEdges[i].isPresent()) {
01279       CkPrintf("TMRC2D: [%d] Edge %d has nodes %d %d elements [%d,%d] [%d,%d]\n", cid, 
01280            i, theEdges[i].nodes[0], theEdges[i].nodes[1], theEdges[i].elements[0].cid, theEdges[i].elements[0].idx, 
01281            theEdges[i].elements[1].cid, theEdges[i].elements[1].idx);
01282     }        
01283 }
01284 
01285 intMsg *chunk::lockChunk(int lhc, int lhi, double prio)
01286 {
01287   intMsg *im = new intMsg;
01288   im->anInt = lockLocalChunk(lhc, lhi, prio);
01289   return im;
01290 }
01291 
01292 int chunk::lockLocalChunk(int lhc, int lhi, double prio)
01293 { 
01294   
01295   
01296   if (!lock) { 
01297     
01298     
01299     removeLock(lhc, lhi);
01300     insertLock(lhc, lhi, prio);
01301     if ((lockList->prio == prio) && (lockList->holderIdx == lhi)
01302     && (lockList->holderCid == lhc)) {
01303 #ifdef TDEBUG3
01304       CkPrintf("TMRC2D: [%d] LOCK chunk %d by %d on %d prio %.10f LOCKED(was %d[%don%d:%.10f])\n", CkMyPe(), cid, lhi, lhc, prio, lock, lockHolderIdx, lockHolderCid, lockPrio);
01305 #endif
01306       lock = 1; lockHolderCid = lhc; lockHolderIdx = lhi; lockPrio = prio; 
01307       
01308       lockList = lockList->next;
01309       return 1;
01310     }
01311     removeLock(lhc, lhi);
01312 #ifdef TDEBUG3
01313     CkPrintf("TMRC2D: [%d] LOCK chunk %d by %d on %d prio %.10f REFUSED (was %d[%don%d:%.10f])\n", CkMyPe(), cid, lhi, lhc, prio, lock, lockHolderIdx, lockHolderCid, lockPrio);
01314 #endif
01315     return 0;
01316   }
01317   else { 
01318     if ((prio == lockPrio) && (lhi == lockHolderIdx) && (lhc == lockHolderCid)) {
01319       
01320 #ifdef TDEBUG3
01321       CkPrintf("TMRC2D: [%d] LOCK chunk %d by %d on %d prio %.10f HELD (was %d[%don%d:%.10f])\n", CkMyPe(), cid, lhi, lhc, prio, lock, lockHolderIdx, lockHolderCid, lockPrio);
01322 #endif
01323       return 1;
01324     }
01325     if ((lhi == lockHolderIdx) && (lhc == lockHolderCid)) {
01326       CkPrintf("ERROR: lockholder %d on %d trying to relock with different prio! prio=%f newprio=%f\n", lhi, lhc, lockPrio, prio);
01327       CmiAssert(!((lhi == lockHolderIdx) && (lhc == lockHolderCid)));
01328     }
01329     
01330 
01331 
01332 
01333 
01334 
01335 
01336 
01337 
01338 
01339 
01340 #ifdef TDEBUG3
01341     CkPrintf("TMRC2D: [%d] LOCK chunk %d by %d on %d prio %.10f REFUSED (was %d[%don%d:%.10f])\n", CkMyPe(), cid, lhi, lhc, prio, lock, lockHolderIdx, lockHolderCid, lockPrio);
01342 #endif
01343     return 0;
01344   }
01345 }
01346 
01347 void chunk::insertLock(int lhc, int lhi, double prio)
01348 {
01349   prioLockStruct *newLock, *tmp;
01350   
01351   newLock = (prioLockStruct *)malloc(sizeof(prioLockStruct));
01352   newLock->prio = prio;
01353   newLock->holderIdx = lhi;
01354   newLock->holderCid = lhc;
01355   newLock->next = NULL;
01356   if (!lockList) lockList = newLock;
01357   else {
01358     if ((prio < lockList->prio) || 
01359     ((prio == lockList->prio) && (lhc < lockList->holderCid)) ||
01360     ((prio == lockList->prio) && (lhc == lockList->holderCid) && 
01361      (lhi < lockList->holderIdx))) {
01362       
01363       newLock->next = lockList;
01364       lockList = newLock;
01365     }
01366     else { 
01367       tmp = lockList;
01368       while (tmp->next) {
01369     if ((prio > tmp->next->prio) || 
01370         ((prio == tmp->next->prio) && (lhc > tmp->next->holderCid)) ||
01371         ((prio == tmp->next->prio) && (lhc == tmp->next->holderCid) &&
01372          (lhi > tmp->next->holderIdx))) 
01373       tmp = tmp->next;
01374     else break;
01375       }
01376       newLock->next = tmp->next;
01377       tmp->next = newLock;
01378     }
01379   }
01380 }
01381 
01382 void chunk::removeLock(int lhc, int lhi) 
01383 {
01384   prioLockStruct *tmp = lockList, *del;
01385   if (!lockList) return;
01386   if ((tmp->holderCid == lhc) && (tmp->holderIdx == lhi)) {
01387     lockList = lockList->next;
01388     free(tmp);
01389   }
01390   else {
01391     while (tmp->next && 
01392        ((tmp->next->holderCid != lhc) || (tmp->next->holderIdx != lhi)))
01393       tmp = tmp->next;
01394     if (tmp->next) {
01395       del = tmp->next;
01396       tmp->next = del->next;
01397       free(del);
01398     }
01399   }
01400 }
01401 
01402 void chunk::unlockChunk(int lhc, int lhi)
01403 {
01404   unlockLocalChunk(lhc, lhi);
01405 }
01406 
01407 void chunk::unlockLocalChunk(int lhc, int lhi)
01408 {
01409   if ((lockHolderIdx == lhi) && (lockHolderCid == lhc)) {
01410     
01411     
01412       lock = 0; 
01413       lockHolderIdx = -1;
01414       lockHolderCid = -1;
01415       lockPrio = -1.0;
01416 #ifdef TDEBUG3
01417       CkPrintf("TMRC2D: [%d] UNLOCK chunk %d by holder %d on %d\n", 
01418            CkMyPe(), cid, lhi, lhc);
01419 #endif
01420     
01421   }
01422   
01423 
01424 
01425 
01426 }
01427 
01428 void chunk::fixNode(int nIdx, int chkid)
01429 {
01430   FEM_Node *nodesPtr = &(meshPtr->node);
01431   const FEM_Comm_List *sharedList = &(nodesPtr->shared.getList(chkid));
01432   nIdx = (*sharedList)[nIdx];
01433 
01434   theNodes[nIdx].fixed = 1;
01435 #ifdef TDEBUG2
01436   CkPrintf("TMRC2D: [%d] Corner detected, fixing node %d\n", cid, nIdx);
01437 #endif
01438 }
01439 
01440 int chunk::joinCommLists(int nIdx, int shd, int *chk, int *idx, int *rChk,
01441              int *rIdx)
01442 {
01443   FEM_Node *theNodes = &(meshPtr->node);
01444   FEM_Comm_Rec *nodeRec=(FEM_Comm_Rec *)(theNodes->shared.getRec(nIdx));
01445   int nShared, count, chunk, index, found, i, j;
01446   if (nodeRec) nShared = nodeRec->getShared();
01447   else { 
01448     rChk = chk;
01449     rIdx = idx;
01450     return shd;
01451   }
01452   rChk = (int *)malloc((shd+nShared)*sizeof(int));
01453   rIdx = (int *)malloc((shd+nShared)*sizeof(int));
01454   for (i=0; i<shd; i++) {
01455     rChk[i] = chk[i];
01456     rIdx[i] = idx[i];
01457   }
01458   count = shd;
01459   for (i=0; i<nShared; i++) {
01460     chunk = nodeRec->getChk(i);
01461     for (j=0; j<shd; j++) {
01462       if (rChk[j] == chunk) { 
01463     found = 1;
01464     break;
01465       }
01466     }
01467     if (!found) {
01468       index = nodeRec->getIdx(i-shd);
01469       rChk[count] = chunk;
01470       rIdx[count] = index;
01471       count++;
01472     }
01473   }
01474   free(rChk);
01475   free(rIdx);
01476   return count;
01477 }
01478 
01479 void chunk::Insert(int eIdx, double len, int cFlag)
01480 {
01481   int i;
01482   if (cFlag) {
01483     i = ++coarsenHeapSize; 
01484     while ((coarsenElements[i/2].len>=len) && (i != 1))
01485     {
01486       coarsenElements[i].len=coarsenElements[i/2].len;
01487       coarsenElements[i].elID=coarsenElements[i/2].elID;  
01488       i/=2;                     
01489     }
01490     coarsenElements[i].elID=eIdx;
01491     coarsenElements[i].len=len; 
01492   }
01493   else {
01494     i = ++refineHeapSize; 
01495     while ((refineElements[i/2].len>=len) && (i != 1))
01496     {
01497       refineElements[i].len=refineElements[i/2].len;
01498       refineElements[i].elID=refineElements[i/2].elID;  
01499       i/=2;                     
01500     }
01501     refineElements[i].elID=eIdx;
01502     refineElements[i].len=len; 
01503   }
01504 }
01505 
01506 
01507 int chunk::Delete_Min(int cflag)
01508 {
01509   int Child, i, Min_ID; 
01510 
01511   if (cflag) {
01512     Min_ID=coarsenElements[1].elID;
01513     for (i=1; i*2 <= coarsenHeapSize-1; i=Child)
01514     {
01515       
01516       Child = i*2;       
01517       if (Child !=coarsenHeapSize)  
01518     if (coarsenElements[Child+1].len < coarsenElements[Child].len)
01519       Child++; 
01520 
01521       
01522       if (coarsenElements[coarsenHeapSize].len >= coarsenElements[Child].len){  
01523     coarsenElements[i].elID = coarsenElements[Child].elID;   
01524     coarsenElements[i].len = coarsenElements[Child].len;
01525       }
01526       else
01527          break; 
01528     }
01529     coarsenElements[i].elID = coarsenElements[coarsenHeapSize].elID;   
01530     coarsenElements[i].len = coarsenElements[coarsenHeapSize].len; 
01531     coarsenHeapSize--;
01532     return Min_ID; 
01533   }
01534   else {
01535     Min_ID=refineElements[1].elID;
01536     for (i=1; i*2 <= refineHeapSize-1; i=Child)
01537     {
01538       
01539       Child = i*2;       
01540       if (Child !=refineHeapSize)  
01541     if (refineElements[Child+1].len < refineElements[Child].len)
01542       Child++; 
01543 
01544       
01545       if (refineElements[refineHeapSize].len >= refineElements[Child].len){  
01546     refineElements[i].elID = refineElements[Child].elID;   
01547     refineElements[i].len = refineElements[Child].len;
01548       }
01549       else
01550          break; 
01551     }
01552     refineElements[i].elID = refineElements[refineHeapSize].elID;   
01553     refineElements[i].len = refineElements[refineHeapSize].len; 
01554     refineHeapSize--;
01555     return Min_ID; 
01556   }
01557 }
01558 
01559 
01560 
01561 intMsg *chunk::getBoundary(int edgeIdx)
01562 {
01563   intMsg *im = new intMsg;
01564   im->anInt = theEdges[edgeIdx].getBoundary();
01565   return im;
01566 }
01567 
01568 
01569 void chunk::validCheck()
01570 {
01571   int i;
01572   FEM_Entity *fem_node = meshPtr->lookup(FEM_NODE,"validCheck");
01573   FEM_DataAttribute *validNode = (FEM_DataAttribute *)fem_node->lookup(FEM_ATTRIB_TAG_MAX-1,"validCheck");
01574   AllocTable2d<int> &validNodeTable = validNode->getInt();
01575   
01576 
01577 
01578 
01579 
01580   for (i=0; i<nodeSlots; i++) {
01581     CkAssert(theNodes[i].isPresent()==validNodeTable[i][0]);
01582   }
01583 }
01584 
01585 intMsg *chunk::neighboring(int idx, elemRef e)
01586 {
01587   intMsg *m= new intMsg;
01588   m->anInt = theElements[idx].neighboring(e);
01589   return m;
01590 }
01591 
01592 intMsg *chunk::safeToCoarsen(int idx, edgeRef e)
01593 {
01594   intMsg *m= new intMsg;
01595   m->anInt = theElements[idx].safeToCoarsen(e);
01596   return m;
01597 }
01598 
01599 #include "refine.def.h"
01600