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

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