MyRCM.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: 2006/01/12 23:39:21 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/graph/numberer/MyRCM.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/graph/numberer/MyRCM.C
00027 // 
00028 // Written: fmk 
00029 // Created: Sun Sept 15 11:47:47: 1996
00030 // Revision: A
00031 //
00032 // Description: This file contains the class definition for MyRCM.
00033 // MyRCM is an object to perform the Reverse Cuthill-McKee numbering
00034 // scheme on the vertices of a graph. This is done by invoking the
00035 // number() method with the Graph.
00036 //
00037 // What: "@(#) MyRCM.C, revA"
00038 
00039 #include <MyRCM.h>
00040 #include <Graph.h>
00041 #include <Vertex.h>
00042 #include <VertexIter.h>
00043 #include <ID.h>
00044 #include <Channel.h>
00045 #include <FEM_ObjectBroker.h>
00046 
00047 // Constructor
00048 MyRCM::MyRCM(int startVertex, bool minDegreeFlag)
00049 :GraphNumberer(GraphNUMBERER_TAG_MyRCM),
00050  numVertex(-1), theRefResult(0), startVertexTag(startVertex),
00051  minDegree(minDegreeFlag)
00052 {
00053 
00054 }
00055 
00056 // Destructor
00057 MyRCM::~MyRCM()
00058 {
00059     if (theRefResult != 0)
00060         delete theRefResult;
00061 }
00062 
00063 void 
00064 MyRCM::setStartVertex(int startVertex)
00065 {
00066     startVertexTag = startVertex;
00067 }
00068 
00069 void 
00070 MyRCM::setMinDegreeFlag(bool flag)
00071 {
00072     minDegree = flag;
00073 }
00074 
00075 
00076 // const ID &number(Graph &theGraph,int startVertexTag = -1,
00077 //                  bool minDegree = false)
00078 //    Method to perform the Reverse Cuthill-mcKenn numbering scheme. The
00079 // user can supply a starting vertex, if none is provided the first vertex
00080 // returned by the iter is used. If minDegree flag is set to true, at each 
00081 // level set the adjacent vertices not yet added from a vertex in the previos
00082 // level set are added in descending degree. The result of the numbering scheme
00083 // is returned in an ID which contains the references for the vertices. If not
00084 // enough memory to allocate a new ID an ID of size 0 is returned.
00085 //
00086 // side effects: this routine changes the color of the vertices.
00087 
00088 const ID &
00089 MyRCM::number(Graph &theGraph, int startVertex)
00090 {
00091     // first check our size, if not same make new
00092     
00093     if (numVertex != theGraph.getNumVertex()) {
00094 
00095         // delete the old
00096         if (theRefResult != 0)
00097             delete theRefResult;
00098         
00099         numVertex = theGraph.getNumVertex();
00100         theRefResult = new ID(numVertex);
00101 
00102         if (theRefResult == 0) {
00103             opserr << "ERROR:  MyRCM::number - Out of Memory\n";
00104             theRefResult = new ID(0);
00105             numVertex = 0;
00106             return *theRefResult;
00107         }
00108     }
00109 
00110     // see if we can do quick return
00111     
00112     if (numVertex == 0) 
00113         return *theRefResult;
00114             
00115 
00116     // we first set the Tmp of all vertices to -1, indicating
00117     // they have not yet been added.
00118     
00119     Vertex *vertexPtr;
00120     VertexIter &vertexIter = theGraph.getVertices();
00121     
00122     while ((vertexPtr = vertexIter()) != 0)
00123         vertexPtr->setTmp(-1);
00124 
00125     // we now set up; setting our markers and getting first vertex
00126     if (startVertex != -1)
00127         startVertexTag = startVertex;
00128     
00129     if (startVertexTag != -1) {
00130         vertexPtr = theGraph.getVertexPtr(startVertexTag);
00131         if (vertexPtr == 0) {
00132             opserr << "WARNING:  MyRCM::number - No vertex with tag ";
00133             opserr << startVertexTag << "Exists - using first come from iter\n";
00134             startVertexTag = -1;
00135         }
00136     }   
00137 
00138     // if no starting vertex use the first one we get from the VertexIter
00139     
00140     VertexIter &vertexIter2 = theGraph.getVertices();    
00141     if (startVertexTag == -1) 
00142         vertexPtr = vertexIter2();
00143 
00144     int currentMark = numVertex-1;  // marks current vertex visiting.
00145     int nextMark = currentMark -1;  // indiactes where to put next Tag in ID.
00146     (*theRefResult)(currentMark) = vertexPtr->getTag();
00147     vertexPtr->setTmp(currentMark);
00148 
00149     // we continue till the ID is full
00150 
00151     while (nextMark >= 0) {
00152 
00153         // get the current vertex and its adjacency
00154         
00155         vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00156         const ID &adjacency = vertexPtr->getAdjacency();
00157 
00158         // go through the vertices adjacency and add vertices which
00159         // have not yet been Tmp'ed to the (*theRefResult)
00160 
00161         int size = adjacency.Size();
00162         for (int i=0; i<size; i++) {
00163             
00164             int vertexTag = adjacency(i);
00165             vertexPtr = theGraph.getVertexPtr(vertexTag);
00166             if ((vertexPtr->getTmp()) == -1) {
00167                 vertexPtr->setTmp(nextMark);
00168                 (*theRefResult)(nextMark--) = vertexTag;
00169             }
00170         }
00171 
00172         // go to the next vertex
00173         //  we decrement because we are doing reverse Cuthill-McKee
00174         
00175         currentMark--;
00176 
00177         // check to see if graph is disconneted
00178         
00179         if ((currentMark == nextMark) && (currentMark >= 0)) {
00180             opserr << "WARNING:  MyRCM::number - Disconnected graph\n";
00181             
00182             // loop over iter till we get a vertex not yet Tmped
00183             
00184             while (((vertexPtr = vertexIter2()) != 0) && 
00185                    (vertexPtr->getTmp() != -1)) 
00186                 ;
00187             
00188             nextMark--;
00189             vertexPtr->setTmp(currentMark);
00190             (*theRefResult)(currentMark) = vertexPtr->getTag();
00191         }
00192 
00193     }
00194     
00195     // now set the vertex references instead of the vertex tags
00196     // in the result, we change the Tmp to indicate number and return
00197     
00198     for (int i=0; i<numVertex; i++) {
00199         int vertexTag = (*theRefResult)(i);
00200         vertexPtr = theGraph.getVertexPtr(vertexTag);
00201         vertexPtr->setTmp(i+1); // 1 through numVertex
00202         (*theRefResult)(i) = vertexPtr->getTag();
00203     }
00204 
00205     theGraph.Print(opserr, 3);
00206     opserr << *theRefResult;
00207     return *theRefResult;
00208 }
00209 
00210 
00211 
00212 int
00213 MyRCM::sendSelf(int tag, Channel &theChannel)
00214 {
00215     return 0;
00216 }
00217 
00218 int
00219 MyRCM::recvSelf(int tag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00220 {
00221     return 0;
00222 }
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 const ID &
00231 MyRCM::number(Graph &theGraph, const ID &startVertices)
00232 {
00233     // first check our size, if not same make new
00234     
00235     if (numVertex != theGraph.getNumVertex()) {
00236 
00237         // delete the old
00238         if (theRefResult != 0)
00239             delete theRefResult;
00240         
00241         numVertex = theGraph.getNumVertex();
00242         theRefResult = new ID(numVertex);
00243 
00244         if (theRefResult == 0) {
00245             opserr << "ERROR:  MyRCM::number - Out of Memory\n";
00246             theRefResult = new ID(0);
00247             numVertex = 0;
00248             return *theRefResult;
00249         }
00250     }
00251 
00252     // see if we can do quick return
00253     
00254     if (numVertex == 0) 
00255         return *theRefResult;
00256 
00257     ID copyStart(startVertices);
00258 
00259     // we determine which node to start with
00260     int minStartVertexTag =0;
00261     int minAvgProfile = 0;
00262     int startVerticesSize = startVertices.Size();
00263     
00264     for (int j=0; j<startVerticesSize; j++) {
00265         // we first set the Tmp of all vertices to -1, indicating
00266         // they have not yet been added.
00267     
00268         Vertex *vertexPtr;
00269         VertexIter &vertexIter = theGraph.getVertices();
00270     
00271         while ((vertexPtr = vertexIter()) != 0)
00272             vertexPtr->setTmp(-1);
00273 
00274         // we now set up; setting our markers and set first vertices
00275         VertexIter &vertexIter2 = theGraph.getVertices();    
00276         int currentMark = numVertex-1;  // marks current vertex visiting.
00277         int nextMark = currentMark-1;
00278 
00279         for (int k=0; k<startVerticesSize; k++)
00280             if (k != j)
00281                 copyStart(k) = 0;
00282             else        
00283                 copyStart(k) = 1;
00284         
00285         vertexPtr = theGraph.getVertexPtr(startVertices(j));    
00286         (*theRefResult)(currentMark) = vertexPtr->getTag();
00287         vertexPtr->setTmp(currentMark);
00288 
00289         int numFromStart = 1;
00290         int avgProfile = 1;     
00291         while (numFromStart < startVerticesSize) {
00292             // get the current vertex and its adjacency
00293 
00294             vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00295             const ID &adjacency = vertexPtr->getAdjacency();
00296 
00297             // go through the vertices adjacency and add vertices which
00298             // have not yet been Tmp'ed to the (*theRefResult)
00299 
00300             int size = adjacency.Size();
00301             for (int i=0; i<size; i++) {
00302                 int vertexTag = adjacency(i);
00303                 int loc =startVertices.getLocation(vertexTag);
00304                 if (loc >= 0) {
00305                     vertexPtr = theGraph.getVertexPtr(vertexTag);
00306                     if ((vertexPtr->getTmp()) == -1) {
00307                         vertexPtr->setTmp(nextMark);
00308                         copyStart(loc) = 1;
00309                         numFromStart++;
00310                         avgProfile += currentMark - nextMark;                   
00311                         (*theRefResult)(nextMark--) = vertexTag;
00312                     }
00313                 }
00314             }
00315 
00316             // go to the next vertex
00317             //  we decrement because we are doing reverse Cuthill-McKee
00318         
00319             currentMark--;
00320 
00321             // check to see if graph is disconneted
00322         
00323             if (currentMark == nextMark && numFromStart < startVerticesSize) {
00324                 // loop over iter till we get a vertex not yet included
00325                 
00326                 for (int l=0; l<startVerticesSize; l++)
00327                     if (copyStart(l) == 0) {
00328                         int vertexTag = startVertices(l);                       
00329                         vertexPtr = theGraph.getVertexPtr(vertexTag);                   
00330                         nextMark--;
00331                         copyStart(l) = 1;
00332                         vertexPtr->setTmp(currentMark);
00333                         numFromStart++;
00334                         (*theRefResult)(currentMark) = vertexPtr->getTag();
00335                         l =startVerticesSize;
00336                     }
00337             }
00338         }
00339         
00340         currentMark = numVertex-1; // set current to the first again
00341         nextMark =  numVertex - startVerticesSize -1;
00342 
00343         // we continue till the ID is full
00344 
00345         while (nextMark >= 0) {
00346             // get the current vertex and its adjacency
00347         
00348             vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00349             const ID &adjacency = vertexPtr->getAdjacency();
00350 
00351             // go through the vertices adjacency and add vertices which
00352             // have not yet been Tmp'ed to the (*theRefResult)
00353 
00354             int size = adjacency.Size();
00355             for (int i=0; i<size; i++) {
00356             
00357                 int vertexTag = adjacency(i);
00358                 vertexPtr = theGraph.getVertexPtr(vertexTag);
00359                 if ((vertexPtr->getTmp()) == -1) {
00360                     vertexPtr->setTmp(nextMark);
00361                     avgProfile += currentMark - nextMark;
00362 
00363                     (*theRefResult)(nextMark--) = vertexTag;
00364                 }
00365             }
00366             // go to the next vertex
00367             //  we decrement because we are doing reverse Cuthill-McKee
00368         
00369             currentMark--;
00370 
00371             // check to see if graph is disconneted
00372         
00373             if ((currentMark == nextMark) && (currentMark >= 0)) {
00374             
00375                 // loop over iter till we get a vertex not yet Tmped
00376                 
00377                 while (((vertexPtr = vertexIter2()) != 0) && 
00378                        (vertexPtr->getTmp() != -1)) 
00379                     ;
00380                 
00381                 nextMark--;
00382                 vertexPtr->setTmp(currentMark);
00383                 (*theRefResult)(currentMark) = vertexPtr->getTag();
00384             }
00385         }
00386         
00387         if (j == 0 || minAvgProfile > avgProfile) {
00388             minStartVertexTag = startVertices(j);
00389             minAvgProfile = avgProfile;
00390         }
00391 
00392     }
00393 
00394     
00395     // now we numebr based on minStartVErtexTag
00396 
00397     // we first set the Tmp of all vertices to -1, indicating
00398     // they have not yet been added.
00399     
00400     Vertex *vertexPtr;
00401     VertexIter &vertexIter = theGraph.getVertices();
00402     
00403     while ((vertexPtr = vertexIter()) != 0)
00404         vertexPtr->setTmp(-1);
00405 
00406     // we now set up; setting our markers and set first vertices
00407     VertexIter &vertexIter2 = theGraph.getVertices();    
00408     int currentMark = numVertex-1;  // marks current vertex visiting.
00409     int nextMark = currentMark-1;
00410     
00411     vertexPtr = theGraph.getVertexPtr(minStartVertexTag);       
00412     (*theRefResult)(currentMark) = vertexPtr->getTag();
00413     vertexPtr->setTmp(currentMark);
00414     currentMark--;      
00415     
00416     int loc = startVertices.getLocation(minStartVertexTag);
00417     for (int k=0; k<startVerticesSize; k++)
00418         if (k != loc)
00419             copyStart(k) = 0;
00420      
00421 
00422     int numFromStart = 1;
00423     while (numFromStart < startVerticesSize) {
00424         // get the current vertex and its adjacency
00425 
00426         vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00427         const ID &adjacency = vertexPtr->getAdjacency();
00428 
00429         // go through the vertices adjacency and add vertices which
00430         // have not yet been Tmp'ed to the (*theRefResult)
00431 
00432         int size = adjacency.Size();
00433         for (int i=0; i<size; i++) {
00434             int vertexTag = adjacency(i);
00435             int loc =startVertices.getLocation(vertexTag);
00436             if (loc >= 0) {
00437                 vertexPtr = theGraph.getVertexPtr(vertexTag);
00438                 if ((vertexPtr->getTmp()) == -1) {
00439                     vertexPtr->setTmp(nextMark);
00440                     copyStart(loc) = 1;
00441                     numFromStart++;
00442                     (*theRefResult)(nextMark--) = vertexTag;
00443                 }
00444             }
00445         }
00446 
00447         // go to the next vertex
00448         //  we decrement because we are doing reverse Cuthill-McKee
00449         
00450         currentMark--;
00451 
00452         // check to see if graph is disconneted
00453         
00454         if (currentMark == nextMark && numFromStart < startVerticesSize) {
00455             // loop over iter till we get a vertex not yet included
00456                 
00457             for (int l=0; l<startVerticesSize; l++)
00458                 if (copyStart(l) == 0) {
00459                     int vertexTag = startVertices(l);                   
00460                     vertexPtr = theGraph.getVertexPtr(vertexTag);                       
00461                     nextMark--;
00462                     copyStart(l) = 1;
00463                     vertexPtr->setTmp(currentMark);
00464                     numFromStart++;
00465                     (*theRefResult)(currentMark) = vertexPtr->getTag();
00466                     l =startVerticesSize;
00467                 }
00468         }       
00469     }
00470         
00471     currentMark = numVertex-1; // set current to the first again
00472     nextMark =  numVertex - startVerticesSize -1;
00473 
00474 
00475     currentMark = numVertex-1; // set current to the first again
00476     
00477     // we continue till the ID is full
00478     while (nextMark >= 0) {
00479 
00480         // get the current vertex and its adjacency
00481         
00482         vertexPtr = theGraph.getVertexPtr((*theRefResult)(currentMark));
00483         const ID &adjacency = vertexPtr->getAdjacency();
00484         
00485         // go through the vertices adjacency and add vertices which
00486         // have not yet been Tmp'ed to the (*theRefResult)
00487         
00488         int size = adjacency.Size();
00489         for (int i=0; i<size; i++) {
00490             
00491             int vertexTag = adjacency(i);
00492             vertexPtr = theGraph.getVertexPtr(vertexTag);
00493             if ((vertexPtr->getTmp()) == -1) {
00494                 vertexPtr->setTmp(nextMark);
00495                 (*theRefResult)(nextMark--) = vertexTag;
00496             }
00497         }
00498 
00499         // go to the next vertex
00500         //  we decrement because we are doing reverse Cuthill-McKee
00501         
00502         currentMark--;
00503         
00504         // check to see if graph is disconneted
00505         
00506         if ((currentMark == nextMark) && (currentMark >= 0)) {
00507             opserr << "WARNING:  MyRCM::number - Disconnected graph ";
00508             
00509             // loop over iter till we get a vertex not yet Tmped
00510             
00511             while (((vertexPtr = vertexIter2()) != 0) && 
00512                    (vertexPtr->getTmp() != -1)) 
00513                 ;
00514                 
00515             nextMark--;
00516             vertexPtr->setTmp(currentMark);
00517             (*theRefResult)(currentMark) = vertexPtr->getTag();
00518         }
00519         
00520     }
00521 
00522     // now set the vertex references instead of the vertex tags
00523     // in the result, we change the Tmp to indicate number and return
00524     
00525     for (int m=0; m<numVertex; m++) {
00526         int vertexTag = (*theRefResult)(m);
00527         vertexPtr = theGraph.getVertexPtr(vertexTag);
00528         vertexPtr->setTmp(m+1); // 1 through numVertex
00529         (*theRefResult)(m) = vertexPtr->getTag();
00530     }
00531 
00532     return *theRefResult;
00533 }
00534 
00535 
00536 

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