ProfileSPDLinSubstrSolver.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:02:03 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/linearSOE/profileSPD/ProfileSPDLinSubstrSolver.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/system_of_eqn/linearSOE/ProfileSPD/ProfileSPDLinSubstrSolver.C
00027 //
00028 // Written: fmk 
00029 // Created: Febuary 1997
00030 // Revision: A
00031 //
00032 // Description: This file contains the implementation for ProfileSPDLinSubstrSolver
00033 
00034 
00035 #include <ProfileSPDLinSubstrSolver.h>
00036 #include <ProfileSPDLinSOE.h>
00037 #include <Matrix.h>
00038 #include <Vector.h>
00039 #include <math.h>
00040 #include <Channel.h>
00041 #include <FEM_ObjectBroker.h>
00042 
00043 ProfileSPDLinSubstrSolver::ProfileSPDLinSubstrSolver(double tol)
00044 :ProfileSPDLinDirectSolver(tol),
00045  DomainSolver(SOLVER_TAGS_ProfileSPDLinSubstrSolver),
00046  dSize(0),DU(0),Aext(0),Yext(0)
00047 {
00048 
00049 }
00050 
00051     
00052 ProfileSPDLinSubstrSolver::~ProfileSPDLinSubstrSolver()
00053 {
00054 }
00055 
00056 int
00057 ProfileSPDLinSubstrSolver::solve()
00058 {
00059     return this->ProfileSPDLinDirectSolver::solve();
00060 }
00061 
00062 int
00063 ProfileSPDLinSubstrSolver::setSize(void)
00064 {
00065     return this->ProfileSPDLinDirectSolver::setSize();
00066 }    
00067 
00068 /* ProfileSPDLinSubstrSolver::condenseA(int numInt)
00069 **
00070 ** purpose: A procedure which takes the stifness matrix A = | A11 A12 |
00071 **                                                          | A21 A22 |
00072 **          and does the following:
00073 **
00074 **              1) replaces A11 with D1 & U11, where A11 = U11'*D1*U11
00075 **
00076 **              2) replaces A12 with M, where M = inv(U11')*A12
00077 **
00078 **              3) replaces A22 with Kdash, where Kdash = A22 - A21*inv(A11)*A12
00079 **                                                      = A22 - M'*inv(D1)*M
00080 **
00081 ** inputs: K[]          - the nxn matrix symmetric matrix  
00082 **         Profile[]    - a vector outlining the profile of K
00083 **         n            - the size of the system
00084 **         in           - the no of internal dof (<n)
00085 **
00086 ** outputs: int    0 if no error
00087 **                -1 if diag term < MINDIAG
00088 **                -2 if diag tem becomes <= 0
00089 **
00090 */
00091 
00092 
00093 int 
00094 ProfileSPDLinSubstrSolver::condenseA(int numInt)
00095 {
00096   /*
00097 for (int iii=0; iii<theSOE->size; iii++) {
00098   int rowiiitop = RowTop[iii];
00099   double *ajiptr = topRowPtr[iii];
00100   opserr << "\n COLUMN " << iii << " TopRow " << rowiiitop << " -> ";
00101   for (int jjj = rowiiitop; jjj <=iii; jjj++)
00102     opserr << *ajiptr++ << " ";
00103 }
00104 opserr << endln;
00105 */
00106 
00107     
00108     // check for quick return
00109     if (theSOE == 0)
00110         return -1;
00111 
00112     if (numInt == 0) {
00113         theSOE->numInt = numInt;        
00114         return 0;
00115     }
00116 
00117     if (dSize != size) {
00118         if (DU != 0) delete [] DU;
00119         DU = new double[numInt];
00120         if (DU == 0) {
00121             opserr << "ProfileSPDLinSubstrSolver::condenseA()";
00122             opserr << " - ran out of memory for work space\n";      
00123             return -1;
00124         }
00125         dSize = numInt;
00126     }
00127 
00128                 
00129     //
00130     //  form D1 & U11, store in A11
00131     //    - where A11 = U11'*D1*U11
00132     //    - done using Crout decomposition
00133     //
00134 
00135 
00136 
00137 
00138 
00139     this->factor(numInt);
00140     
00141     /*
00142      *  form M, leave in A12
00143      *   - where M = inv(U11')*A12
00144      */
00145     int i;
00146 
00147     for (i=numInt; i<size; i++) {
00148         
00149         int rowitop = RowTop[i];
00150         double *ajiPtr = topRowPtr[i];
00151 
00152         int jstrt = rowitop;
00153         if (rowitop == 0) {
00154             jstrt = 1;
00155             ajiPtr++;
00156         } else {
00157             jstrt = rowitop;
00158         }
00159 
00160         
00161         for (int j=jstrt; j<numInt; j++) {
00162             double tmp = *ajiPtr;
00163           
00164             int rowjtop = RowTop[j];
00165 
00166             double *akiPtr, *akjPtr;
00167            
00168             if (rowitop > rowjtop) {
00169                 akiPtr = topRowPtr[i];
00170                 akjPtr = topRowPtr[j] + (rowitop-rowjtop);
00171                 
00172                 for (int k=rowitop; k<j; k++) 
00173                     tmp -= *akjPtr++ * *akiPtr++ ;
00174               
00175             } else {
00176                 akiPtr = topRowPtr[i] + (rowjtop-rowitop);
00177                 akjPtr = topRowPtr[j];
00178                
00179                 for (int k=rowjtop; k<j; k++) 
00180                     tmp -= *akjPtr++ * *akiPtr++ ;          
00181             }
00182 
00183             *ajiPtr++ = tmp;
00184         }
00185     }
00186 
00187 
00188     /*
00189      * Now form K*, leave in A22
00190      *  - where K* = A22 - M'*inv(D11)*M
00191      */
00192 
00193     for (i=numInt; i<size; i++) {
00194 
00195         int rowitop = RowTop[i];
00196         double *ajiPtr =  topRowPtr[i];;
00197 
00198         int jstrt;
00199 
00200         if (rowitop < numInt) {
00201             ajiPtr += (numInt-rowitop);
00202             jstrt = numInt;
00203         }
00204         else
00205           jstrt = rowitop;
00206 
00207         double *DUPtr = DU; 
00208         double *akiPtr =  topRowPtr[i];
00209 
00210         for (int k=rowitop; k<numInt; k++)
00211           *DUPtr++ = *akiPtr++ * invD[k];
00212 
00213        
00214         for (int j=jstrt; j<=i; j++) {
00215            
00216             double tmp = *ajiPtr;
00217             int rowjtop = RowTop[j];
00218             double *akiPtr, *akjPtr;
00219             
00220             if (rowitop > rowjtop) {
00221                 akiPtr = DU;
00222                 akjPtr = topRowPtr[j] + (rowitop-rowjtop);
00223                 
00224                 for (int k=rowitop; k<numInt; k++) 
00225                   tmp -= *akjPtr++ * *akiPtr++;
00226 
00227             } else {
00228                 akiPtr = &DU[rowjtop-rowitop];
00229                 akjPtr = topRowPtr[j];
00230                 
00231                 for (int k=rowjtop; k<numInt; k++) 
00232                     tmp -= *akjPtr++ * *akiPtr++;
00233             }
00234 
00235             *ajiPtr++ = tmp;
00236         }
00237     }      
00238 
00239 
00240     theSOE->isAcondensed = true;
00241     theSOE->numInt = numInt;
00242 
00243     opserr << "ProfileSPDLinSubstrSolver::condenseA  numDOF: " << size << "  numInt: " << numInt << "  numExt: " << size-numInt << endln;
00244 
00245     return 0;
00246 
00247 }
00248 
00249 
00250 
00251 
00252 /* name: condenseRHS
00253 **
00254 ** purpose: A procedure which takes the stifness matrix A = | D1\U11   M  | 
00255 **                                                          | A21    A22* |
00256 **          
00257 **          and load vector B = | B1 |
00258 **                              | B2 |
00259 **          does the following:
00260 **
00261 **              1) replaces R1 with R1*, where R1* = inv(D11)inv(U11')R1
00262 **
00263 **              2) replaces R2 with R2*, where R2* = R2 - A21*inv(A11)*R1
00264 **                                                 = R2 - M'*R1*
00265 **
00266 ** inputs: A[nxn] - the nxn matrix symmetric matrix  STORED AS ROW VECTOR IN COL MAJOR ORDER
00267 **         R[n]   - the nX1 load vector
00268 **         n            - the size of the system
00269 **         in           - the no of internal dof (<n)
00270 **
00271 ** outputs: int    0 if no error
00272 **                -1 if diag term < MINDIAG
00273 **                -2 if diag tem becomes <= 0
00274 **
00275 */
00276 
00277 int 
00278 ProfileSPDLinSubstrSolver::condenseRHS(int numInt, Vector *v)
00279 {
00280 
00281     // check for quick return
00282     if (theSOE == 0)
00283         return -1;
00284 
00285     if (numInt == 0) {
00286         theSOE->numInt = numInt;
00287         return 0;
00288     }
00289 
00290     // check A has been condensed & numInt was numInt given
00291     if (theSOE->isAcondensed != true) {
00292         int ok = this->condenseA(numInt);
00293         if (ok < 0) {
00294             opserr << "ProfileSPDLinSubstrSolver::condenseRHS()";
00295             opserr << " - failed to condenseA\n";
00296             return ok;
00297         }
00298     }
00299 
00300     if (theSOE->numInt != numInt) {     
00301         opserr << "ProfileSPDLinSubstrSolver::condenseRHS()";
00302         opserr << " - numInt " << numInt << "does not agree with condensedA";
00303         opserr << " numInt " << theSOE->numInt << endln;
00304         return -1;
00305     }
00306 
00307 
00308     // set some pointers
00309     double *B = theSOE->B;
00310 
00311     //
00312     // form Y1*, leaving in Y1
00313     // - simply a triangular solve
00314     //
00315 
00316     // do forward substitution 
00317     for (int i=1; i<numInt; i++) {
00318         
00319         int rowitop = RowTop[i];            
00320         double *ajiPtr = topRowPtr[i];
00321         double *bjPtr  = &B[rowitop];  
00322         double tmp = 0;     
00323         
00324         for (int j=rowitop; j<i; j++) 
00325             tmp -= *ajiPtr++ * *bjPtr++; 
00326         
00327         B[i] += tmp;
00328     }
00329 
00330     // divide by diag term 
00331     double *bjPtr = B; 
00332     double *aiiPtr = invD;
00333     for (int j=0; j<numInt; j++) 
00334         *bjPtr++ = *aiiPtr++ * B[j];
00335 
00336     //
00337     // Now form Y2*, leaving in Y2
00338     //
00339 
00340     for (int ii=numInt; ii<size; ii++) {
00341         int rowitop = RowTop[ii];           
00342         double *ajiPtr = topRowPtr[ii];
00343         double *bjPtr  = &B[rowitop];  
00344         double tmp = 0;     
00345         
00346         for (int j=rowitop; j<numInt; j++)      
00347             tmp -= *ajiPtr++ * *bjPtr++;
00348 
00349         B[ii] += tmp;
00350     }
00351     /*
00352       for (int iii=0; iii<theSOE->size; iii++) {
00353       opserr << "COLUMN " << iii << " Biii -> " << B[iii] << endln;
00354       }
00355       opserr << endln;
00356       */
00357 
00358     return 0;
00359 }
00360 
00361 
00362 int 
00363 ProfileSPDLinSubstrSolver::computeCondensedMatVect(
00364                                int numInt, const Vector &theVect) 
00365 {
00366     opserr << "ProfileSPDLinSubstrSolver::computeCondensedMatVect() -";
00367     opserr << " not implemented yet\n";
00368     return -1;
00369 }
00370 
00371 
00372 const Matrix &
00373 ProfileSPDLinSubstrSolver::getCondensedA(void)
00374 {
00375     int numInt = theSOE->numInt;
00376     int matSize = size - numInt;
00377 
00378     // check Aext exists, if not create it
00379     if (Aext == 0) {
00380         Aext = new Matrix(matSize,matSize);
00381         
00382         if (Aext == 0 || Aext->noRows() == 0) {
00383             opserr << "ProfileSPDLinSubstrSolver::getCondensedA";
00384             opserr << "- ran out of memory for matSize " << matSize << " \n";
00385             exit(-1);
00386         }
00387     }
00388     
00389     // check that current Aext is big enough if not enllarge
00390     if (Aext->noRows() != matSize) {
00391         delete Aext;
00392         Aext = new Matrix(matSize,matSize);
00393         
00394         if (Aext == 0 || Aext->noRows() == 0) {
00395             opserr << "ProfileSPDLinSubstrSolver::getCondensedA";
00396             opserr << "- ran out of memory for matSize " << matSize << " \n";
00397             exit(-1);
00398         }
00399     }
00400     
00401     // set the components of Aee to be the matrix
00402     Aext->Zero();
00403     for (int i=numInt; i<size; i++) {
00404         int col = i - numInt;
00405 
00406         int rowitop = RowTop[i];
00407         double *akiPtr = topRowPtr[i];
00408         
00409         int row =0;
00410         if (rowitop < numInt) 
00411             akiPtr += (numInt - rowitop);
00412         else
00413             row = rowitop - numInt; // numInt FORTRAN index, rowitop C index
00414             
00415         while (row < col){
00416             double aki = *akiPtr++;
00417             (*Aext)(row,col) = aki;
00418             (*Aext)(col,row) = aki;         
00419             row++;
00420         }
00421         (*Aext)(col,row) = *akiPtr;
00422     }
00423     return *Aext;
00424 }
00425 
00426 
00427 const Vector &
00428 ProfileSPDLinSubstrSolver::getCondensedRHS(void)
00429 {
00430     int numInt = theSOE->numInt;
00431     int matSize = size - numInt;
00432 
00433     double *Y = &(theSOE->B[numInt]);
00434 
00435     // check Yext exists, if not create it
00436     if (Yext == 0) {
00437         Yext = new Vector(Y,matSize);
00438         
00439         if (Yext == 0 || Yext->Size() == 0) {
00440             opserr << "ProfileSPDLinSubstrSolver::getCondensedRHS";
00441             opserr << "- ran out of memory for vector Size " << matSize << " \n";
00442             exit(-1);
00443         }
00444     }
00445     
00446     // check that current Yext is big enough if not enllarge
00447     if (Yext->Size() != matSize) {
00448         delete Yext;
00449         Yext = new Vector(Y,matSize);
00450         
00451         if (Yext == 0 || Yext->Size() == 0) {
00452             opserr << "ProfileSPDLinSubstrSolver::getCondensedRHS";
00453             opserr << "- ran out of memory for vect Size " << matSize << " \n";
00454             exit(-1);
00455         }
00456     }
00457     
00458     return *Yext;
00459 }
00460 
00461 const Vector &
00462 ProfileSPDLinSubstrSolver::getCondensedMatVect(void)
00463 {
00464     opserr << "ProfileSPDLinSubstrSolver::computeCondensedMatVect() -";
00465     opserr << " not implemented yet\n";
00466     exit(-1);
00467 
00468     // needed for a strict compiler, program will exit before this
00469     Vector *errVect = new Vector(0); 
00470     return *errVect;
00471       
00472 }
00473 
00474 
00475 int 
00476 ProfileSPDLinSubstrSolver::setComputedXext(const Vector &xExt)
00477 {
00478     if (xExt.Size() != (size - theSOE->numInt)) {
00479         opserr << "ProfileSPDLinSubstrSolver::setComputedxExt() :";
00480         opserr << " - size mismatch " << xExt.Size() << " and ";
00481         opserr << size-theSOE->numInt << endln;
00482         return -1;
00483     }
00484 
00485     double *xPtr = &(theSOE->X)[theSOE->numInt];
00486     for (int i=0; i<xExt.Size(); i++)
00487         *xPtr++ = xExt(i);
00488 
00489     return 0;
00490 }    
00491 
00492 
00493 /* name: S O L V r I
00494 **
00495 ** purpose: A procedure which takes the stifness matrix K = | D1\U11   M  | 
00496 **                                                          | K21    K22* |
00497 **          
00498 **          and load/displ vector R = | R1* |
00499 **                                    | r2  |
00500 **          does the following:
00501 **
00502 **              1) replaces R1* with r1, where r1 = inv(K11){R1 - K12*r2}
00503 **                                                = inv(D11)inv(U11'){(D1)R1* - Mr2}
00504 **
00505 ** inputs: K[nxn] - the nxn matrix symmetric matrix  STORED AS ROW VECTOR IN COL MAJ ORD
00506 **         R[n]   - the nX1 load vector
00507 **         n            - the size of the system
00508 **         in           - the no of internal dof (<n)
00509 **
00510 **
00511 */
00512 int 
00513 ProfileSPDLinSubstrSolver::solveXint(void)
00514 {
00515 
00516   /*
00517    * form X1 = (D1)Y1* - M *X2, store in X1*
00518    */
00519 
00520     int numInt = theSOE->numInt;
00521     double *X = theSOE->X;
00522     double *B = theSOE->B;
00523     
00524     for (int j=0; j<numInt; j++) 
00525         X[j] = B[j]/invD[j];
00526 
00527     for (int i=numInt; i<size; i++) {
00528         
00529         int rowitop = RowTop[i];
00530         double *ajiPtr = topRowPtr[i];
00531         double *XjPtr  = &X[rowitop];
00532         double Xi = X[i];
00533 
00534         for (int j=rowitop; j<numInt; j++)
00535             *XjPtr++ -= *ajiPtr++ * Xi;
00536     }
00537 
00538     for (int l=0; l<numInt; l++) 
00539        X[l] = X[l]*invD[l];
00540 
00541   /*
00542    * form inv(U11)*A, store in A
00543    * - simply a triangular solve (back sub)
00544    */
00545     for (int k=(numInt-1); k>0; k--) {
00546 
00547         int rowktop = RowTop[k];
00548         double Xk = X[k];
00549         double *ajiPtr = topRowPtr[k];          
00550 
00551         for (int j=rowktop; j<k; j++) 
00552             X[j] -= *ajiPtr++ * Xk;
00553     }                
00554     return 0;
00555 }
00556 
00557 int
00558 ProfileSPDLinSubstrSolver::getClassTag(void) const
00559 {
00560     return SOLVER_TAGS_ProfileSPDLinSubstrSolver;
00561 }
00562 
00563 int
00564 ProfileSPDLinSubstrSolver::sendSelf(int cTag,
00565                                     Channel &theChannel)
00566 {
00567     if (size != 0)
00568         opserr << "ProfileSPDLinSubstrSolver::sendSelf - does not send itself YET\n"; 
00569     return 0;
00570 }
00571 
00572 
00573 int 
00574 ProfileSPDLinSubstrSolver::recvSelf(int cTag,
00575                                     Channel &theChannel, 
00576                                     FEM_ObjectBroker &theBroker)
00577 {
00578     return 0;
00579 }

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