ArrayGraph.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.2 $
00022 // $Date: 2003/02/14 23:01:22 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/graph/graph/ArrayGraph.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/graph/ArrayGraph.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 ArrayGraph.
00033 // The vertices in an ArrayGraph are held in an array. This is more efficient
00034 // than holding them in a List data structure, but problems can arise with
00035 // large Graphs in getting enough contiguous memory for the array.
00036 //
00037 // What: "@(#) ArrayGraph.C, revA"
00038 
00039 #include <ArrayGraph.h>
00040 #include <Vertex.h>
00041 #include <AnalysisModel.h>
00042 #include <DOF_Group.h>
00043 #include <FE_Element.h>
00044 
00045 ArrayGraph::ArrayGraph(int arraySize)
00046 :numVertex(0), numEdge(0), sizeVertices(arraySize), lastEmpty(0),
00047  theVertices(0), myIter(*this) 
00048 {
00049     // we now try and get an array of size arraySize
00050     theVertices = new Vertex *[arraySize];
00051     if (theVertices == 0)  {
00052         opserr << "Warning ArrayGraph::ArrayGraph";
00053         opserr << " - no contiguous memory block big enough available\n";
00054         sizeVertices = 0;
00055     }
00056     
00057     // zero the pointers
00058     
00059     for (int i=0; i<arraySize; i++)
00060         theVertices[i] = 0;
00061 }
00062 
00063 ArrayGraph::~ArrayGraph()
00064 {
00065     // delete all the vertices, then delete theVertices array
00066     
00067     if (theVertices != 0) {
00068         for (int i=0; i<numVertex; i++)
00069             if (theVertices[i] != 0)
00070                 delete theVertices[i];
00071         delete [] theVertices;
00072     }
00073 }
00074 
00075 
00076 // bool addVertex(int vertexTag, int vertexRef, 
00077 //               int vertexWeight=0, int vertexColor = 0) 
00078 // Method to add a vertex to the graph. If the adjacency list
00079 // of the vertex is not empty the graph will first check to see all
00080 // vertices in the the the vertices adjacency list exist in the graph
00081 // before the vertex is added. It then checks if it neeeds a new array
00082 // and if so creates one, i.e. if the {\em arraySize} $=$ {\em
00083 // numVertex} it creates a new array, whose size is double the original
00084 // and copies the pointers to the vertices, before invoking {\em
00085 // delete()} on the old array. It now tries to add the vertex in the
00086 // array at location {\em vertexTag}. If this fails it adds at the first
00087 // empty location it comes to. Returns a 0 if successfull addition, a
00088 // $-1$ otherwise and a message to opserr explaining the problem. \\ 
00089 
00090 
00091 bool
00092 ArrayGraph::addVertex(Vertex *vertexPtr)
00093 {
00094     // check the vertex * and its adjacency list
00095     if (vertexPtr == 0) {
00096         opserr << "WARNING ArrayGraph::addVertex";
00097         opserr << " - attempting to add a NULL vertex*\n";
00098         return false;
00099     }
00100     
00101     if (vertexPtr->getDegree() != 0) {
00102         const ID &adjacency = vertexPtr->getAdjacency();
00103         int size = adjacency.Size();
00104         for (int i=0; i<size; i++) {
00105             Vertex *other = this->getVertexPtr(adjacency(i));
00106             if (other == 0) {
00107                 opserr << "WARNING ArrayGraph::addVertex";
00108                 opserr << " - vertex with adjacent vertex not in graph\n";
00109                 return false;
00110             }           
00111         }
00112     }
00113 
00114     // check if we have room to place the vertex
00115     if (numVertex == sizeVertices) {
00116 
00117         int newSize = sizeVertices*2;
00118         Vertex **newVertices = new Vertex *[newSize];
00119         
00120         if (newVertices == 0) {
00121             opserr << "WARNING ArrayGraph::addVertex";
00122             opserr << " - out of contiguous memory could not create a new array";
00123             delete vertexPtr;
00124             return false;
00125         }
00126 
00127         // copy the old and 0 the extra, then delete the old
00128         for (int i=0; i<sizeVertices; i++)
00129             newVertices[i] = theVertices[i];
00130         for (int j=sizeVertices; j<newSize; j++)
00131             newVertices[j] = 0;
00132 
00133         delete [] theVertices;
00134         
00135         theVertices = newVertices;
00136         sizeVertices = newSize;
00137     }
00138     
00139     // now see if we can add the Vertex into the array in its vertexTag location
00140     int vertexTag = vertexPtr->getTag();
00141     if ((vertexTag >= 0) && (vertexTag < sizeVertices) && 
00142         (theVertices[vertexTag] == 0)) {
00143 
00144         theVertices[vertexTag]= vertexPtr;
00145         numVertex++;
00146         return 0;
00147 
00148     } else {
00149         
00150         // we have to serach through the array till we find an empty spot
00151         
00152         for (int i=0; i<sizeVertices; i++) 
00153             if (theVertices[i] == 0) {
00154                 
00155                 lastEmpty = i+1; // stores the lastEmpty place
00156                 theVertices[i] = vertexPtr;
00157                 numVertex++;
00158                 return true;
00159             }
00160     }
00161 
00162     // we should never get here
00163 
00164     return false;
00165 }
00166 
00167 // Vertex *getVertexPtr(int vertexTag);} 
00168 // A method which returns a pointer to the vertex whose tag is given by 
00169 // vertexTag. The method first looks at location {\em vertexTag} for the
00170 // vertex, otherwise it must search through the array until it finds the
00171 // vertex it is looking for. If no such vertex exists in the graph $0$ is
00172 // returned.\\ 
00173 
00174 Vertex *
00175 ArrayGraph::getVertexPtr(int vertexTag) 
00176 {
00177     // check first to see if it's in a nice position
00178     if ((vertexTag >= 0) && (vertexTag < sizeVertices) &&
00179         (theVertices[vertexTag] != 0) &&
00180         (theVertices[vertexTag]->getTag() == vertexTag)) {
00181 
00182         return theVertices[vertexTag];  
00183     }
00184     // it's not nicely positioned, we have to search
00185     // through theVertices until we find it
00186     
00187     else 
00188         for (int i=0; i<sizeVertices; i++)
00189             if ((theVertices[i] != 0) && 
00190                 (theVertices[i]->getTag() == vertexTag)){
00191 
00192                 return theVertices[i];
00193             }
00194 
00195     // else the vertex is not there
00196     
00197     return 0;
00198 }
00199 
00200 // int addEdge(int vertexTag, int otherVertexTag);
00201 // Causes the Graph to add an edge {\em (vertexTag,otherVertexTag)} to
00202 // the Graph. A check is first made to see if vertices with tags given by
00203 // {\em vertexTag} and {\em otherVertexTag} exist in the graph. If they
00204 // do not exist a $-1$ is returned, otherwise the method invokes {\em
00205 // addEdge()} on each of the corresponding vertices in the 
00206 // graph. Returns $0$ if sucessfull, a negative number if not.
00207 
00208 int 
00209 ArrayGraph::addEdge(int vertexTag, int otherVertexTag)
00210 {
00211     // get pointers to the vertices, if one does not exist return
00212 
00213     Vertex *vertex1 = this->getVertexPtr(vertexTag);
00214     Vertex *vertex2 = this->getVertexPtr(otherVertexTag);
00215     if ((vertex1 == 0) || (vertex2 == 0))
00216         return -1;
00217 
00218     // add an edge to each vertex
00219     int result;
00220     if ((result = vertex1->addEdge(otherVertexTag)) == 0)
00221         if ((result = vertex2->addEdge(vertexTag)) == 0)
00222             numEdge++;
00223 
00224     return result;
00225 }
00226 
00227 // VertexIter \&getVertices(void);} 
00228 // A method which first invokes {\em reset()} on the graphs ArrayVertexIter
00229 // and then returns a reference to this iter.\\
00230 
00231 VertexIter &
00232 ArrayGraph::getVertices(void) 
00233 {
00234     // reset the iter and then return it
00235     myIter.reset();
00236     return myIter;
00237 }
00238 
00239 
00240 int 
00241 ArrayGraph::getNumVertex(void) const
00242 {
00243     return numVertex;
00244 }
00245 
00246 
00247 int 
00248 ArrayGraph::getNumEdge(void) const
00249 {
00250     return numEdge;
00251 }
00252 
00253 
00254 int 
00255 ArrayGraph::getArraySize(void) const
00256 {
00257     return sizeVertices;
00258 }
00259 
00260 
00261 void 
00262 ArrayGraph::Print(OPS_Stream &s) const
00263 {
00264     s << numVertex << " " << numEdge << endln;
00265     
00266     Vertex *vertexPtr;
00267     
00268     // loop over the vertices and print each
00269     
00270     for (int i=0; i<sizeVertices; i++) {
00271         vertexPtr = theVertices[i];
00272         if (vertexPtr != 0)
00273             vertexPtr->Print(s);
00274     }
00275 }
00276 
00277 OPS_Stream &operator<<(OPS_Stream &s, const ArrayGraph &M)
00278 {
00279   M.Print(s);
00280   return s;
00281 }
00282 

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