Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

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