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

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