UmfpackGenLinSOE.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.5 $
00022 // $Date: 2006/02/28 19:19:34 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/linearSOE/umfGEN/UmfpackGenLinSOE.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/system_of_eqn/linearSOE/umfGEN/UmfpackGenLinSOE.h
00027 //
00028 // Written: fmk 
00029 // Created: 11/98
00030 // Revision: A
00031 //
00032 // Description: This file contains the class definition for 
00033 // UmfpackGenLinSolver. It solves the UmfpackGenLinSOEobject by calling
00034 // UMFPACK2.2.1 routines.
00035 //
00036 // What: "@(#) UmfpackGenLinSolver.h, revA"
00037 
00038 #include <UmfpackGenLinSOE.h>
00039 #include <UmfpackGenLinSolver.h>
00040 #include <Matrix.h>
00041 #include <Graph.h>
00042 #include <Vertex.h>
00043 #include <VertexIter.h>
00044 #include <math.h>
00045 
00046 #include <Channel.h>
00047 #include <FEM_ObjectBroker.h>
00048 
00049 UmfpackGenLinSOE::UmfpackGenLinSOE(UmfpackGenLinSolver &the_Solver)
00050 :LinearSOE(the_Solver, LinSOE_TAGS_UmfpackGenLinSOE),
00051  size(0), nnz(0), A(0), B(0), X(0), colA(0), rowStartA(0),
00052  lValue(0), index(0),
00053  vectX(0), vectB(0), Asize(0), Bsize(0),
00054  factored(false)
00055 {
00056     the_Solver.setLinearSOE(*this);
00057 }
00058 
00059 
00060 UmfpackGenLinSOE::~UmfpackGenLinSOE()
00061 {
00062     if (A != 0) delete [] A;
00063     if (B != 0) delete [] B;
00064     if (X != 0) delete [] X;
00065     if (rowStartA != 0) delete [] rowStartA;
00066     if (colA != 0) delete []colA;
00067     if (index != 0) delete []index;
00068     if (vectX != 0) delete vectX;    
00069     if (vectB != 0) delete vectB;        
00070 }
00071 
00072 
00073 int
00074 UmfpackGenLinSOE::getNumEqn(void) const
00075 {
00076     return size;
00077 }
00078 
00079 int 
00080 UmfpackGenLinSOE::setSize(Graph &theGraph)
00081 {
00082 
00083     int result = 0;
00084     int oldSize = size;
00085     size = theGraph.getNumVertex();
00086 
00087     // fist itearte through the vertices of the graph to get nnz
00088     Vertex *theVertex;
00089     int newNNZ = 0;
00090     VertexIter &theVertices = theGraph.getVertices();
00091     while ((theVertex = theVertices()) != 0) {
00092         const ID &theAdjacency = theVertex->getAdjacency();
00093         newNNZ += theAdjacency.Size() +1; // the +1 is for the diag entry
00094     }
00095     nnz = newNNZ;
00096     lValue = 20*nnz; // 20 because 3 (10 also) was not working for some instances
00097 
00098     opserr << "UmfpackGenLinSOE::setSize - n " << size << " nnz " << nnz << " lVal " << lValue << endln;
00099 
00100     if (lValue > Asize) { // we have to get more space for A and colA
00101 
00102       if (A != 0) 
00103         delete [] A;
00104       if (colA != 0)
00105         delete [] colA;
00106         
00107       A = new double[lValue]; // 3 if job =1, otherie 2 will do
00108       colA = new int[newNNZ];
00109         
00110       if (A == 0 || colA == 0) {
00111         opserr << "WARNING UmfpackGenLinSOE::UmfpackGenLinSOE :";
00112         opserr << " ran out of memory for A and colA with nnz = ";
00113         opserr << newNNZ << " \n";
00114         size = 0; Asize = 0; nnz = 0;
00115         result =  -1;
00116       } 
00117         
00118       Asize = lValue;
00119 
00120       // create space for index;
00121       if (index != 0)
00122         delete [] index;
00123 
00124       index = new int[2*nnz];
00125     }
00126 
00127     // zero the matrix
00128     for (int i=0; i<Asize; i++)
00129         A[i] = 0;
00130         
00131     factored = false;
00132     
00133     if (size > Bsize) { // we have to get space for the vectors
00134         
00135         // delete the old       
00136         if (B != 0) delete [] B;
00137         if (X != 0) delete [] X;
00138         if (rowStartA != 0) delete [] rowStartA;
00139 
00140         // create the new
00141         B = new double[size];
00142         X = new double[size];
00143         rowStartA = new int[size+1]; 
00144         
00145         if (B == 0 || X == 0 || rowStartA == 0) {
00146             opserr << "WARNING UmfpackGenLinSOE::UmfpackGenLinSOE :";
00147             opserr << " ran out of memory for vectors (size) (";
00148             opserr << size << ") \n";
00149             size = 0; Bsize = 0;
00150             result =  -1;
00151         }
00152         else
00153             Bsize = size;
00154     }
00155 
00156     // zero the vectors
00157     for (int j=0; j<size; j++) {
00158         B[j] = 0;
00159         X[j] = 0;
00160     }
00161     
00162     // create new Vectors objects
00163     if (size != oldSize) {
00164         if (vectX != 0)
00165             delete vectX;
00166 
00167         if (vectB != 0)
00168             delete vectB;
00169         
00170         vectX = new Vector(X,size);
00171         vectB = new Vector(B,size);     
00172     }
00173 
00174     // fill in rowStartA and colA
00175     if (size != 0) {
00176       rowStartA[0] = 0;
00177       int startLoc = 0;
00178       int lastLoc = 0;
00179       for (int a=0; a<size; a++) {
00180 
00181         theVertex = theGraph.getVertexPtr(a);
00182         if (theVertex == 0) {
00183           opserr << "WARNING:UmfpackGenLinSOE::setSize :";
00184           opserr << " vertex " << a << " not in graph! - size set to 0\n";
00185           size = 0;
00186           return -1;
00187         }
00188 
00189         colA[lastLoc++] = theVertex->getTag(); // place diag in first
00190         const ID &theAdjacency = theVertex->getAdjacency();
00191         int idSize = theAdjacency.Size();
00192         
00193         // now we have to place the entries in the ID into order in colA
00194         for (int i=0; i<idSize; i++) {
00195 
00196           int row = theAdjacency(i);
00197           bool foundPlace = false;
00198           // find a place in colA for current col
00199           for (int j=startLoc; j<lastLoc; j++)
00200             if (colA[j] > row) { 
00201               // move the entries already there one further on
00202               // and place col in current location
00203               for (int k=lastLoc; k>j; k--)
00204                 
00205                 colA[k] = colA[k-1];
00206               colA[j] = row;
00207               foundPlace = true;
00208               j = lastLoc;
00209             }
00210           if (foundPlace == false) // put in at the end
00211             colA[lastLoc] = row;
00212 
00213           lastLoc++;
00214         }
00215         rowStartA[a+1] = lastLoc;;          
00216         startLoc = lastLoc;
00217       }
00218     }
00219     
00220 
00221     // fill out index
00222     int *indexRowPtr = &index[0];
00223     int *indexColPtr = &index[nnz];
00224     for (int ii=0; ii<size; ii++) {
00225       int rowBegin = rowStartA[ii];
00226       int rowEnd = rowStartA[ii+1] -1;
00227       for (int j=rowBegin; j<=rowEnd; j++) {
00228         int row = ii+1;  // + 1 for fortarn indexing
00229         int col = colA[j] +1; // +1 for fortran indexing
00230         *indexRowPtr++ = row;
00231         *indexColPtr++ = col;
00232       }
00233     }
00234 
00235     // invoke setSize() on the Solver    
00236     LinearSOESolver *the_Solver = this->getSolver();
00237     int solverOK = the_Solver->setSize();
00238     if (solverOK < 0) {
00239         opserr << "WARNING:UmfpackGenLinSOE::setSize :";
00240         opserr << " solver failed setSize()\n";
00241         return solverOK;
00242     }    
00243     return result;
00244 }
00245 
00246 int 
00247 UmfpackGenLinSOE::addA(const Matrix &m, const ID &id, double fact)
00248 {
00249     // check for a quick return 
00250     if (fact == 0.0)  
00251         return 0;
00252 
00253     int idSize = id.Size();
00254     
00255     // check that m and id are of similar size
00256     if (idSize != m.noRows() && idSize != m.noCols()) {
00257         opserr << "UmfpackGenLinSOE::addA() ";
00258         opserr << " - Matrix and ID not of similar sizes\n";
00259         return -1;
00260     }
00261     
00262     if (fact == 1.0) { // do not need to multiply 
00263         for (int i=0; i<idSize; i++) {
00264             int row = id(i);
00265             if (row < size && row >= 0) {
00266                 int startRowLoc = rowStartA[row];
00267                 int endRowLoc = rowStartA[row+1];
00268                 for (int j=0; j<idSize; j++) {
00269                     int col = id(j);
00270                     if (col <size && col >= 0) {
00271                         // find place in A using colA
00272                         for (int k=startRowLoc; k<endRowLoc; k++)
00273                             if (colA[k] == col) {
00274                                 A[k] += m(i,j);
00275                                 k = endRowLoc;
00276                             }
00277                      }
00278                 }  // for j             
00279             } 
00280         }  // for i
00281     } else {
00282         for (int i=0; i<idSize; i++) {
00283             int row = id(i);
00284             if (row < size && row >= 0) {
00285                 int startRowLoc = rowStartA[row];
00286                 int endRowLoc = rowStartA[row+1];
00287                 for (int j=0; j<idSize; j++) {
00288                     int col = id(j);
00289                     if (col <size && col >= 0) {
00290                         // find place in A using colA
00291                         for (int k=startRowLoc; k<endRowLoc; k++)
00292                             if (colA[k] == col) {
00293                                 A[k] += fact * m(i,j);
00294                                 k = endRowLoc;
00295                             }
00296                      }
00297                 }  // for j             
00298             } 
00299         }  // for i
00300     }
00301 
00302     return 0;
00303 }
00304 
00305     
00306 int 
00307 UmfpackGenLinSOE::addB(const Vector &v, const ID &id, double fact)
00308 {
00309 
00310     // check for a quick return 
00311     if (fact == 0.0)  return 0;
00312 
00313     int idSize = id.Size();    
00314     // check that m and id are of similar size
00315     if (idSize != v.Size() ) {
00316         opserr << "UmfpackGenLinSOE::addB() ";
00317         opserr << " - Vector and ID not of similar sizes\n";
00318         return -1;
00319     }    
00320 
00321     if (fact == 1.0) { // do not need to multiply if fact == 1.0
00322         for (int i=0; i<idSize; i++) {
00323             int pos = id(i);
00324             if (pos <size && pos >= 0)
00325                 B[pos] += v(i);
00326         }
00327     } else if (fact == -1.0) { // do not need to multiply if fact == -1.0
00328         for (int i=0; i<idSize; i++) {
00329             int pos = id(i);
00330             if (pos <size && pos >= 0)
00331                 B[pos] -= v(i);
00332         }
00333     } else {
00334         for (int i=0; i<idSize; i++) {
00335             int pos = id(i);
00336             if (pos <size && pos >= 0)
00337                 B[pos] += v(i) * fact;
00338         }
00339     }   
00340 
00341     return 0;
00342 }
00343 
00344 
00345 int
00346 UmfpackGenLinSOE::setB(const Vector &v, double fact)
00347 {
00348     // check for a quick return 
00349     if (fact == 0.0)  return 0;
00350 
00351 
00352     if (v.Size() != size) {
00353         opserr << "WARNING BandGenLinSOE::setB() -";
00354         opserr << " incomptable sizes " << size << " and " << v.Size() << endln;
00355         return -1;
00356     }
00357     
00358     if (fact == 1.0) { // do not need to multiply if fact == 1.0
00359         for (int i=0; i<size; i++) {
00360             B[i] = v(i);
00361         }
00362     } else if (fact == -1.0) {
00363         for (int i=0; i<size; i++) {
00364             B[i] = -v(i);
00365         }
00366     } else {
00367         for (int i=0; i<size; i++) {
00368             B[i] = v(i) * fact;
00369         }
00370     }   
00371     return 0;
00372 }
00373 
00374 void 
00375 UmfpackGenLinSOE::zeroA(void)
00376 {
00377     double *Aptr = A;
00378     for (int i=0; i<Asize; i++)
00379         *Aptr++ = 0;
00380 
00381     factored = false;
00382 }
00383         
00384 void 
00385 UmfpackGenLinSOE::zeroB(void)
00386 {
00387     double *Bptr = B;
00388     for (int i=0; i<size; i++)
00389         *Bptr++ = 0;
00390 }
00391 
00392 void 
00393 UmfpackGenLinSOE::setX(int loc, double value)
00394 {
00395     if (loc < size && loc >=0)
00396         X[loc] = value;
00397 }
00398 
00399 
00400 void 
00401 UmfpackGenLinSOE::setX(const Vector &x)
00402 {
00403   if (x.Size() == size && vectX != 0)
00404     *vectX = x;
00405 }
00406 
00407 
00408 const Vector &
00409 UmfpackGenLinSOE::getX(void)
00410 {
00411     if (vectX == 0) {
00412         opserr << "FATAL UmfpackGenLinSOE::getX - vectX == 0";
00413         exit(-1);
00414     }
00415     return *vectX;
00416 }
00417 
00418 const Vector &
00419 UmfpackGenLinSOE::getB(void)
00420 {
00421     if (vectB == 0) {
00422         opserr << "FATAL UmfpackGenLinSOE::getB - vectB == 0";
00423         exit(-1);
00424     }        
00425     return *vectB;
00426 }
00427 
00428 double 
00429 UmfpackGenLinSOE::normRHS(void)
00430 {
00431     double norm =0.0;
00432     for (int i=0; i<size; i++) {
00433         double Yi = B[i];
00434         norm += Yi*Yi;
00435     }
00436     return sqrt(norm);
00437     
00438 }    
00439 
00440 
00441 int
00442 UmfpackGenLinSOE::setUmfpackGenLinSolver(UmfpackGenLinSolver &newSolver)
00443 {
00444     newSolver.setLinearSOE(*this);
00445     
00446     if (size != 0) {
00447         int solverOK = newSolver.setSize();
00448         if (solverOK < 0) {
00449             opserr << "WARNING:UmfpackGenLinSOE::setSolver :";
00450             opserr << "the new solver could not setSeize() - staying with old\n";
00451             return -1;
00452         }
00453     }
00454     
00455     return this->LinearSOE::setSolver(newSolver);
00456 }
00457 
00458 
00459 int 
00460 UmfpackGenLinSOE::sendSelf(int cTag, Channel &theChannel)
00461 {
00462     return 0;
00463 }
00464 
00465 int 
00466 UmfpackGenLinSOE::recvSelf(int cTag, Channel &theChannel, 
00467                            FEM_ObjectBroker &theBroker)
00468 {
00469     return 0;
00470 }
00471 

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