00001 
00002 
00003 
00004 
00005 
00006 
00007 #include "ParFUM.h"
00008 #include "ParFUM_internals.h"
00009 using namespace std;
00010 
00011 const int faceMap2d_tri[3][2] = {{0,1},{1,2},{2,0}};
00012 const int faceMap2d_quad[4][2] = {{0,1},{1,2},{2,3},{3,0}};
00013 const int faceMap3d_tet[4][3] = {{0,1,2},{0,3,1},{0,2,3},{1,3,2}};
00014 const int faceMap3d_hex[6][4] = {{0,1,2,3},{1,5,6,2},{2,6,7,3},{3,7,4,0},{0,4,5,1},{5,4,6,7}};
00015 
00016 const int edgeMap3d_tet[6][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
00017 const int edgeMap3d_hex[12][2] = {{0,1},{0,3},{0,4},{1,2},{1,5},{2,3},{2,6},{3,7},{4,5},{4,7},{5,6},{6,7}};
00018 
00019 const int faceMap2d_cohquad[2][2] = {{0,1},{2,3}}; 
00020 const int faceMap3d_cohprism[2][3] = {{0,1,2},{3,4,5}}; 
00021 
00022 
00023 inline void addSharedNodeData(int node, const IDXL_Rec *sharedChunkList,
00024             adjNode *adaptAdjTable)
00025 {
00026     adaptAdjTable[node].numSharedPartitions = sharedChunkList->getShared();
00027     adaptAdjTable[node].sharedWithPartition = 
00028         new int [sharedChunkList->getShared()];
00029     adaptAdjTable[node].sharedWithLocalIdx = 
00030         new int [sharedChunkList->getShared()];
00031     for(int j=0; j<sharedChunkList->getShared(); j++){
00032         int sharedChunk = sharedChunkList->getChk(j);
00033         int sharedIdx = sharedChunkList->getIdx(j);
00034         adaptAdjTable[node].sharedWithPartition[j] = sharedChunk;
00035         adaptAdjTable[node].sharedWithLocalIdx[j] = sharedIdx;
00036     }
00037 }
00038 
00039 
00040 inline void addElementNodeSetData(
00041         const int elem, 
00042         const int *conn, 
00043         const int nodesPerElem,
00044         const int numFaces, 
00045         const int numEdges, 
00046         const int faceSize,
00047         const int faceMap[MAX_ADJELEMS][MAX_FACE_SIZE],
00048         const int edgeMap[MAX_EDGES][2],
00049         adjNode *faceTable, 
00050         adjNode* edgeTable)
00051 {
00052     
00053     for (int j=0; j<numFaces; j++) { 
00054         adjElem *e = new adjElem(faceSize);
00055         e->nodeSetID = j;
00056         for (int k=0; k<faceSize; k++) { 
00057             e->nodeSet[k] = conn[elem * nodesPerElem + faceMap[j][k]];
00058         }
00059         
00060         e->nodeSet.quickSort();
00061         int minNode = e->nodeSet[0];
00062         e->elemID = elem;
00063         e->next = faceTable[minNode].adjElemList->next;
00064         faceTable[minNode].adjElemList->next = e;
00065         faceTable[minNode].adjElemCount++;
00066         
00067         
00068         
00069         
00070     }
00071 
00072     
00073     if (edgeTable) {
00074         for (int j=0; j<numEdges; j++) { 
00075             adjElem *e = new adjElem(2);
00076             e->nodeSetID = j;
00077             for (int k=0; k<2; k++) { 
00078                 e->nodeSet[k] = conn[elem * nodesPerElem + edgeMap[j][k]];
00079             }
00080             
00081             
00082             e->nodeSet.quickSort();
00083             int minNode = e->nodeSet[0];
00084             e->elemID = elem;
00085             e->next = edgeTable[minNode].adjElemList->next;
00086             edgeTable[minNode].adjElemList->next = e;
00087             edgeTable[minNode].adjElemCount++;
00088         
00089             
00090             
00091             
00092             
00093         }
00094     }
00095 }
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 inline adjElem *searchAdjElemInList(adjElem *adjStart, int *searchForNodeSet,
00105             int nodeSetSize, int searchForElemID, int *found)
00106 {
00107     adjElem *rover = adjStart; 
00108     *found = 0;
00109 
00110     while (rover->next != NULL) {
00111         if (rover->next->elemID != searchForElemID) {
00112             
00113             *found = 1; 
00114                         
00115 
00116             if (nodeSetSize != rover->next->nodeSet.size()) {
00117                 *found = 0; 
00118                 
00119                 continue; 
00120             }
00121             for (int j=0; j<nodeSetSize; j++) {
00122                 if (rover->next->nodeSet[j] != searchForNodeSet[j]) {
00123                     
00124                     *found = 0; 
00125                     break;
00126                 }
00127             }
00128         }
00129         if (*found) {
00130             
00131             
00132             
00133             
00134             break; 
00135         } else {
00136             rover = rover->next; 
00137         }
00138     }
00139     return rover;
00140 }
00141 
00142 
00144 void CreateAdaptAdjacencies(int meshid, int elemType)
00145 {
00146     
00147     int myRank,numChunks;
00148     int faceSize;    
00149     int faceMapSize; 
00150     int edgeMapSize; 
00151 
00152     MPI_Comm_rank(MPI_COMM_WORLD,&myRank);
00153     MPI_Comm_size(MPI_COMM_WORLD,&numChunks);
00154     FEM_Mesh* mesh = FEM_chunk::get("CreateAdaptAdjacencies")->lookup(
00155             meshid,"CreateAdaptAdjacencies");
00156     FEM_Elem* elem = (FEM_Elem *)mesh->lookup(
00157             FEM_ELEM+elemType,"CreateAdaptAdjacencies");
00158     FEM_Node* node = (FEM_Node *)mesh->lookup(
00159             FEM_NODE,"CreateAdaptAdjacencies");
00160 
00161     const int numElems = elem->size();
00162     const int numNodes = node->size();
00163     const int nodesPerElem = (elem->getConn()).width();
00164     CkAssert(node->getCoord() != NULL);
00165     const int dim = (node->getCoord())->getWidth();
00166     CkAssert(dim == 2|| dim == 3);
00167 
00168     
00169     
00170     
00171     
00172     
00173     
00174     int faceMap[MAX_ADJELEMS][MAX_FACE_SIZE];
00175     int edgeMap[MAX_EDGES][2];
00176 
00177     guessElementShape(dim, nodesPerElem, 
00178             &faceSize, &faceMapSize, &edgeMapSize, 
00179             faceMap, edgeMap);
00180     CkAssert(faceMapSize <= MAX_ADJELEMS);
00181     CkAssert(edgeMapSize <= MAX_EDGES);
00182     CkAssert(faceSize <= MAX_FACE_SIZE);
00183 
00184     
00185     FEM_DataAttribute* adaptAdjAttr = (FEM_DataAttribute*) elem->lookup(
00186             FEM_ADAPT_FACE_ADJ, "CreateAdaptAdjacencies");  
00187     adaptAdjAttr->setWidth(faceMapSize*sizeof(adaptAdj));
00188     adaptAdj* adaptFaceAdjacencies = 
00189         reinterpret_cast<adaptAdj*>((adaptAdjAttr->getChar()).getData());
00190 
00191     FEM_DataAttribute* adaptAdjEdgeAttr = (FEM_DataAttribute*) elem->lookup(
00192             FEM_ADAPT_EDGE_ADJ, "CreateAdaptAdjacencies");  
00193     adaptAdjEdgeAttr->setWidth(edgeMapSize*sizeof(CkVec<adaptAdj>*));
00194     CkVec<adaptAdj>** adaptEdgeAdjacencies = edgeMapSize == 0 ?
00195         NULL :
00196         reinterpret_cast<CkVec<adaptAdj>**>(
00197                 (adaptAdjEdgeAttr->getChar()).getData());
00198 
00199     
00200     for (int i=0; i<numElems; i++) {
00201         for (int j=0; j<faceMapSize; ++j) {
00202             adaptFaceAdjacencies[i*faceMapSize + j].partID = -1;
00203             adaptFaceAdjacencies[i*faceMapSize + j].localID = -1;
00204         }
00205         if (adaptEdgeAdjacencies) {
00206             for (int j=0; j<edgeMapSize; ++j) {
00207                 adaptEdgeAdjacencies[i*edgeMapSize + j] = new CkVec<adaptAdj>;
00208                 assert(adaptEdgeAdjacencies[i*edgeMapSize + j] != NULL);
00209             }
00210         }
00211     }
00212 
00213     
00214     
00215     
00216 
00217     adjNode *faceTable;
00218     adjNode *edgeTable;
00219     faceTable = new adjNode[numNodes];
00220     edgeTable = adaptEdgeAdjacencies ? new adjNode[numNodes] : NULL;
00221 
00222     
00223     for (int i=0; i<numNodes; i++) {
00224         if (node->is_valid(i)) {
00225             const IDXL_Rec *sharedChunkList = node->shared.getRec(i);
00226             if (sharedChunkList != NULL) {
00227                 addSharedNodeData(i, sharedChunkList, faceTable);
00228                 if (edgeTable)
00229                     addSharedNodeData(i, sharedChunkList, edgeTable);
00230             } else {
00231                 faceTable[i].sharedWithPartition = NULL;
00232                 faceTable[i].sharedWithLocalIdx= NULL;
00233                 if (edgeTable) {
00234                     edgeTable[i].sharedWithPartition = NULL;
00235                     edgeTable[i].sharedWithLocalIdx= NULL;
00236                 }
00237             }
00238         } else {
00239             faceTable[i].sharedWithPartition = NULL;
00240             faceTable[i].sharedWithLocalIdx= NULL;
00241             if (edgeTable) {
00242                 edgeTable[i].sharedWithPartition = NULL;
00243                 edgeTable[i].sharedWithLocalIdx= NULL;
00244             }
00245         }
00246     }
00247 
00248     
00249     const int *conn = (elem->getConn()).getData();
00250     for (int i=0; i<numElems; i++) {
00251         if(elem->is_valid(i)){
00252             addElementNodeSetData(i, conn, nodesPerElem, faceMapSize, 
00253                     edgeMapSize, faceSize, faceMap, edgeMap, faceTable, 
00254                     edgeTable);
00255         }
00256     }
00257 
00258     fillLocalAdaptAdjacencies(
00259             numNodes,
00260             node,
00261             faceTable,
00262             edgeTable,
00263             faceMapSize,
00264             edgeMapSize,
00265             adaptFaceAdjacencies,
00266             adaptEdgeAdjacencies,
00267             myRank,
00268             elemType);
00269 
00270     
00271     
00272     
00273 
00274     MPI_Barrier(MPI_COMM_WORLD);
00275     MSA1DREQLIST *requestTable;
00276     if (myRank == 0) {
00277         requestTable = new MSA1DREQLIST(numChunks,numChunks);
00278     } else {
00279         requestTable = new MSA1DREQLIST;
00280     }
00281     MPI_Bcast_pup(*requestTable,0,MPI_COMM_WORLD);
00282     requestTable->enroll(numChunks);
00283     MSA1DREQLIST::Accum requestTableAcc = requestTable->getInitialAccum();
00284 
00285     makeAdjacencyRequests(
00286             numNodes,
00287             node,
00288             faceTable,
00289             requestTableAcc,
00290             faceSize,
00291             myRank,
00292             elemType);
00293 
00294     MSA1DREQLIST::Read reqTableRead = requestTableAcc.syncToRead();
00295     
00296 
00297     MSA1DREPLYLIST *replyTable;
00298     if (myRank == 0) {
00299         replyTable = new MSA1DREPLYLIST(numChunks,numChunks);
00300     } else {
00301         replyTable = new MSA1DREPLYLIST;
00302     }
00303     MPI_Bcast_pup(*replyTable,0,MPI_COMM_WORLD);
00304     replyTable->enroll(numChunks);
00305     MSA1DREPLYLIST::Accum replyAcc = replyTable->getInitialAccum();
00306 
00307     replyAdjacencyRequests(
00308             reqTableRead.get(myRank).vec,
00309             replyAcc,
00310             node,
00311             faceTable,
00312             adaptFaceAdjacencies,
00313             adaptEdgeAdjacencies,
00314             faceSize,
00315             faceMapSize,
00316             myRank,
00317             elemType,
00318             false);
00319 
00320     reqTableRead.syncDone();
00321     replyAcc.syncDone();
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338     delete requestTable;
00339     delete replyTable;
00340 
00341     if (adaptEdgeAdjacencies != NULL) {
00342         MSA1DREQLIST *edgeRequestTable;
00343         MSA1DREPLYLIST *edgeReplyTable;
00344 
00345         
00346         if (myRank == 0) {
00347             edgeRequestTable = new MSA1DREQLIST(numChunks,numChunks);
00348         } else {
00349             edgeRequestTable = new MSA1DREQLIST;
00350         }
00351         MPI_Bcast_pup(*edgeRequestTable,0,MPI_COMM_WORLD);
00352         edgeRequestTable->enroll(numChunks);
00353     MSA1DREQLIST::Accum edgeRequestTableAcc = requestTable->getInitialAccum();
00354 
00355         makeAdjacencyRequests(
00356                 numNodes,
00357                 node,
00358                 edgeTable,
00359                 edgeRequestTableAcc,
00360                 2,
00361                 myRank,
00362                 elemType);
00363 
00364     MSA1DREQLIST::Read edgeReqRead = edgeRequestTableAcc.syncToRead();
00365         
00366 
00367         if (myRank == 0) {
00368             edgeReplyTable = new MSA1DREPLYLIST(numChunks,numChunks);
00369         } else {
00370             edgeReplyTable = new MSA1DREPLYLIST;
00371         }
00372         MPI_Bcast_pup(*edgeReplyTable,0,MPI_COMM_WORLD);
00373         edgeReplyTable->enroll(numChunks);
00374     MSA1DREPLYLIST::Accum edgeReplyAcc = edgeReplyTable->getInitialAccum();
00375 
00376         replyAdjacencyRequests(
00377                 edgeReqRead.get(myRank).vec,
00378                 edgeReplyAcc,
00379                 node,
00380                 edgeTable,
00381                 adaptFaceAdjacencies,
00382                 adaptEdgeAdjacencies,
00383                 2,
00384                 edgeMapSize,
00385                 myRank,
00386                 elemType,
00387                 true);
00388 
00389         edgeReqRead.syncDone();
00390         edgeReplyAcc.syncDone();
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409         delete edgeRequestTable;
00410         delete edgeReplyTable;
00411     }
00412 
00413     for (int i=0; i<numNodes; ++i) {
00414         delete[] faceTable[i].sharedWithPartition;
00415         delete[] faceTable[i].sharedWithLocalIdx;
00416         adjElem* e = faceTable[i].adjElemList->next;
00417         adjElem* dummy;
00418             while (e != NULL) {
00419             dummy = e;
00420             e = e->next;
00421             delete dummy;
00422         }
00423 
00424         if (edgeTable) {
00425             delete[] edgeTable[i].sharedWithPartition;
00426             delete[] edgeTable[i].sharedWithLocalIdx;
00427             e = edgeTable[i].adjElemList->next;
00428             while (e != NULL) {
00429                 dummy = e;
00430                 e = e->next;
00431                 delete dummy;
00432             }
00433         }
00434     }
00435     delete[] faceTable;
00436     delete[] edgeTable;
00437     
00438 }
00439 
00440 
00441 void fillLocalAdaptAdjacencies(
00442         const int numNodes, 
00443         FEM_Node* node, 
00444         adjNode* faceTable, 
00445         adjNode* edgeTable,
00446         const int faceMapSize,
00447         const int edgeMapSize,
00448         adaptAdj* adaptFaceAdjacencies,
00449         CkVec<adaptAdj>** adaptEdgeAdjacencies,
00450         const int myRank, 
00451         const int elemType)
00452 {
00453     
00454     adjNode* adaptAdjTable = faceTable;
00455     for (int i=0; i<numNodes; i++) {
00456         if (!adaptAdjTable)
00457             break;
00458         
00459         
00460         
00461         if (node->is_valid(i) && adaptAdjTable[i].adjElemList != NULL) {
00462             
00463             adjElem *preTarget = adaptAdjTable[i].adjElemList;
00464             adjElem *target = adaptAdjTable[i].adjElemList->next;
00465             while (target != NULL) { 
00466                 int found = 0;
00467                 
00468                 
00469                 
00470                 
00471                 
00472                 
00473                 adjElem *rover = searchAdjElemInList(preTarget,
00474                         target->nodeSet.getVec(), target->nodeSet.size(),
00475                         target->elemID, &found);
00476 
00477                 if (found) {
00478                     
00479                     
00480                     
00481                     
00482                     
00483 
00484                     adaptFaceAdjacencies[faceMapSize*target->elemID +
00485                     target->nodeSetID] = adaptAdj(myRank, rover->next->elemID,
00486                             elemType);
00487                     adaptFaceAdjacencies[
00488                     faceMapSize*rover->next->elemID +
00489                     rover->next->nodeSetID] = adaptAdj(myRank, target->elemID,
00490                             elemType);
00491 
00492                     
00493                     adjElem *tmp = rover->next;
00494                     rover->next = rover->next->next;
00495                     delete tmp;
00496                     tmp = target;
00497                     preTarget->next = target->next;
00498                     target = target->next;
00499                     delete tmp;
00500                 } else {
00501                     
00502                     
00503                     
00504                     
00505                     
00506                     preTarget = target;
00507                     target = target->next;
00508                 }
00509             }
00510         }
00511     }
00512   
00513   
00514     adaptAdjTable = edgeTable;
00515     for (int i=0; i<numNodes; i++) {
00516         if (!adaptAdjTable)
00517             break;
00518         
00519         
00520         
00521         if (node->is_valid(i) && adaptAdjTable[i].adjElemList != NULL) {
00522             adjElem *preTarget = adaptAdjTable[i].adjElemList;
00523             adjElem *target = adaptAdjTable[i].adjElemList->next;
00524             
00525             
00526             
00527             
00528             
00529             
00530 
00531             preTarget = adaptAdjTable[i].adjElemList;
00532             target = preTarget->next;
00533             while (target != NULL) { 
00534                 
00535                 
00536                 
00537                 
00538                 int found = 0;
00539                 
00540                 
00541                 
00542                 
00543                 
00544                 
00545                 adjElem
00546                         *rover =
00547                                 searchAdjElemInList(preTarget, target->nodeSet.getVec(), target->nodeSet.size(), target->elemID, &found);
00548 
00549                 while (found) {
00550                     
00551                     
00552                     
00553                     
00554                     
00555 
00556                     
00557 
00558                     adaptEdgeAdjacencies[edgeMapSize*target->elemID +
00559                     target->nodeSetID]->push_back(adaptAdj(myRank, rover->next->elemID, elemType));
00560                     
00561                     
00562                     
00563                     
00564 
00565                     rover
00566                             = searchAdjElemInList(rover->next, target->nodeSet.getVec(), target->nodeSet.size(), target->elemID, &found);
00567                 }
00568                 target = target->next;
00569             }
00570         }
00571     }
00572 }
00573 
00574 
00575 void makeAdjacencyRequests(
00576         const int numNodes,
00577         FEM_Node *node,
00578         adjNode *adaptAdjTable,
00579         MSA1DREQLIST::Accum &requestTable, 
00580         const int nodeSetSize,
00581         const int myRank,
00582         const int elemType)
00583 {
00584     for (int i=0; i<numNodes; i++) { 
00585         
00586         if(node->is_valid(i)){
00587             if (adaptAdjTable[i].adjElemList->next!=NULL) {
00588                 adjElem *adjStart = adaptAdjTable[i].adjElemList->next;
00589                 while (adjStart !=NULL) {
00590                     
00591                     std::set<int> commonSharedChunks;
00592                     for (int j=0; j<nodeSetSize; j++) {
00593                         
00594                         
00595                         
00596                         int sharedNode = adjStart->nodeSet[j];
00597                         adjNode *sharedNodeAdj = &adaptAdjTable[sharedNode];
00598                         std::set<int> sharedChunks(
00599                                 sharedNodeAdj->sharedWithPartition,
00600                                 sharedNodeAdj->sharedWithPartition + 
00601                                 sharedNodeAdj->numSharedPartitions);
00602                         if(j == 0){
00603                             commonSharedChunks = sharedChunks;
00604                         }else{
00605                             std::set<int> tmpIntersect;
00606                             set_intersection(
00607                                     commonSharedChunks.begin(), 
00608                                     commonSharedChunks.end(), 
00609                                     sharedChunks.begin(), 
00610                                     sharedChunks.end(),
00611                                     inserter(
00612                                         tmpIntersect, 
00613                                         tmpIntersect.begin()));
00614                             commonSharedChunks = tmpIntersect;              
00615                         }
00616                     }
00617                     
00618                     
00619                     
00620                     int numCommonSharedChunks = commonSharedChunks.size();
00621                     if(numCommonSharedChunks > 0){
00622                         
00623                         
00624                         adjRequest *adjRequestList = 
00625                             new adjRequest[numCommonSharedChunks];
00626                         
00627                         
00628                         
00629 
00630 
00631 
00632 
00633 
00634                         for(int j=0;j<nodeSetSize;j++){
00635                             int sharedNode = adjStart->nodeSet[j];
00636                             const IDXL_Rec *recSharedNode = 
00637                                 node->shared.getRec(sharedNode);
00638                             int countChunk=0;
00639                             for(std::set<int>::iterator chunkIterator = 
00640                                     commonSharedChunks.begin();
00641                                     chunkIterator != commonSharedChunks.end();
00642                                     chunkIterator++){
00643                                 int chunk = *chunkIterator;
00644                                 if(j == 0){
00645                                     
00646                                     
00647                                     adjRequestList[countChunk] = 
00648                                         adjRequest(adjStart->elemID,
00649                                                 myRank,
00650                                                 adjStart->nodeSetID,
00651                                                 elemType);
00652                                 }
00653 
00654                                 
00655                                 
00656                                 
00657                                 int sharedNodeIdx=-1; 
00658                                 for(int k=0;k<recSharedNode->getShared();k++){
00659                                     if(recSharedNode->getChk(k) == chunk){
00660                                         
00661                                         sharedNodeIdx = 
00662                                             recSharedNode->getIdx(k);
00663                                         break;
00664                                     }
00665                                 }
00666                                 CkAssert(sharedNodeIdx != -1);
00667                                 
00668                                 
00669                                 
00670                                 adjRequestList[countChunk].
00671                                     translatedNodeSet[j] = sharedNodeIdx;
00672                                 countChunk++;
00673                             }
00674                         }
00675 
00676                         
00677                         
00678                         
00679                         
00680                         int countChunk=0;
00681                         for(std::set<int>::iterator chunkIterator = 
00682                                 commonSharedChunks.begin();
00683                                 chunkIterator != commonSharedChunks.end();
00684                                 chunkIterator++){
00685                             int chunk = *chunkIterator;
00686 #if 0
00687                             printf("[%d] Sending to chunk %d request (%d,%d,%d,%d) \n",
00688                    myRank, chunk,
00689                    adjRequestList[countChunk].elemID,
00690                    adjRequestList[countChunk].chunkID,
00691                    adjRequestList[countChunk].elemType,
00692                    adjRequestList[countChunk].nodeSetID);
00693 #endif
00694                             requestTable(chunk) += adjRequestList[countChunk];
00695                             countChunk++;
00696                         }
00697                         delete [] adjRequestList;
00698                     }
00699                     adjStart = adjStart->next;
00700                 }
00701             }
00702         }
00703     }
00704 }
00705 
00706 
00707 void replyAdjacencyRequests(
00708     CkVec<adjRequest> *receivedRequestVec,
00709         MSA1DREPLYLIST::Accum &replyTable,
00710         FEM_Node* node,
00711         adjNode* adaptAdjTable,
00712         adaptAdj* adaptFaceAdjacencies,
00713         CkVec<adaptAdj>** adaptEdgeAdjacencies,
00714         const int nodeSetSize,
00715         const int numAdjElems,
00716         const int myRank,
00717         const int elemType,
00718         bool isEdgeRequest)
00719 {
00720     
00721     
00722     
00723     
00724     
00725     
00726     
00727     
00728 
00729     
00730     
00731     for (int i=0;i<receivedRequestVec->length();i++) {    
00732         adjRequest &receivedRequest = (*receivedRequestVec)[i];
00733         const IDXL_List &sharedNodeList = 
00734             node->shared.getList(receivedRequest.chunkID);
00735         CkVec<int> sharedNodes(nodeSetSize);
00736         
00737         for (int j=0;j<nodeSetSize;j++) {
00738             int sharedNode = sharedNodeList[
00739                 receivedRequest.translatedNodeSet[j]];
00740             sharedNodes[j] = sharedNode;
00741         }
00742         sharedNodes.quickSort();
00743         
00744         
00745         adjNode *minNode = &adaptAdjTable[sharedNodes[0]];
00746         int found=0;
00747         
00748         adjElem *rover =  searchAdjElemInList(
00749                 minNode->adjElemList, 
00750                 sharedNodes.getVec(), 
00751                 nodeSetSize, 
00752                 -1, 
00753                 &found);
00754 
00755 
00756 
00757 
00758         
00759 
00760         
00761         if (found) { 
00762             
00763             
00764             
00765             
00766             int matchingElemID = rover->next->elemID;
00767 
00768             if (isEdgeRequest) {
00769                 
00770                 
00771                 while (found) {
00772 
00773 
00774 
00775 
00776 
00777                     CkVec<adaptAdj>* matchingAdaptAdj = adaptEdgeAdjacencies[
00778                         matchingElemID*numAdjElems + rover->next->nodeSetID];
00779                     matchingAdaptAdj->push_back(adaptAdj(
00780                                 receivedRequest.chunkID,
00781                                 receivedRequest.elemID, 
00782                                 receivedRequest.elemType));
00783 
00784                     rover = searchAdjElemInList(
00785                             rover->next, 
00786                             sharedNodes.getVec(), 
00787                             nodeSetSize, 
00788                             -1, 
00789                             &found);
00790                     
00791                     if (found) {
00792                         matchingElemID = rover->next->elemID;
00793                     }
00794                 }
00795             } else {
00796                 adaptAdj *matchingAdaptAdj = &adaptFaceAdjacencies[
00797                     matchingElemID*numAdjElems + rover->next->nodeSetID];
00798                 CkAssert(matchingAdaptAdj->localID == -1);
00799                 matchingAdaptAdj->partID = receivedRequest.chunkID;
00800                 matchingAdaptAdj->localID = receivedRequest.elemID;
00801                 matchingAdaptAdj->elemType = receivedRequest.elemType;
00802 
00803                 adjElem *tmp = rover->next;
00804                 rover->next = tmp->next;
00805                 delete tmp;
00806             }
00807             
00808             
00809             
00810             adjReply reply;
00811             reply.requestingElemID = receivedRequest.elemID;
00812             reply.requestingNodeSetID = receivedRequest.nodeSetID;
00813             reply.replyingElem.partID = myRank;
00814             reply.replyingElem.localID = matchingElemID;
00815             reply.replyingElem.elemType = elemType;
00816             
00817             replyTable(receivedRequest.chunkID) += reply;
00818         } else {
00819             
00820             
00821         }
00822     }
00823 }
00824 
00825 
00826 inline void findNodeSet(
00827         int meshid,
00828         int elemType,
00829         int* faceSize, 
00830         int* faceMapSize, 
00831         int* edgeMapSize,
00832         int nodeSetMap[MAX_ADJELEMS][MAX_NODESET_SIZE],
00833         int edgeMap[MAX_EDGES][2])
00834 {
00835   FEM_Mesh *mesh = FEM_chunk::get("GetAdaptAdj")->
00836     lookup(meshid,"GetAdaptAdj");
00837   FEM_Elem *elem = (FEM_Elem *)mesh->
00838     lookup(FEM_ELEM+elemType,"GetAdaptAdj");
00839   FEM_Node *node = (FEM_Node *)mesh->
00840     lookup(FEM_NODE,"GetAdaptAdj");
00841   const int nodesPer = (elem->getConn()).width();
00842   assert(node->getCoord()!= NULL);
00843   
00844   
00845   
00846   
00847   assert(nodesPer > 0);
00848   const int dim = (node->getCoord())->getWidth();
00849   assert(dim == 2|| dim == 3);
00850   
00851   guessElementShape(dim, nodesPer, 
00852             faceSize, faceMapSize, edgeMapSize, 
00853             nodeSetMap, edgeMap);
00854 }
00855 
00856 void getAndDumpAdaptAdjacencies(
00857         const int meshid, 
00858         const int numElems, 
00859         const int elemType, 
00860         const int myRank)
00861 {
00862   int faceSize;
00863   int faceMapSize, edgeMapSize;
00864   int nodeSetMap[MAX_ADJELEMS][MAX_NODESET_SIZE]; 
00865   int edgeMap[MAX_EDGES][2]; 
00866   
00867   findNodeSet(meshid, elemType, &faceSize, &faceMapSize, &edgeMapSize,
00868           nodeSetMap, edgeMap);
00869   
00870   for (int i=0; i<numElems; i++) {
00871     printf("[%d] %d  :",myRank,i);
00872     for (int j=0; j<faceMapSize; j++) {
00873       adaptAdj *entry = getAdaptAdj(meshid, i, elemType, j);
00874       printf("(%d,%d,%d)", entry->partID, entry->localID, entry->elemType);
00875     }
00876     printf("\n");
00877   }
00878   
00879   if (edgeMapSize == 0) return;
00880   for (int i=0; i<numElems; i++) {
00881     printf("[%d] %d  :", myRank, i);
00882     for (int j=0; j<edgeMapSize; j++) {
00883       CkVec<adaptAdj>* entry = getEdgeAdaptAdj(meshid, i, elemType, j);
00884       for (int k=0; k<entry->size(); ++k) {
00885           printf("(%d,%d,%d)", (*entry)[k].partID, (*entry)[k].localID, 
00886            (*entry)[k].elemType);
00887       }
00888       if (j < (edgeMapSize-1)) printf(" | ");
00889     }
00890     printf("\n");
00891   }
00892 }
00893 
00894 
00895 adaptAdj* lookupAdaptAdjacencies(
00896         const FEM_Mesh* const mesh,
00897         const int elemType,
00898         int* numAdjacencies)
00899 {
00900     FEM_Elem *elem = (FEM_Elem*)mesh->lookup(
00901             FEM_ELEM+elemType, "lookupAdaptAdjacencies");
00902 
00903     FEM_DataAttribute* adaptAttr = (FEM_DataAttribute*)elem->lookup(
00904             FEM_ADAPT_FACE_ADJ, "lookupAdaptAdjacencies");
00905     *numAdjacencies = adaptAttr->getWidth()/sizeof(adaptAdj);
00906     AllocTable2d<unsigned char> &table = adaptAttr->getChar();
00907 
00908     return (adaptAdj*)(adaptAttr->getChar().getData());
00909 }
00910 
00911 adaptAdj* lookupAdaptAdjacencies(
00912         const int meshid,
00913         const int elemType,
00914         int* numAdjacencies)
00915 {
00916     FEM_Mesh* mesh = FEM_chunk::get("lookupAdaptAdjacencies")->lookup(
00917             meshid, "lookupAdaptAdjacencies");
00918     return lookupAdaptAdjacencies(mesh, elemType, numAdjacencies);
00919 }
00920 
00921 CkVec<adaptAdj>** lookupEdgeAdaptAdjacencies(
00922         const FEM_Mesh* const mesh,
00923         const int elemType,
00924         int* numAdjacencies)
00925 {
00926     FEM_Elem *elem = (FEM_Elem*)mesh->lookup(
00927             FEM_ELEM+elemType,"lookupAdaptAdjacencies");
00928     FEM_DataAttribute* adaptAdjAttr = (FEM_DataAttribute*)elem->lookup(
00929             FEM_ADAPT_EDGE_ADJ, "CreateAdaptAdjacencies");  
00930     *numAdjacencies = adaptAdjAttr->getWidth()/sizeof(CkVec<adaptAdj>**);
00931     CkVec<adaptAdj>** adaptAdjacencies = 
00932         reinterpret_cast<CkVec<adaptAdj>**>((adaptAdjAttr->getChar()).getData());
00933     return adaptAdjacencies;
00934 }
00935 
00936 CkVec<adaptAdj>** lookupEdgeAdaptAdjacencies(
00937         const int meshID,
00938         const int elemType,
00939         int* numAdjacencies)
00940 {
00941     FEM_Mesh *mesh = FEM_chunk::get("lookupAdaptAdjacencies")->
00942         lookup(meshID,"lookupAdaptAdjacencies");
00943     return lookupEdgeAdaptAdjacencies(mesh, elemType, numAdjacencies);
00944 }
00945 
00947 adaptAdj* getAdaptAdj(
00948         const int meshID, 
00949         const int localID,
00950         const int elemType, 
00951         const int faceID)
00952 {
00953     int numAdjacencies;
00954     adaptAdj* adaptAdjacencies = 
00955         lookupAdaptAdjacencies(meshID, elemType, &numAdjacencies);
00956     return &(adaptAdjacencies[localID*numAdjacencies+faceID]);
00957 }
00958 
00959 adaptAdj* getAdaptAdj(
00960         const FEM_Mesh* const meshPtr, 
00961         const int localID,
00962         const int elemType, 
00963         const int faceID)
00964 {
00965     int numAdjacencies;
00966     adaptAdj* adaptAdjacencies = 
00967         lookupAdaptAdjacencies(meshPtr, elemType, &numAdjacencies);
00968     return &(adaptAdjacencies[localID*numAdjacencies+faceID]);
00969 }
00970 
00971 CkVec<adaptAdj>* getEdgeAdaptAdj(
00972         const int meshID, 
00973         const int localID,
00974         const int elemType, 
00975         const int edgeID)
00976 {
00977     int numAdjacencies;
00978     CkVec<adaptAdj>** adaptAdjacencies = 
00979         lookupEdgeAdaptAdjacencies(meshID, elemType, &numAdjacencies);
00980     return adaptAdjacencies[localID*numAdjacencies+edgeID];
00981 }
00982 
00983 CkVec<adaptAdj>* getEdgeAdaptAdj(
00984         const FEM_Mesh* const meshPtr, 
00985         const int localID,
00986         const int elemType, 
00987         const int edgeID)
00988 {
00989     int numAdjacencies;
00990     CkVec<adaptAdj>** adaptAdjacencies = 
00991         lookupEdgeAdaptAdjacencies(meshPtr, elemType, &numAdjacencies);
00992     return adaptAdjacencies[localID*numAdjacencies+edgeID];
00993 }
00994 
00998 adaptAdj* getAdaptAdj(
00999         const int meshID, 
01000         const int localID,
01001         const int elemType, 
01002         const int* const vertexList)
01003 {
01004   int faceID = getElemFace(meshID, elemType, vertexList);
01005   return getAdaptAdj(meshID, localID, elemType, faceID);
01006 }
01007 
01008 CkVec<adaptAdj>* getEdgeAdaptAdj(
01009         const int meshID, 
01010         const int localID,
01011         const int elemType, 
01012         const int* const vertexList)
01013 {
01014   int edgeID = getElemEdge(meshID, elemType, vertexList);
01015   return getEdgeAdaptAdj(meshID, localID, elemType, edgeID);
01016 }
01017 
01018 adaptAdj* getFaceAdaptAdj(
01019         const int meshID, 
01020         const int localID,
01021         const int elemType, 
01022         const int* const vertexList)
01023 {
01024   return getAdaptAdj(meshID, localID, elemType, vertexList);
01025 }
01026 
01027 adaptAdj* getFaceAdaptAdj(
01028         const int meshID, 
01029         const int localID,
01030         const int elemType, 
01031         const int faceID)
01032 {
01033     return getAdaptAdj(meshID, localID, elemType, faceID);
01034 }
01035 
01036 adaptAdj* getFaceAdaptAdj(
01037         const FEM_Mesh* const meshPtr, 
01038         const int localID,
01039         const int elemType, 
01040         const int faceID)
01041 {
01042     return getAdaptAdj(meshPtr, localID, elemType, faceID);
01043 }
01044 
01045 
01047 void clearEdgeAdjacency(
01048         const FEM_Mesh* const meshPtr,
01049         const int localID,
01050         const int elemType,
01051         const int edgeID)
01052 {
01053     getEdgeAdaptAdj(meshPtr, localID, elemType, edgeID)->removeAll();
01054 }
01055 
01056 void clearEdgeAdjacency(
01057         const int meshID,
01058         const int localID,
01059         const int elemType,
01060         const int edgeID)
01061 {
01062     FEM_Mesh *mesh = FEM_chunk::get("lookupAdaptAdjacencies")->
01063         lookup(meshID,"lookupAdaptAdjacencies");
01064     clearEdgeAdjacency(mesh, localID, elemType, edgeID);
01065 }
01066 
01068 void addEdgeAdjacency(
01069         const FEM_Mesh* const meshPtr,
01070         const int localID,
01071         const int elemType,
01072         const int edgeID,
01073         const adaptAdj adj)
01074 {
01075   CkAssert(adj.localID != -1);
01076   getEdgeAdaptAdj(meshPtr, localID, elemType, edgeID)->push_back(adj);
01077 }
01078 
01079 void addEdgeAdjacency(
01080         const int meshID,
01081         const int localID,
01082         const int elemType,
01083         const int edgeID,
01084         const adaptAdj adj)
01085 {
01086   CkAssert(adj.localID != -1);
01087   FEM_Mesh *mesh = FEM_chunk::get("lookupAdaptAdjacencies")->
01088     lookup(meshID,"lookupAdaptAdjacencies");
01089   addEdgeAdjacency(mesh, localID, elemType, edgeID, adj);
01090 }
01091 
01094 int getElemFace(
01095         const int meshID, 
01096         const int type, 
01097         const int* vertexList)
01098 {
01099   int faceSize;
01100   int faceMapSize;
01101   int faceMap[MAX_ADJELEMS][MAX_NODESET_SIZE];
01102   int edgeMapSize; 
01103   int edgeMap[MAX_EDGES][2]; 
01104   findNodeSet(meshID, type, &faceSize, &faceMapSize, &edgeMapSize,
01105          faceMap, edgeMap);
01106   
01107   
01108   std::set<int> vertexSet(vertexList, vertexList+faceSize);
01109   for (int i=0; i<faceMapSize; i++) {
01110     std::set<int> aNodeSet(faceMap[i], faceMap[i]+faceSize);
01111     if (vertexSet == aNodeSet) return i;
01112   }
01113 
01114   
01115   CkAbort("ERROR: GetEdgeFace: vertexList is not a valid face./n");
01116   return -1;
01117 }
01118 
01119 int getElemEdge(
01120         const int meshID, 
01121         const int type, 
01122         const int* vertexList)
01123 {
01124   int faceSize; 
01125   int faceMapSize; 
01126   int faceMap[MAX_ADJELEMS][MAX_NODESET_SIZE]; 
01127   int edgeMapSize;
01128   int edgeMap[MAX_EDGES][2];
01129   findNodeSet(meshID, type, &faceSize, &faceMapSize, &edgeMapSize,
01130          faceMap, edgeMap);
01131   
01132   
01133   std::set<int> vertexSet(vertexList, vertexList+2);
01134   for (int i=0; i<edgeMapSize; i++) {
01135     std::set<int> aNodeSet(edgeMap[i], edgeMap[i]+2);
01136     if (vertexSet == aNodeSet) return i;
01137   }
01138 
01139   
01140   CkAbort("ERROR: GetEdgeFace: vertexList is not a valid edge./n");
01141   return -1;
01142 }
01143 
01144 
01145 
01148 void setAdaptAdj(
01149         const int meshID, 
01150         const adaptAdj elem, 
01151         const int faceID, 
01152         const adaptAdj nbr)
01153 {
01154   int numAdjacencies;
01155   adaptAdj *adaptAdjTable = lookupAdaptAdjacencies(meshID, elem.elemType,
01156                            &numAdjacencies);
01157   adaptAdjTable[elem.localID*numAdjacencies + faceID] = nbr;
01158 }
01159 
01160 void setAdaptAdj(
01161         const FEM_Mesh* meshPtr,
01162         const adaptAdj elem, 
01163         const int faceID, 
01164         const adaptAdj nbr)
01165 {
01166   int numAdjacencies;
01167   adaptAdj *adaptAdjTable = lookupAdaptAdjacencies(meshPtr, elem.elemType,
01168                            &numAdjacencies);
01169   adaptAdjTable[elem.localID*numAdjacencies + faceID] = nbr;
01170 }
01171 
01172 void addToAdaptAdj(
01173         const int meshid, 
01174         const adaptAdj elem, 
01175         const int edgeID, 
01176         const adaptAdj nbr)
01177 {
01178   CkAssert(nbr.localID != -1);
01179   CkVec<adaptAdj>* adjVec = getEdgeAdaptAdj(meshid, elem.localID, 
01180                         elem.elemType, edgeID);
01181   adjVec->push_back(nbr);
01182 }
01183 
01184 void addToAdaptAdj(
01185         const FEM_Mesh* meshPtr, 
01186         const adaptAdj elem, 
01187         const int edgeID, 
01188         const adaptAdj nbr)
01189 {
01190   CkAssert(nbr.localID != -1);
01191   CkVec<adaptAdj>* adjVec = getEdgeAdaptAdj(meshPtr, elem.localID, 
01192                         elem.elemType, edgeID);
01193   adjVec->push_back(nbr);
01194 }
01195 
01196 void removeFromAdaptAdj(
01197         const int meshid, 
01198         const adaptAdj elem, 
01199         const int edgeID, 
01200         const adaptAdj nbr)
01201 {
01202     CkVec<adaptAdj>* adjVec = getEdgeAdaptAdj(meshid, elem.localID, 
01203             elem.elemType, edgeID);
01204     for (int i=0; i<adjVec->size(); ++i) {
01205         if ((*adjVec)[i] == nbr) {
01206             adjVec->remove(i);
01207             return;
01208         }
01209     }
01210     CkAbort("removeFromAdaptAdj did not find the specified nbr");
01211 }
01212 
01213 
01214 void copyAdaptAdj(
01215         const int meshid, 
01216         const adaptAdj* const srcElem, 
01217         const adaptAdj* const destElem)
01218 {
01219     FEM_Mesh* meshPtr = FEM_chunk::get("ReplaceAdaptAdj")->lookup(
01220             meshid,"ReplaceAdaptAdj");
01221     copyAdaptAdj(meshPtr, srcElem, destElem);
01222 }
01223 
01224 
01225 void copyAdaptAdj(
01226         const FEM_Mesh* const meshPtr, 
01227         const adaptAdj* const srcElem, 
01228         const adaptAdj* const destElem)
01229 {
01230     int numAdjacencies;
01231     adaptAdj* adaptAdjTable = lookupAdaptAdjacencies(meshPtr, srcElem->elemType,
01232             &numAdjacencies);
01233     memcpy(&adaptAdjTable[destElem->localID*numAdjacencies],
01234             &adaptAdjTable[srcElem->localID*numAdjacencies],
01235             numAdjacencies*sizeof(adaptAdj));
01236 }
01237 
01238 
01239 void copyEdgeAdaptAdj(
01240         const int meshid, 
01241         const adaptAdj* const srcElem, 
01242         const adaptAdj* const destElem)
01243 {
01244     FEM_Mesh* meshPtr = FEM_chunk::get("ReplaceAdaptAdj")->lookup(
01245             meshid,"ReplaceAdaptAdj");
01246     copyEdgeAdaptAdj(meshPtr, srcElem, destElem);
01247 }
01248 
01249 
01250 void copyEdgeAdaptAdj(
01251         const FEM_Mesh* const meshPtr, 
01252         const adaptAdj* const srcElem, 
01253         const adaptAdj* const destElem)
01254 {
01255     int nAdj;
01256     CkVec<adaptAdj>** adaptAdjTable = lookupEdgeAdaptAdjacencies(meshPtr, 
01257             srcElem->elemType, &nAdj);
01258     
01259     CkVec<adaptAdj>** srcTable = &adaptAdjTable[srcElem->localID*nAdj];
01260     CkVec<adaptAdj>** dstTable = &adaptAdjTable[destElem->localID*nAdj];
01261     for (int i=0; i<nAdj; ++i) 
01262         *dstTable[i] = *srcTable[i]; 
01263 }
01264 
01265 
01266 
01270 void replaceAdaptAdj(
01271         const FEM_Mesh* const meshPtr, 
01272         const adaptAdj elem, 
01273         const adaptAdj originalNbr, 
01274         const adaptAdj newNbr)
01275 {
01276   int numAdjacencies;
01277   adaptAdj *adaptAdjTable = lookupAdaptAdjacencies(meshPtr, elem.elemType,
01278                            &numAdjacencies);
01279   for(int i=0;i<numAdjacencies;i++){
01280     if(adaptAdjTable[elem.localID*numAdjacencies+i] == originalNbr){
01281       adaptAdjTable[elem.localID*numAdjacencies+i] = newNbr;
01282       return;
01283     }
01284   }
01285   CkAbort("replaceAdaptAdj did not find the specified originalNbr");
01286 }
01287 
01288 
01289 void replaceAdaptAdj(
01290         const int meshID, 
01291         const adaptAdj elem, 
01292         const adaptAdj originalNbr, 
01293         const adaptAdj newNbr)
01294 {
01295   FEM_Mesh* meshPtr = FEM_chunk::get("ReplaceAdaptAdj")->lookup(
01296     meshID,"ReplaceAdaptAdj");
01297   replaceAdaptAdj(meshPtr, elem, originalNbr, newNbr);
01298 }
01299 
01300 
01301 void replaceAdaptAdjOnEdge(
01302         const FEM_Mesh* const meshPtr, 
01303         const adaptAdj elem, 
01304         const adaptAdj originalNbr,
01305         const adaptAdj newNbr,
01306         const int edgeID)
01307 {
01308   int numAdjacencies;
01309   CkAssert(newNbr.localID != -1);
01310   CkVec<adaptAdj>** adaptAdjTable = lookupEdgeAdaptAdjacencies(
01311     meshPtr, elem.elemType, &numAdjacencies);
01312   CkVec<adaptAdj>* innerTable = 
01313     adaptAdjTable[elem.localID*numAdjacencies + edgeID];
01314   for (int n=0; n<innerTable->size(); ++n) {
01315     if((*innerTable)[n] == originalNbr){
01316       (*innerTable)[n] = newNbr;
01317       return;
01318     }
01319   }
01320   CkAbort("replaceAdaptAdjOnEdge did not find the specified originalNbr");
01321 }
01322 
01323 
01324 void replaceAdaptAdjOnEdge(
01325         const int meshID, 
01326         const adaptAdj elem, 
01327         const adaptAdj originalNbr, 
01328         const adaptAdj newNbr,
01329         const int edgeID)
01330 {
01331   CkAssert(newNbr.localID != -1);
01332   FEM_Mesh* meshPtr = FEM_chunk::get("ReplaceAdaptAdj")->lookup(
01333     meshID,"ReplaceAdaptAdj");
01334   replaceAdaptAdjOnEdge(meshPtr, elem, originalNbr, newNbr, edgeID);
01335 }
01336 
01337 
01338 #define copyNodeMap(numEntries,entrySize,map,srcMap) \
01339 do { \
01340   for (int i=0;i<numEntries;i++){ \
01341     for(int j=0;j<entrySize;j++){ \
01342       map[i][j] = srcMap[i][j]; \
01343     } \
01344   } \
01345 } while (0) 
01346 
01347 
01348 
01349 
01350 
01351 void guessElementShape(
01352         const int dim, 
01353         const int nodesPerElem, 
01354         int* faceSize, 
01355         int *faceMapSize, 
01356         int* edgeMapSize,
01357         int faceMap[MAX_ADJELEMS][MAX_FACE_SIZE], 
01358         int edgeMap[MAX_EDGES][2])
01359 {
01360     switch(dim){
01361         case 2:
01362             {
01363                 
01364                 switch (nodesPerElem) {
01365                     case 3:
01366                         
01367                         *faceSize = 2;
01368                         *faceMapSize = 3;
01369                         *edgeMapSize = 0;
01370                         copyNodeMap(3,2,faceMap,faceMap2d_tri);
01371                         break;
01372                     case 4:
01373                         
01374                         *faceSize = 2;
01375                         *faceMapSize = 4;
01376                         *edgeMapSize = 0;
01377                         copyNodeMap(4,2,faceMap,faceMap2d_quad);
01378                         break;
01379                     default:
01380                         CkPrintf("Unknown element type\n");
01381                         CkAssert(false);
01382                 }
01383             }
01384             break;
01385         case 3:
01386             {
01387                 
01388                 switch(nodesPerElem){
01389                     case 4:
01390                         
01391                         *faceSize = 3;
01392                         *faceMapSize = 4;
01393                         *edgeMapSize = 6;
01394                         copyNodeMap(4,3,faceMap,faceMap3d_tet);
01395                         copyNodeMap(6,2,edgeMap,edgeMap3d_tet);
01396                         break;
01397                     case 8:
01398                         
01399                         *faceSize = 4;
01400                         *faceMapSize = 6;
01401                         *edgeMapSize = 12;
01402                         copyNodeMap(6,4,faceMap,faceMap3d_hex);
01403                         copyNodeMap(12,2,edgeMap,edgeMap3d_hex);
01404                         break;
01405                     default:
01406                         CkPrintf("Unknown element type\n");
01407                         CkAssert(false);
01408                 }
01409             }
01410             break;
01411         default:
01412             CkPrintf("Unknown element type\n");
01413             CkAssert(false);
01414     }
01415 }
01416