MatrixOperations.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 2001, 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 ** Reliability module developed by:                                   **
00020 **   Terje Haukaas (haukaas@ce.berkeley.edu)                          **
00021 **   Armen Der Kiureghian (adk@ce.berkeley.edu)                       **
00022 **                                                                    **
00023 ** ****************************************************************** */
00024                                                                         
00025 // $Revision: 1.5 $
00026 // $Date: 2003/03/04 00:39:26 $
00027 // $Source: /usr/local/cvs/OpenSees/SRC/reliability/analysis/misc/MatrixOperations.cpp,v $
00028 
00029 
00030 //
00031 // Written by Terje Haukaas (haukaas@ce.berkeley.edu)
00032 //
00033 
00034 #include <MatrixOperations.h>
00035 #include <Vector.h>
00036 #include <Matrix.h>
00037 #include <math.h>
00038 #include <string.h>
00039 
00040 
00041 MatrixOperations::MatrixOperations(Matrix passedMatrix)
00042 {
00043         int rows = passedMatrix.noRows();
00044         int cols = passedMatrix.noCols();
00045 
00046         theMatrix = new Matrix(rows,cols);
00047         (*theMatrix) = passedMatrix;
00048 
00049         theLowerCholesky = new Matrix(rows,cols);
00050         theInverseLowerCholesky = new Matrix(rows,cols);
00051         theInverse = new Matrix(rows,cols);
00052         theTranspose = new Matrix(rows,cols);
00053         theSquareRoot = new Matrix(rows,cols);
00054 
00055         theMatrixNorm = 0;
00056         theTrace = 0; 
00057 
00058 }
00059 
00060 
00061 MatrixOperations::~MatrixOperations()
00062 {
00063         delete theMatrix;
00064         delete theLowerCholesky;
00065         delete theInverseLowerCholesky;
00066         delete theInverse;
00067         delete theTranspose;
00068         delete theSquareRoot;
00069 }
00070 
00071 
00072 
00073 int
00074 MatrixOperations::setMatrix(Matrix passedMatrix)
00075 {
00076         int rows = passedMatrix.noRows();
00077         int cols = passedMatrix.noCols();
00078 
00079         // delete
00080         delete theMatrix;
00081         delete theLowerCholesky;
00082         delete theInverseLowerCholesky;
00083         delete theInverse;
00084         delete theTranspose;
00085         delete theSquareRoot;
00086 
00087         // reallocate
00088         theMatrix = new Matrix(rows,cols);
00089         (*theMatrix) = passedMatrix;
00090         theLowerCholesky = new Matrix(rows,cols);
00091         theInverseLowerCholesky = new Matrix(rows,cols);
00092         theInverse = new Matrix(rows,cols);
00093         theTranspose = new Matrix(rows,cols);
00094         theSquareRoot = new Matrix(rows,cols);
00095 
00096         return 0;
00097 }
00098 
00099 
00100 Matrix 
00101 MatrixOperations::getMatrix()
00102 {
00103         return (*theMatrix);
00104 }
00105 
00106 
00107 Matrix 
00108 MatrixOperations::getLowerCholesky()
00109 {
00110         if (theLowerCholesky == 0) {
00111                 opserr << "MatrixOperations::getLowerCholesky() - this" << endln
00112                         << " matrix has not been computed." << endln;
00113                 return (*theMatrix);
00114         }
00115 
00116         return (*theLowerCholesky);
00117 }
00118 
00119 
00120 Matrix 
00121 MatrixOperations::getInverseLowerCholesky()
00122 {
00123         if (theInverseLowerCholesky == 0) {
00124                 opserr << "MatrixOperations::getInverseLowerCholesky() - this" << endln
00125                         << " matrix has not been computed." << endln;
00126                 return (*theMatrix);
00127         }
00128 
00129         return (*theInverseLowerCholesky);
00130 }
00131 
00132 
00133 Matrix 
00134 MatrixOperations::getInverse()
00135 {
00136         if (theInverse == 0) {
00137                 opserr << "MatrixOperations::getInverse() - this" << endln
00138                         << " matrix has not been computed." << endln;
00139                 return (*theMatrix);
00140         }
00141         
00142         return (*theInverse);
00143 }
00144 
00145 
00146 Matrix 
00147 MatrixOperations::getTranspose()
00148 {
00149         if (theTranspose == 0) {
00150                 opserr << "MatrixOperations::getTranspose() - this" << endln
00151                         << " matrix has not been computed." << endln;
00152                 return (*theMatrix);
00153         }
00154         
00155         return (*theTranspose);
00156 }
00157 
00158 
00159 Matrix 
00160 MatrixOperations::getSquareRoot()
00161 {
00162         if (theSquareRoot == 0) {
00163                 opserr << "MatrixOperations::getSquareRoot() - this" << endln
00164                         << " matrix has not been computed." << endln;
00165                 return (*theMatrix);
00166         }
00167         
00168         return (*theSquareRoot);
00169 }
00170 
00171 
00172 double
00173 MatrixOperations::getMatrixNorm()
00174 {
00175         return theMatrixNorm;
00176 }
00177 
00178 
00179 double
00180 MatrixOperations::getTrace()
00181 {
00182         return theTrace;
00183 }
00184 
00185 
00186 int
00187 MatrixOperations::computeLowerCholesky()
00188 {
00189         Matrix passedMatrix = (*theMatrix);
00190 
00191         // This algorithm is more or less like given in Professor Der Kiureghians
00192         // handout/brief in CE193 on Cholesky decomposition.
00193 
00194         // Should first check that the matrix is quadratic, etc. 
00195 
00196         int sizeOfPassedMatrix = passedMatrix.noCols();
00197         int i, j, k;
00198         double sumOfLambda_i_k_squared = 0;
00199         double sumOfLambda_i_kLambda_j_k = 0;
00200         Matrix lambda( sizeOfPassedMatrix , sizeOfPassedMatrix );
00201 
00202         for ( i=0 ; i<sizeOfPassedMatrix ; i++ ) 
00203         {
00204                 for ( j=0 ; j<sizeOfPassedMatrix ; j++ )
00205                 {
00206                         sumOfLambda_i_k_squared = 0;
00207                         sumOfLambda_i_kLambda_j_k = 0;
00208                         lambda(i,j) = 0.0;
00209                         for ( k=0 ; k<i ; k++ )
00210                         {
00211                                 sumOfLambda_i_k_squared += pow ( lambda(i,k) , 2 );
00212                         }
00213                         for ( k=0 ; k<j ; k++ )
00214                         {
00215                                 sumOfLambda_i_kLambda_j_k += lambda(i,k) * lambda(j,k);
00216                         }
00217                         if ( i == j )
00218                         {
00219                                 if ( ( passedMatrix(i,j) - sumOfLambda_i_k_squared ) < 1.0e-8) {
00220                                         opserr << "WARNING: MatrixOperations::computeLowerCholesky()" << endln
00221                                                 << " ... matrix may be close to singular. " << endln;
00222                                 }
00223                                 lambda(i,j) = sqrt ( passedMatrix(i,j) - sumOfLambda_i_k_squared );
00224                         }
00225                         if ( i > j )
00226                         {
00227                                 if ( fabs(lambda(j,j)) < 1.0e-8) {
00228                                         opserr << "WARNING: MatrixOperations::computeLowerCholesky()" << endln
00229                                                 << " ... matrix may be close to singular. " << endln;
00230                                 }
00231                                 lambda(i,j) = ( passedMatrix(i,j) - sumOfLambda_i_kLambda_j_k ) / lambda(j,j);
00232                         }
00233                         if ( i < j )
00234                         {
00235                                 lambda(i,j) = 0.0;
00236                         }
00237                 }
00238         }
00239 
00240         (*theLowerCholesky) = lambda;
00241 
00242         return 0;
00243 }
00244 
00245 
00246 
00247 
00248 int
00249 MatrixOperations::computeInverseLowerCholesky()
00250 {
00251         Matrix passedMatrix = (*theMatrix);
00252 
00253         // This algorithm is more or less like given in Professor Der Kiureghians
00254         // handout/brief in CE193 on Cholesky decomposition.
00255 
00256         // Should first check that the matrix is quadratic, etc. 
00257 
00258         int sizeOfPassedMatrix = passedMatrix.noCols();
00259         
00260         this->computeLowerCholesky();
00261         Matrix lambda = this->getLowerCholesky();
00262 
00263         Matrix gamma( sizeOfPassedMatrix , sizeOfPassedMatrix );
00264         int i, j, k;
00265         double sumOfLambda_i_kGamma_k_j = 0;
00266         for ( i=0 ; i<sizeOfPassedMatrix ; i++ ) 
00267         {
00268                 for ( j=0 ; j<sizeOfPassedMatrix ; j++ )
00269                 {
00270                         sumOfLambda_i_kGamma_k_j = 0;
00271                         gamma(i,j) = 0.0;
00272                         for ( k=j ; k<i ; k++ )
00273                         {
00274                                 sumOfLambda_i_kGamma_k_j += lambda(i,k) * gamma(k,j);
00275                         }
00276                         if ( i == j )
00277                         {
00278                                 gamma(i,j) = 1 / lambda(i,i);
00279                         }
00280                         if ( i > j )
00281                         {
00282                                 if ( fabs(lambda(i,i)) < 1.0e-8) {
00283                                         opserr << "WARNING: MatrixOperations::computeInverseLowerCholesky()" << endln
00284                                                 << " ... matrix may be close to singular. " << endln;
00285                                 }
00286                                 gamma(i,j) = - sumOfLambda_i_kGamma_k_j / lambda(i,i);
00287                         }
00288                         if ( i < j )
00289                         {
00290                                 gamma(i,j) = 0.0;
00291                         }
00292                 }
00293         }
00294 
00295         (*theInverseLowerCholesky) = gamma;
00296 
00297         return 0;
00298 }
00299 
00300 
00301 int
00302 MatrixOperations::computeCholeskyAndItsInverse()
00303 {
00304         Matrix &passedMatrix = (*theMatrix);
00305 
00306         // This algorithm is more or less like given in Professor Der Kiureghians
00307         // handout/brief in CE193 on Cholesky decomposition.
00308 
00309         // Should first check that the matrix is quadratic, etc. 
00310 
00311         int sizeOfPassedMatrix = passedMatrix.noCols();
00312         double sumOfLambda_i_k_squared = 0.0;
00313         double sumOfLambda_i_kLambda_j_k = 0.0;
00314         double sumOfLambda_i_kGamma_k_j = 0.0;
00315         Matrix lambda( sizeOfPassedMatrix , sizeOfPassedMatrix );
00316         Matrix gamma( sizeOfPassedMatrix , sizeOfPassedMatrix );
00317         int i, j, k;
00318 
00319         // Lower Cholesky
00320         for ( i=0 ; i<sizeOfPassedMatrix ; i++ ) 
00321         {
00322                 for ( j=0 ; j<sizeOfPassedMatrix ; j++ )
00323                 {
00324                         sumOfLambda_i_k_squared = 0.0;
00325                         sumOfLambda_i_kLambda_j_k = 0.0;
00326                         lambda(i,j) = 0.0;
00327                         for ( k=0 ; k<i ; k++ )
00328                         {
00329                                 sumOfLambda_i_k_squared += pow ( lambda(i,k) , 2.0 );
00330                         }
00331                         for ( k=0 ; k<j ; k++ )
00332                         {
00333                                 sumOfLambda_i_kLambda_j_k += lambda(i,k) * lambda(j,k);
00334                         }
00335                         if ( i == j )
00336                         {
00337                                 if ( ( passedMatrix(i,j) - sumOfLambda_i_k_squared ) < 1.0e-8) {
00338                                         opserr << "WARNING: MatrixOperations::computeCholeskyAndItsInverse()" << endln
00339                                                 << " ... matrix may be close to singular. " << endln;
00340                                 }
00341                                 lambda(i,j) = sqrt ( passedMatrix(i,j) - sumOfLambda_i_k_squared );
00342                         }
00343                         if ( i > j )
00344                         {
00345                                 if ( fabs(lambda(j,j)) < 1.0e-8) {
00346                                         opserr << "WARNING: MatrixOperations::computeCholeskyAndItsInverse()" << endln
00347                                                 << " ... matrix may be close to singular. " << endln;
00348                                 }
00349                                 lambda(i,j) = ( passedMatrix(i,j) - sumOfLambda_i_kLambda_j_k ) / lambda(j,j);
00350                         } 
00351                         if ( i < j )
00352                         {
00353                                 lambda(i,j) = 0.0;
00354                         }
00355                 }
00356         }
00357 
00358         // Inverse lower Cholesky
00359         for ( i=0 ; i<sizeOfPassedMatrix ; i++ ) 
00360         {
00361                 for ( j=0 ; j<sizeOfPassedMatrix ; j++ )
00362                 {
00363                         sumOfLambda_i_kGamma_k_j = 0;
00364                         gamma(i,j) = 0.0;
00365                         for ( k=j ; k<i ; k++ )
00366                         {
00367                                 sumOfLambda_i_kGamma_k_j += lambda(i,k) * gamma(k,j);
00368                         }
00369                         if ( i == j )
00370                         {
00371                                 gamma(i,j) = 1 / lambda(i,i);
00372                         }
00373                         if ( i > j )
00374                         {
00375                                 if ( fabs(lambda(i,i)) < 1.0e-8) {
00376                                         opserr << "WARNING: MatrixOperations::computeCholeskyAndItsInverse()" << endln
00377                                                 << " ... matrix may be close to singular. " << endln;
00378                                 }
00379                                 gamma(i,j) = - sumOfLambda_i_kGamma_k_j / lambda(i,i);
00380                         }
00381                         if ( i < j )
00382                         {
00383                                 gamma(i,j) = 0.0;
00384                         }
00385                 }
00386         }
00387 
00388         (*theLowerCholesky) = lambda;
00389         (*theInverseLowerCholesky) = gamma;
00390 
00391         return 0;
00392 }
00393 
00394 
00395 
00396 
00397 
00398 
00399 int
00400 MatrixOperations::computeTranspose()
00401 {
00402         Matrix &A = (*theMatrix);
00403 
00404         int sizeOfA = A.noCols();
00405 
00406         Matrix B(sizeOfA,sizeOfA);
00407 
00408         for (int i=0; i<sizeOfA; i++) {
00409                 for (int j=0; j<sizeOfA; j++) {
00410                         B(i,j) = A(j,i);
00411                 }
00412         }
00413 
00414         (*theTranspose) = B;
00415 
00416         return 0;
00417 }
00418 
00419 
00420 
00421 
00422 
00423 int
00424 MatrixOperations::computeSquareRoot()
00425 {
00426         Matrix &A = (*theMatrix);
00427 
00428         int sizeOfA = A.noCols();
00429 
00430         Matrix B(sizeOfA,sizeOfA);
00431 
00432         for (int i=0; i<sizeOfA; i++) {
00433                 for (int j=0; j<sizeOfA; j++) {
00434                         B(i,j) = sqrt( A(i,j) );
00435                 }
00436         }
00437 
00438         (*theSquareRoot) = B;
00439 
00440         return 0;
00441 }
00442 
00443 
00444 
00445 int
00446 MatrixOperations::computeInverse()
00447 {
00448 
00449         Matrix &A = (*theMatrix);
00450 
00451         // Return the invers matrix B such that A*B=I
00452         int sizeOfA = A.noCols();
00453         Matrix B ( sizeOfA, sizeOfA );
00454         Matrix AB ( sizeOfA, 2*sizeOfA );
00455         int i, j, k;
00456 
00457         // Set up the AB matrix
00458         for ( i=0 ; i<sizeOfA ; i++ )
00459         {
00460                 for ( j=0 ; j<(sizeOfA*2) ; j++ )
00461                 {
00462                         if ( j < sizeOfA )
00463                         {
00464                                 AB(i,j) = A(i,j);
00465                         }
00466                         else
00467                         {
00468                                 if ( j == (sizeOfA+i) )
00469                                 {
00470                                         AB(i,j) = 1.0;
00471                                 }
00472                                 else
00473                                 {
00474                                         AB(i,j) = 0.0;
00475                                 }
00476                         }
00477                 }
00478         }
00479 
00480         // The Gauss-Jordan method
00481         double pivot;
00482         double ABii;
00483 
00484         for ( k=0 ; k<sizeOfA ; k++ )
00485         {
00486                 for ( i=k ; i<sizeOfA ; i++ )
00487                 {
00488                         ABii = AB(i,i);
00489                         pivot = AB(i,k);
00490                         for ( j=k ; j<(sizeOfA*2) ; j++ )
00491                         {
00492                                 if ( i == k )
00493                                 {
00494                                         AB(i,j) = AB(i,j) / ABii;
00495                                 }
00496                                 else
00497                                 {
00498                                         AB(i,j) = AB(i,j) - pivot * AB(k,j);
00499                                 }
00500                         }
00501                 }
00502         }
00503         for ( k=1 ; k<sizeOfA ; k++ )
00504         {
00505                 for ( i=k ; i<sizeOfA ; i++ )
00506                 {
00507                         pivot = AB( (sizeOfA-i-1), (sizeOfA-k) );
00508                         for ( j=(sizeOfA-k) ; j<(sizeOfA*2) ; j++ )
00509                         {
00510                                         AB((sizeOfA-i-1),(j)) = 
00511                                                 AB((sizeOfA-i-1),(j)) - 
00512                                                 pivot * AB((sizeOfA-k),(j));
00513                         }
00514                 }
00515         }
00516 
00517 
00518         // Collect the B matrix
00519         for ( i=0 ; i<sizeOfA ; i++ )
00520         {
00521                 for ( j=sizeOfA ; j<(sizeOfA*2) ; j++ )
00522                 {
00523                         B(i,(j-sizeOfA)) = AB(i,j);
00524                 }
00525         }
00526 
00527         (*theInverse) = B;
00528         
00529         return 0;
00530 }
00531 
00532 
00533 
00534 int
00535 MatrixOperations::computeMatrixNorm()
00536 {
00537         Matrix &passedMatrix = (*theMatrix);
00538 
00539         int numberOfColumns = passedMatrix.noCols();
00540         int numberOfRows = passedMatrix.noRows();
00541         double sum = 0;
00542         for ( int i=0 ; i<numberOfRows ; i++ )
00543         {
00544                 for ( int j=0 ; j<numberOfColumns ; j++ )
00545                 {
00546                         sum += passedMatrix(i,j) * passedMatrix(i,j);
00547                 }
00548         }
00549 
00550         theMatrixNorm = sqrt(sum);
00551 
00552         return 0;
00553 }
00554 
00555 
00556 int
00557 MatrixOperations::computeTrace()
00558 {
00559         Matrix &passedMatrix = (*theMatrix);
00560 
00561         int numberOfColumns = passedMatrix.noCols();
00562         int numberOfRows = passedMatrix.noRows();
00563         
00564         if (numberOfColumns != numberOfRows) {
00565                 opserr << "MatrixOperations::computeTrace() - can not" << endln
00566                         << " compute the trace of a non-quadratic matrix." << endln;
00567                 return -1;
00568         }
00569 
00570         double product = 1.0;
00571         for ( int i=0 ; i<numberOfRows ; i++ )
00572         {
00573                 product = product * passedMatrix(i,i);
00574         }
00575 
00576         theTrace = product;
00577 
00578         return 0;
00579 }
00580 
00581 
00582 
00583 
00584 
00585 /*
00586 double
00587 MatrixOperations::vectorDotProduct(Vector vector1, Vector vector2)
00588 {
00589         int sizeOfVector1 = vector1.Size();
00590         int sizeOfVector2 = vector2.Size();
00591         double sum = 0;
00592 
00593         if ( sizeOfVector1 != sizeOfVector2 )
00594         {
00595                 opserr << "vectorDotProduct can not be performed" << endln;
00596         }
00597         else
00598         {
00599                 for ( int i=0 ; i<sizeOfVector1 ; i++ )
00600                 {
00601                         sum += vector1(i) * vector2(i);
00602                 }
00603         }
00604 
00605         return sum;
00606 }
00607 */
00608 
00609 
00610 /*
00611 Vector 
00612 MatrixOperations::matrixTimesVector(Matrix passedMatrix, Vector passedVector)
00613 {
00614         int numberOfMatrixRows = passedMatrix.noRows();
00615         int sizeOfPassedVector = passedVector.Size();
00616         Vector result(numberOfMatrixRows);
00617         int i, j;
00618         double sum;
00619 
00620         for ( i=0 ; i<numberOfMatrixRows ; i++ )
00621         {
00622                 sum = 0.0;
00623                 for ( j=0 ; j<sizeOfPassedVector ; j++ )
00624                 {
00625                         sum += passedMatrix(i,j) * passedVector(j);
00626                 }
00627                 result(i) = sum;
00628         }
00629 
00630         return result;
00631 }
00632 */

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