RCM.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.3 $
00022 // $Date: 2003/10/06 20:54:08 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/graph/numberer/RCM.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: fmk 
00027 // Revision: A
00028 //
00029 // Description: This file contains the class definition for RCM.
00030 // RCM is an object to perform the Reverse Cuthill-McKee numbering
00031 // scheme on the vertices of a graph. This is done by invoking the
00032 // number() method with the Graph.
00033 //
00034 // What: "@(#) RCM.C, revA"
00035 
00036 #include <RCM.h>
00037 #include <Graph.h>
00038 #include <Vertex.h>
00039 #include <VertexIter.h>
00040 #include <ID.h>
00041 #include <Channel.h>
00042 #include <FEM_ObjectBroker.h>
00043 
00044 // Constructor
00045 RCM::RCM(bool gps)
00046 :GraphNumberer(GraphNUMBERER_TAG_RCM),
00047  numVertex(-1), theRefResult(0), GPS(gps)
00048 {
00049 
00050 }
00051 
00052 // Destructor
00053 RCM::~RCM()
00054 {
00055     if (theRefResult != 0)
00056         delete theRefResult;
00057 }
00058 
00059 
00060 // const ID &number(Graph &theGraph,int startVertexTag = -1,
00061 //                  bool minDegree = false)
00062 //    Method to perform the Reverse Cuthill-mcKenn numbering scheme. The
00063 // user can supply a starting vertex, if none is provided the first vertex
00064 // returned by the iter is used. If minDegree flag is set to true, at each 
00065 // level set the adjacent vertices not yet added from a vertex in the previos
00066 // level set are added in descending degree. The result of the numbering scheme
00067 // is returned in an ID which contains the references for the vertices. If not
00068 // enough memory to allocate a new ID an ID of size 0 is returned.
00069 //
00070 // side effects: this routine changes the color of the vertices.
00071 
00072 const ID &
00073 RCM::number(Graph &theGraph, int startVertex)
00074 {
00075     // first check our size, if not same make new
00076     if (numVertex != theGraph.getNumVertex()) {
00077 
00078         // delete the old
00079         if (theRefResult != 0)
00080             delete theRefResult;
00081         
00082         numVertex = theGraph.getNumVertex();
00083         theRefResult = new ID(numVertex);
00084 
00085         if (theRefResult == 0) {
00086             opserr << "ERROR:  RCM::number - Out of Memory\n";
00087             theRefResult = new ID(0);
00088             numVertex = 0;
00089             return *theRefResult;
00090         }
00091     }
00092 
00093     // see if we can do quick return
00094     
00095     if (numVertex == 0) 
00096         return *theRefResult;
00097             
00098 
00099     // we first set the Tmp of all vertices to -1, indicating
00100     // they have not yet been added.
00101     
00102     Vertex *vertexPtr;
00103     VertexIter &vertexIter = theGraph.getVertices();
00104     
00105     while ((vertexPtr = vertexIter()) != 0)
00106         vertexPtr->setTmp(-1);
00107 
00108     // we now set up; setting our markers and getting first vertex
00109     int startVertexTag;
00110     startVertexTag = startVertex;
00111     
00112     if (startVertexTag != -1) {
00113         vertexPtr = theGraph.getVertexPtr(startVertexTag);
00114         if (vertexPtr == 0) {
00115             opserr << "WARNING:  RCM::number - No vertex with tag ";
00116             opserr << startVertexTag << "Exists - using first come from iter\n";
00117             startVertexTag = -1;
00118         }
00119     }   
00120 
00121     // if no starting vertex use the first one we get from the VertexIter
00122     VertexIter &vertexIter2 = theGraph.getVertices();    
00123     Vertex *start;
00124 
00125     if (startVertexTag == -1) {
00126         vertexPtr = vertexIter2();
00127         start = vertexPtr;
00128 
00129         // if GPS true use gibbs-poole-stodlmyer determine the last 
00130         // level set assuming a starting vertex and then use one of the 
00131         // nodes in this set to base the numbering on   
00132         if (GPS == true) {      
00133             
00134             int currentMark = numVertex-1;  // marks current vertex visiting.
00135             int nextMark = currentMark -1;  // marks where to put next Tag
00136             int startLastLevelSet = nextMark;
00137             (*theRefResult)(currentMark) = vertexPtr->getTag();
00138             vertexPtr->setTmp(currentMark);    
00139 
00140             // we continue till the ID is full
00141 
00142             while (nextMark >= 0) {
00143                 // get the current vertex and its adjacency
00144                 
00145                 vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00146                 const ID &adjacency = vertexPtr->getAdjacency();
00147 
00148                 // go through the vertices adjacency and add vertices which
00149                 // have not yet been Tmp'ed to the (*theRefResult)
00150 
00151                 int size = adjacency.Size();
00152                 for (int i=0; i<size; i++) {
00153             
00154                     int vertexTag = adjacency(i);
00155                     vertexPtr = theGraph.getVertexPtr(vertexTag);
00156                     if ((vertexPtr->getTmp()) == -1) {
00157                         vertexPtr->setTmp(nextMark);
00158                         (*theRefResult)(nextMark--) = vertexTag;
00159                     }
00160                 }
00161 
00162                 // go to the next vertex
00163                 //  we decrement because we are doing reverse Cuthill-McKee
00164         
00165                 currentMark--;
00166                 
00167                 if (startLastLevelSet == currentMark)
00168                     startLastLevelSet = nextMark;
00169 
00170                 // check to see if graph is disconneted
00171         
00172                 if ((currentMark == nextMark) && (currentMark >= 0)) {
00173 
00174                     // loop over iter till we get a vertex not yet Tmped
00175                     while (((vertexPtr = vertexIter2()) != 0) && 
00176                            (vertexPtr->getTmp() != -1)) 
00177                         ;
00178             
00179                     nextMark--;
00180                     startLastLevelSet = nextMark;
00181                     vertexPtr->setTmp(currentMark);
00182                     (*theRefResult)(currentMark) = vertexPtr->getTag();
00183 
00184                 }
00185             
00186             }
00187 
00188             // create an id of the last level set
00189             if (startLastLevelSet > 0) {
00190                 ID lastLevelSet(startLastLevelSet);
00191                 for (int i=0; i<startLastLevelSet; i++)
00192                     lastLevelSet(i) = (*theRefResult)(i);
00193                 
00194                 return this->number(theGraph,lastLevelSet);
00195             }
00196 
00197         }
00198         else // we start with just the first vertex we get
00199             vertexPtr = start;
00200     }
00201 
00202 
00203     VertexIter &vertexIter3 = theGraph.getVertices();
00204     Vertex *otherPtr;
00205 
00206     // set to -1 all the vertices     
00207     while ((otherPtr = vertexIter3()) != 0)
00208         otherPtr->setTmp(-1);
00209 
00210 
00211     VertexIter &vertexIter4 = theGraph.getVertices();
00212 
00213     int currentMark = numVertex-1;  // marks current vertex visiting.
00214     int nextMark = currentMark -1;  // indiactes where to put next Tag in ID.
00215     (*theRefResult)(currentMark) = vertexPtr->getTag();
00216     vertexPtr->setTmp(currentMark);
00217 
00218     // we continue till the ID is full
00219     while (nextMark >= 0) {
00220         // get the current vertex and its adjacency
00221         vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00222         const ID &adjacency = vertexPtr->getAdjacency();
00223 
00224         // go through the vertices adjacency and add vertices which
00225         // have not yet been Tmp'ed to the (*theRefResult)
00226 
00227         int size = adjacency.Size();
00228         for (int i=0; i<size; i++) {
00229             
00230             int vertexTag = adjacency(i);
00231             vertexPtr = theGraph.getVertexPtr(vertexTag);
00232             if ((vertexPtr->getTmp()) == -1) {
00233                 vertexPtr->setTmp(nextMark);
00234                 (*theRefResult)(nextMark--) = vertexTag;
00235             }
00236         }
00237 
00238         // go to the next vertex
00239         //  we decrement because we are doing reverse Cuthill-McKee
00240         
00241         currentMark--;
00242 
00243         // check to see if graph is disconneted
00244         
00245         if ((currentMark == nextMark) && (currentMark >= 0)) {
00246           // opserr << "WARNING:  RCM::number - Disconnected graph -2 \n ";
00247             
00248           // loop over iter till we get a vertex not yet Tmped
00249             
00250           while (((vertexPtr = vertexIter4()) != 0) && 
00251                  (vertexPtr->getTmp() != -1)) 
00252             ;
00253             
00254           nextMark--;
00255           vertexPtr->setTmp(currentMark);
00256           (*theRefResult)(currentMark) = vertexPtr->getTag();
00257         }
00258 
00259     }
00260     
00261     // now set the vertex references instead of the vertex tags
00262     // in the result, we change the Tmp to indicate number and return
00263     
00264     for (int i=0; i<numVertex; i++) {
00265         int vertexTag = (*theRefResult)(i);
00266         vertexPtr = theGraph.getVertexPtr(vertexTag);
00267         vertexPtr->setTmp(i+1); // 1 through numVertex
00268         (*theRefResult)(i) = vertexPtr->getTag();
00269     }
00270 
00271     return *theRefResult;
00272 }
00273 
00274 
00275 
00276 int
00277 RCM::sendSelf(int commitTag, Channel &theChannel)
00278 {
00279     return 0;
00280 }
00281 
00282 int
00283 RCM::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00284 {
00285     return 0;
00286 }
00287 
00288 
00289 const ID &
00290 RCM::number(Graph &theGraph, const ID &startVertices)
00291 {
00292 
00293     // first check our size, if not same make new
00294     if (numVertex != theGraph.getNumVertex()) {
00295 
00296         // delete the old
00297         if (theRefResult != 0)
00298             delete theRefResult;
00299         
00300         numVertex = theGraph.getNumVertex();
00301         theRefResult = new ID(numVertex);
00302 
00303         if (theRefResult == 0) {
00304             opserr << "ERROR:  RCM::number - Out of Memory\n";
00305             theRefResult = new ID(0);
00306             numVertex = 0;
00307             return *theRefResult;
00308         }
00309     }
00310 
00311     // see if we can do quick return
00312     
00313     if (numVertex == 0) 
00314         return *theRefResult;
00315 
00316     // determine one that gives the min avg profile         
00317     int minStartVertexTag =0;
00318     int minAvgProfile = 0;
00319     int startVerticesSize = startVertices.Size();
00320     Vertex *vertexPtr;
00321     
00322     int startVertexTag =0;
00323     
00324     for (int i=0; i<startVerticesSize; i++) {
00325         // we first set the Tmp of all vertices to -1, indicating
00326         // they have not yet been added.
00327         VertexIter &vertexIter = theGraph.getVertices();
00328     
00329         while ((vertexPtr = vertexIter()) != 0)
00330             vertexPtr->setTmp(-1);
00331 
00332         startVertexTag = startVertices(i);
00333 
00334         if (startVertexTag != -1) {
00335             vertexPtr = theGraph.getVertexPtr(startVertexTag);
00336             if (vertexPtr == 0) {
00337                 opserr << "WARNING:  RCM::number - No vertex with tag ";
00338                 opserr << startVertexTag << "Exists - using first come from iter\n";
00339                 startVertexTag = -1;
00340             }
00341         }       
00342 
00343         int currentMark = numVertex-1;  // marks current vertex visiting.
00344         int nextMark = currentMark -1;  // indiactes where to put next Tag in ID.
00345         (*theRefResult)(currentMark) = vertexPtr->getTag();
00346         vertexPtr->setTmp(currentMark);
00347         int avgProfile = 0;
00348         VertexIter &vertexIter2 = theGraph.getVertices();    
00349 
00350         // we continue till the ID is full
00351 
00352         while (nextMark >= 0) {
00353 
00354             // get the current vertex and its adjacency
00355             vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00356             const ID &adjacency = vertexPtr->getAdjacency();
00357 
00358             // go through the vertices adjacency and add vertices which
00359             // have not yet been Tmp'ed to the (*theRefResult)
00360 
00361             int size = adjacency.Size();
00362             for (int j=0; j<size; j++) {
00363                 
00364                 int vertexTag = adjacency(j);
00365                 vertexPtr = theGraph.getVertexPtr(vertexTag);
00366                 if ((vertexPtr->getTmp()) == -1) {
00367                     vertexPtr->setTmp(nextMark);
00368                     avgProfile += (currentMark - nextMark);
00369                     (*theRefResult)(nextMark--) = vertexTag;
00370                 }
00371             }
00372 
00373             // go to the next vertex
00374             //  we decrement because we are doing reverse Cuthill-McKee
00375         
00376             currentMark--;
00377 
00378             // check to see if graph is disconneted
00379         
00380             if ((currentMark == nextMark) && (currentMark >= 0)) {
00381             
00382                 // loop over iter till we get a vertex not yet Tmped
00383             
00384                 while (((vertexPtr = vertexIter2()) != 0) && 
00385                        (vertexPtr->getTmp() != -1)) 
00386                     ;
00387                 nextMark--;
00388         
00389                 vertexPtr->setTmp(currentMark);
00390                 (*theRefResult)(currentMark) = vertexPtr->getTag();
00391             }
00392 
00393         }               
00394 
00395         if (i == 0 || minAvgProfile > avgProfile) {
00396             minStartVertexTag = startVertexTag;
00397             minAvgProfile = avgProfile;
00398         }
00399         
00400     }
00401 
00402         
00403     // we number based on minStartVertexTag
00404     minAvgProfile = 0;
00405 
00406     if (minStartVertexTag != startVertexTag) {
00407 
00408         // we could just call the other numbering routine - 
00409         // we will    just write it out again for now - CHANGE LATER
00410         startVertexTag = minStartVertexTag;
00411 
00412         // set all unmarked
00413         VertexIter &vertexIter = theGraph.getVertices();
00414         while ((vertexPtr = vertexIter()) != 0)
00415             vertexPtr->setTmp(-1);
00416         
00417         vertexPtr = theGraph.getVertexPtr(startVertexTag);
00418 
00419         int currentMark = numVertex-1;  // marks current vertex visiting.
00420         int nextMark = currentMark -1;  // indiactes where to put next Tag in ID.
00421         (*theRefResult)(currentMark) = vertexPtr->getTag();
00422         vertexPtr->setTmp(currentMark);
00423         VertexIter &vertexIter2 = theGraph.getVertices();    
00424 
00425         // we continue till the ID is full
00426 
00427         while (nextMark >= 0) {
00428 
00429             // get the current vertex and its adjacency
00430         
00431             vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00432             const ID &adjacency = vertexPtr->getAdjacency();
00433 
00434             // go through the vertices adjacency and add vertices which
00435             // have not yet been Tmp'ed to the (*theRefResult)
00436 
00437             int size = adjacency.Size();
00438             for (int j=0; j<size; j++) {
00439                 
00440                 int vertexTag = adjacency(j);
00441                 vertexPtr = theGraph.getVertexPtr(vertexTag);
00442                 if ((vertexPtr->getTmp()) == -1) {
00443                     vertexPtr->setTmp(nextMark);
00444                     minAvgProfile += (currentMark-nextMark);
00445                     (*theRefResult)(nextMark--) = vertexTag;
00446                 }
00447             }
00448 
00449             // go to the next vertex
00450             //  we decrement because we are doing reverse Cuthill-McKee
00451         
00452             currentMark--;
00453 
00454             // loop over iter till we get a vertex not yet Tmped
00455             if ((currentMark == nextMark) && (currentMark >= 0)) {
00456               // opserr << "WARNING:  RCM::number - Disconnected graph\n";
00457                 
00458               while (((vertexPtr = vertexIter2()) != 0) && 
00459                      (vertexPtr->getTmp() != -1)) 
00460                 ;
00461               
00462               nextMark--;
00463               vertexPtr->setTmp(currentMark);
00464               (*theRefResult)(currentMark) = vertexPtr->getTag();
00465             }
00466         }           
00467     }   
00468 
00469 
00470     // now set the vertex references instead of the vertex tags
00471     // in the result, we change the Tmp to indicate number and return
00472     
00473     for (int j=0; j<numVertex; j++) {
00474         int vertexTag = (*theRefResult)(j);
00475         vertexPtr = theGraph.getVertexPtr(vertexTag);
00476         vertexPtr->setTmp(j+1); // 1 through numVertex
00477         (*theRefResult)(j) = vertexPtr->getTag();
00478     }   
00479 
00480     return *theRefResult;
00481 }
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 

Generated on Mon Oct 23 15:05:12 2006 for OpenSees by doxygen 1.5.0