00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00080 delete theMatrix;
00081 delete theLowerCholesky;
00082 delete theInverseLowerCholesky;
00083 delete theInverse;
00084 delete theTranspose;
00085 delete theSquareRoot;
00086
00087
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
00192
00193
00194
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
00254
00255
00256
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
00307
00308
00309
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
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
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
00452 int sizeOfA = A.noCols();
00453 Matrix B ( sizeOfA, sizeOfA );
00454 Matrix AB ( sizeOfA, 2*sizeOfA );
00455 int i, j, k;
00456
00457
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
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
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
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632