Matrix.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.12 $
00022 // $Date: 2003/04/02 22:02:46 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/matrix/Matrix.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/matrix/Matrix.h
00027 //
00028 // Written: fmk 
00029 // Created: 11/96
00030 // Revision: A
00031 //
00032 // Description: This file contains the class implementation for Matrix.
00033 //
00034 // What: "@(#) Matrix.h, revA"
00035 
00036 #include "Matrix.h"
00037 #include "Vector.h"
00038 #include "ID.h"
00039 #include <Tensor.h>
00040 
00041 #include <stdlib.h>
00042 
00043 #define MATRIX_WORK_AREA 400
00044 #define INT_WORK_AREA 20
00045 
00046 int Matrix::sizeDoubleWork = MATRIX_WORK_AREA;
00047 int Matrix::sizeIntWork = INT_WORK_AREA;
00048 double Matrix::MATRIX_NOT_VALID_ENTRY =0.0;
00049 double *Matrix::matrixWork = 0;
00050 int    *Matrix::intWork =0;
00051 
00052 //double *Matrix::matrixWork = (double *)malloc(400*sizeof(double));
00053 
00054 //
00055 // CONSTRUCTORS
00056 //
00057 
00058 Matrix::Matrix()
00059 :numRows(0), numCols(0), dataSize(0), data(0), fromFree(0)
00060 {
00061   // allocate work areas if the first
00062   if (matrixWork == 0) {
00063     matrixWork = new double[sizeDoubleWork];
00064     intWork = new int[sizeIntWork];
00065     if (matrixWork == 0 || intWork == 0) {
00066       opserr << "WARNING: Matrix::Matrix() - out of memory creating work area's\n";
00067       exit(-1);
00068     }
00069   }
00070 }
00071 
00072 
00073 Matrix::Matrix(int nRows,int nCols)
00074 :numRows(nRows), numCols(nCols), dataSize(0), data(0), fromFree(0)
00075 {
00076 
00077   // allocate work areas if the first matrix
00078   if (matrixWork == 0) {
00079     matrixWork = new double[sizeDoubleWork];
00080     intWork = new int[sizeIntWork];
00081     if (matrixWork == 0 || intWork == 0) {
00082       opserr << "WARNING: Matrix::Matrix() - out of memory creating work area's\n";
00083       exit(-1);
00084     }
00085   }
00086 
00087 #ifdef _G3DEBUG
00088     if (nRows < 0) {
00089       opserr << "WARNING: Matrix::Matrix(int,int): tried to init matrix ";
00090       opserr << "with num rows: " << nRows << " <0\n";
00091       numRows = 0; numCols =0; dataSize =0; data = 0;
00092     }
00093     if (nCols < 0) {
00094       opserr << "WARNING: Matrix::Matrix(int,int): tried to init matrix";
00095       opserr << "with num cols: " << nCols << " <0\n";
00096       numRows = 0; numCols =0; dataSize =0; data = 0;
00097     }
00098 #endif
00099     dataSize = numRows * numCols;
00100     data = 0;
00101 
00102     if (dataSize > 0) {
00103       data = new double[dataSize];
00104       //data = (double *)malloc(dataSize*sizeof(double));
00105       if (data == 0) {
00106         opserr << "WARNING:Matrix::Matrix(int,int): Ran out of memory on init ";
00107         opserr << "of size " << dataSize << endln;
00108         numRows = 0; numCols =0; dataSize =0;
00109       } else {
00110         // zero the data
00111         double *dataPtr = data;
00112         for (int i=0; i<dataSize; i++)
00113           *dataPtr++ = 0.0;
00114       }
00115     }
00116 }
00117 
00118 Matrix::Matrix(double *theData, int row, int col) 
00119 :numRows(row),numCols(col),dataSize(row*col),data(theData),fromFree(1)
00120 {
00121   // allocate work areas if the first matrix
00122   if (matrixWork == 0) {
00123     matrixWork = new double[sizeDoubleWork];
00124     intWork = new int[sizeIntWork];
00125     if (matrixWork == 0 || intWork == 0) {
00126       opserr << "WARNING: Matrix::Matrix() - out of memory creating work area's\n";
00127       exit(-1);
00128     }
00129   }
00130 
00131 #ifdef _G3DEBUG
00132     if (row < 0) {
00133       opserr << "WARNING: Matrix::Matrix(int,int): tried to init matrix with numRows: ";
00134       opserr << row << " <0\n";
00135       numRows = 0; numCols =0; dataSize =0; data = 0;
00136     }
00137     if (col < 0) {
00138       opserr << "WARNING: Matrix::Matrix(int,int): tried to init matrix with numCols: ";
00139       opserr << col << " <0\n";
00140       numRows = 0; numCols =0; dataSize =0; data = 0;
00141     }    
00142 #endif
00143 
00144     // does nothing
00145 }
00146 
00147 Matrix::Matrix(const Matrix &other)
00148 :numRows(0), numCols(0), dataSize(0), data(0), fromFree(0)
00149 {
00150   // allocate work areas if the first matrix
00151   if (matrixWork == 0) {
00152     matrixWork = new double[sizeDoubleWork];
00153     intWork = new int[sizeIntWork];
00154     if (matrixWork == 0 || intWork == 0) {
00155       opserr << "WARNING: Matrix::Matrix() - out of memory creating work area's\n";
00156       exit(-1);
00157     }
00158   }
00159 
00160     numRows = other.numRows;
00161     numCols = other.numCols;
00162     dataSize = other.dataSize;
00163 
00164     if (dataSize != 0) {
00165       data = new double[dataSize];
00166       // data = (double *)malloc(dataSize*sizeof(double));
00167       if (data == 0) {
00168         opserr << "WARNING:Matrix::Matrix(Matrix &): ";
00169         opserr << "Ran out of memory on init of size " << dataSize << endln; 
00170         numRows = 0; numCols =0; dataSize = 0;
00171       } else {
00172         // copy the data
00173         double *dataPtr = data;
00174         double *otherDataPtr = other.data;
00175         for (int i=0; i<dataSize; i++)
00176           *dataPtr++ = *otherDataPtr++;
00177       }
00178     }
00179 }
00180 
00181 
00182 //
00183 // DESTRUCTOR
00184 //
00185 
00186 Matrix::~Matrix()
00187 {
00188   if (data != 0) 
00189     if (fromFree == 0)
00190       delete [] data; 
00191   //  if (data != 0) free((void *) data);
00192 }
00193     
00194 
00195 //
00196 // METHODS - Zero, Assemble, Solve
00197 //
00198 
00199 int
00200 Matrix::setData(double *theData, int row, int col) 
00201 {
00202   // delete the old if allocated
00203   if (data != 0) 
00204     if (fromFree == 0)
00205       delete [] data; 
00206 
00207   numRows = row;
00208   numCols = col;
00209   dataSize = row*col;
00210   data = theData;
00211   fromFree = 1;
00212 
00213 #ifdef _G3DEBUG
00214   if (row < 0) {
00215     opserr << "WARNING: Matrix::setSize(): tried to init matrix with numRows: ";
00216     opserr << row << " <0\n";
00217     numRows = 0; numCols =0; dataSize =0; data = 0;
00218     return -1;
00219   }
00220   if (col < 0) {
00221     opserr << "WARNING: Matrix::setSize(): tried to init matrix with numCols: ";
00222     opserr << col << " <0\n";
00223     numRows = 0; numCols =0; dataSize =0; data = 0;
00224     return -1;
00225   }    
00226 #endif
00227   
00228   return 0;
00229 }
00230 
00231 void
00232 Matrix::Zero(void)
00233 {
00234   double *dataPtr = data;
00235   for (int i=0; i<dataSize; i++)
00236     *dataPtr++ = 0;
00237 }
00238 
00239 
00240 int
00241 Matrix::resize(int rows, int cols) {
00242 
00243   int newSize = rows*cols;
00244 
00245   if (newSize <= 0) {
00246     opserr << "Matrix::resize) - rows " << rows << " or cols " << cols << " specified <= 0\n";
00247     return -1;
00248   }
00249 
00250   else if (newSize > dataSize) {
00251 
00252     // free the old space
00253     if (data != 0) 
00254       if (fromFree == 0)
00255         delete [] data; 
00256     //  if (data != 0) free((void *) data);
00257 
00258     fromFree = 0;
00259     // create new space
00260     data = new double[newSize];
00261     // data = (double *)malloc(dataSize*sizeof(double));
00262     if (data == 0) {
00263       opserr << "Matrix::resize(" << rows << "," << cols << ") - out of memory\n";
00264       numRows = 0; numCols =0; dataSize = 0;
00265       return -2;
00266     }
00267     dataSize = newSize;
00268     numRows = rows;
00269     numCols = cols;
00270   }
00271 
00272   // just reset the cols and rows - save two memory calls at expense of holding 
00273   // onto extra memory
00274   else {
00275     numRows = rows;
00276     numCols = cols;
00277   }
00278 
00279   return 0;
00280 }
00281 
00282 
00283 
00284 
00285 
00286 int
00287 Matrix::Assemble(const Matrix &V, const ID &rows, const ID &cols, double fact) 
00288 {
00289   int pos_Rows, pos_Cols;
00290   int res = 0;
00291 
00292   for (int i=0; i<cols.Size(); i++) {
00293     pos_Cols = cols(i);
00294     for (int j=0; j<rows.Size(); j++) {
00295       pos_Rows = rows(j);
00296       
00297       if ((pos_Cols >= 0) && (pos_Rows >= 0) && (pos_Rows < numRows) &&
00298           (pos_Cols < numCols) && (i < V.numCols) && (j < V.numRows))
00299         (*this)(pos_Rows,pos_Cols) += V(j,i)*fact;
00300       else {
00301         opserr << "WARNING: Matrix::Assemble(const Matrix &V, const ID &l): ";
00302         opserr << " - position (" << pos_Rows << "," << pos_Cols << ") outside bounds \n";
00303         res = -1;
00304       }
00305     }
00306   }
00307 
00308   return res;
00309 }
00310 
00311 #ifdef _WIN32
00312 extern "C" int  DGESV(int *N, int *NRHS, double *A, int *LDA, 
00313                               int *iPiv, double *B, int *LDB, int *INFO);
00314 
00315 extern "C" int  DGETRF(int *M, int *N, double *A, int *LDA, 
00316                               int *iPiv, int *INFO);
00317 
00318 extern "C" int  DGETRS(char *TRANS, unsigned int sizeT,
00319                                int *N, int *NRHS, double *A, int *LDA, 
00320                                int *iPiv, double *B, int *LDB, int *INFO);
00321 
00322 extern "C" int  DGETRI(int *N, double *A, int *LDA, 
00323                               int *iPiv, double *Work, int *WORKL, int *INFO);
00324 
00325 #else
00326 extern "C" int dgesv_(int *N, int *NRHS, double *A, int *LDA, int *iPiv, 
00327                       double *B, int *LDB, int *INFO);
00328 
00329 extern "C" int dgetrs_(char *TRANS, int *N, int *NRHS, double *A, int *LDA, 
00330                        int *iPiv, double *B, int *LDB, int *INFO);                     
00331 
00332 extern "C" int dgetrf_(int *M, int *N, double *A, int *LDA, 
00333                        int *iPiv, int *INFO);
00334 
00335 extern "C" int dgetri_(int *N, double *A, int *LDA, 
00336                        int *iPiv, double *Work, int *WORKL, int *INFO);
00337 extern "C" int dgerfs_(char *TRANS, int *N, int *NRHS, double *A, int *LDA, 
00338                        double *AF, int *LDAF, int *iPiv, double *B, int *LDB, 
00339                        double *X, int *LDX, double *FERR, double *BERR, 
00340                        double *WORK, int *IWORK, int *INFO);
00341 
00342 #endif
00343 
00344 int
00345 Matrix::Solve(const Vector &b, Vector &x) const
00346 {
00347 
00348     int n = numRows;
00349 
00350 #ifdef _G3DEBUG    
00351     if (numRows != numCols) {
00352       opserr << "Matrix::Solve(b,x) - the matrix of dimensions " 
00353              << numRows << ", " << numCols << " is not square " << endln;
00354       return -1;
00355     }
00356 
00357     if (n != x.Size()) {
00358       opserr << "Matrix::Solve(b,x) - dimension of x, " << numRows << "is not same as matrix " <<  x.Size() << endln;
00359       return -2;
00360     }
00361 
00362     if (n != b.Size()) {
00363       opserr << "Matrix::Solve(b,x) - dimension of x, " << numRows << "is not same as matrix " <<  b.Size() << endln;
00364       return -2;
00365     }
00366 #endif
00367     
00368     // check work area can hold all the data
00369     if (dataSize > sizeDoubleWork) {
00370 
00371       if (matrixWork != 0) {
00372         delete [] matrixWork;
00373       }
00374       matrixWork = new double[dataSize];
00375       sizeDoubleWork = dataSize;
00376       
00377       if (matrixWork == 0) {
00378         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00379         sizeDoubleWork = 0;      
00380         return -3;
00381       }
00382     }
00383 
00384     // check work area can hold all the data
00385     if (n > sizeIntWork) {
00386 
00387       if (intWork != 0) {
00388         delete [] intWork;
00389       }
00390       intWork = new int[n];
00391       sizeIntWork = n;
00392       
00393       if (intWork == 0) {
00394         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00395         sizeIntWork = 0;      
00396         return -3;
00397       }
00398     }
00399 
00400     
00401     // copy the data
00402     int i;
00403     for (i=0; i<dataSize; i++)
00404       matrixWork[i] = data[i];
00405 
00406     // set x equal to b
00407     x = b;
00408 
00409     int nrhs = 1;
00410     int ldA = n;
00411     int ldB = n;
00412     int info;
00413     double *Aptr = matrixWork;
00414     double *Xptr = x.theData;
00415     int *iPIV = intWork;
00416     
00417 
00418 #ifdef _WIN32
00419     DGESV(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00420 #else
00421     dgesv_(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00422 #endif
00423 
00424     
00425 
00426     return 0;
00427 }
00428 
00429 
00430 int
00431 Matrix::Solve(const Matrix &b, Matrix &x) const
00432 {
00433 
00434     int n = numRows;
00435     int nrhs = x.numCols;
00436 
00437 #ifdef _G3DEBUG    
00438     if (numRows != numCols) {
00439       opserr << "Matrix::Solve(B,X) - the matrix of dimensions [" << numRows << " " <<  numCols << "] is not square\n";
00440       return -1;
00441     }
00442 
00443     if (n != x.numRows) {
00444       opserr << "Matrix::Solve(B,X) - #rows of X, " << x.numRows << " is not same as the matrices: " << numRows << endln;
00445       return -2;
00446     }
00447 
00448     if (n != b.numRows) {
00449       opserr << "Matrix::Solve(B,X) - #rows of B, " << b.numRows << " is not same as the matrices: " << numRows << endln;
00450       return -2;
00451     }
00452 
00453     if (x.numCols != b.numCols) {
00454       opserr << "Matrix::Solve(B,X) - #cols of B, " << b.numCols << " , is not same as that of X, b " <<  x.numCols << endln;
00455       return -3;
00456     }
00457 #endif
00458 
00459     // check work area can hold all the data
00460     if (dataSize > sizeDoubleWork) {
00461 
00462       if (matrixWork != 0) {
00463         delete [] matrixWork;
00464       }
00465       matrixWork = new double[dataSize];
00466       sizeDoubleWork = dataSize;
00467       
00468       if (matrixWork == 0) {
00469         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00470         sizeDoubleWork = 0;      
00471         return -3;
00472       }
00473     }
00474 
00475     // check work area can hold all the data
00476     if (n > sizeIntWork) {
00477 
00478       if (intWork != 0) {
00479         delete [] intWork;
00480       }
00481       intWork = new int[n];
00482       sizeIntWork = n;
00483       
00484       if (intWork == 0) {
00485         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00486         sizeIntWork = 0;      
00487         return -3;
00488       }
00489     }
00490     
00491     x = b;
00492 
00493     // copy the data
00494     int i;
00495     for (i=0; i<dataSize; i++)
00496       matrixWork[i] = data[i];
00497 
00498 
00499     int ldA = n;
00500     int ldB = n;
00501     int info;
00502     double *Aptr = matrixWork;
00503     double *Xptr = x.data;
00504     
00505     int *iPIV = intWork;
00506     
00507 
00508 #ifdef _WIN32
00509     DGESV(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00510 #else
00511     dgesv_(&n,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info);
00512 
00513     /*
00514     // further correction if required
00515     double Bptr[n*n];
00516     for (int i=0; i<n*n; i++) Bptr[i] = b.data[i];
00517     double *origData = data;
00518     double Ferr[n];
00519     double Berr[n];
00520     double newWork[3*n];
00521     int newIwork[n];
00522     
00523     dgerfs_("N",&n,&n,origData,&ldA,Aptr,&n,iPIV,Bptr,&ldB,Xptr,&ldB,
00524             Ferr, Berr, newWork, newIwork, &info);
00525     */
00526 #endif
00527 
00528     return info;
00529 }
00530 
00531 
00532 int
00533 Matrix::Invert(Matrix &theInverse) const
00534 {
00535 
00536     int n = numRows;
00537     int nrhs = theInverse.numCols;
00538 
00539 #ifdef _G3DEBUG    
00540     if (numRows != numCols) {
00541       opserr << "Matrix::Solve(B,X) - the matrix of dimensions [" << numRows << "," << numCols << "] is not square\n";
00542       return -1;
00543     }
00544 
00545     if (n != theInverse.numRows) {
00546       opserr << "Matrix::Solve(B,X) - #rows of X, " << numRows<< ", is not same as matrix " << theInverse.numRows << endln;
00547       return -2;
00548     }
00549 #endif
00550 
00551     // check work area can hold all the data
00552     if (dataSize > sizeDoubleWork) {
00553 
00554       if (matrixWork != 0) {
00555         delete [] matrixWork;
00556       }
00557       matrixWork = new double[dataSize];
00558       sizeDoubleWork = dataSize;
00559       
00560       if (matrixWork == 0) {
00561         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00562         sizeDoubleWork = 0;      
00563         return -3;
00564       }
00565     }
00566 
00567     // check work area can hold all the data
00568     if (n > sizeIntWork) {
00569 
00570       if (intWork != 0) {
00571         delete [] intWork;
00572       }
00573       intWork = new int[n];
00574       sizeIntWork = n;
00575       
00576       if (intWork == 0) {
00577         opserr << "WARNING: Matrix::Solve() - out of memory creating work area's\n";
00578         sizeIntWork = 0;      
00579         return -3;
00580       }
00581     }
00582     
00583     // copy the data
00584     theInverse = *this;
00585     
00586     for (int i=0; i<dataSize; i++)
00587       matrixWork[i] = data[i];
00588 
00589     int ldA = n;
00590     int ldB = n;
00591     int info;
00592     double *Wptr = matrixWork;
00593     double *Aptr = theInverse.data;
00594     int workSize = sizeDoubleWork;
00595     
00596     int *iPIV = intWork;
00597     
00598 
00599 #ifdef _WIN32
00600     DGETRF(&n,&n,Aptr,&ldA,iPIV,&info);
00601     if (info != 0) 
00602       return info;
00603     
00604     DGETRI(&n,Aptr,&ldA,iPIV,Wptr,&workSize,&info);
00605 #else
00606     dgetrf_(&n,&n,Aptr,&ldA,iPIV,&info);
00607     if (info != 0) 
00608       return info;
00609     
00610     dgetri_(&n,Aptr,&ldA,iPIV,Wptr,&workSize,&info);
00611     
00612 #endif
00613 
00614     return info;
00615 }
00616     
00617                     
00618 
00619 int
00620 Matrix::addMatrix(double factThis, const Matrix &other, double factOther)
00621 {
00622     if (factThis == 1.0 && factOther == 0.0)
00623       return 0;
00624 
00625 #ifdef _G3DEBUG
00626     if ((other.numRows != numRows) || (other.numCols != numCols)) {
00627       opserr << "Matrix::addMatrix(): incompatable matrices\n";
00628       return -1;
00629     }
00630 #endif
00631 
00632     if (factThis == 1.0) {
00633 
00634       // want: this += other * factOther
00635       if (factOther == 1.0) {
00636         double *dataPtr = data;
00637         double *otherDataPtr = other.data;                  
00638         for (int i=0; i<dataSize; i++)
00639           *dataPtr++ += *otherDataPtr++;
00640       } else {
00641         double *dataPtr = data;
00642         double *otherDataPtr = other.data;                  
00643         for (int i=0; i<dataSize; i++)
00644           *dataPtr++ += *otherDataPtr++ * factOther;
00645       }
00646     } 
00647 
00648     else if (factThis == 0.0) {
00649 
00650       // want: this = other * factOther
00651       if (factOther == 1.0) {
00652         double *dataPtr = data;
00653         double *otherDataPtr = other.data;                  
00654         for (int i=0; i<dataSize; i++)
00655           *dataPtr++ = *otherDataPtr++;
00656       } else {
00657         double *dataPtr = data;
00658         double *otherDataPtr = other.data;                  
00659         for (int i=0; i<dataSize; i++)
00660           *dataPtr++ = *otherDataPtr++ * factOther;
00661       }
00662     } 
00663 
00664     else {
00665 
00666       // want: this = this * thisFact + other * factOther
00667       if (factOther == 1.0) {
00668         double *dataPtr = data;
00669         double *otherDataPtr = other.data;                  
00670         for (int i=0; i<dataSize; i++) {
00671           double value = *dataPtr * factThis + *otherDataPtr++;
00672           *dataPtr++ = value;
00673         }
00674       } else {
00675         double *dataPtr = data;
00676         double *otherDataPtr = other.data;                  
00677         for (int i=0; i<dataSize; i++) {
00678           double value = *dataPtr * factThis + *otherDataPtr++ * factOther;
00679           *dataPtr++ = value;
00680         }
00681       }
00682     } 
00683 
00684     // successfull
00685     return 0;
00686 }
00687 
00688 
00689 
00690 int
00691 Matrix::addMatrixProduct(double thisFact, 
00692                          const Matrix &B, 
00693                          const Matrix &C, 
00694                          double otherFact)
00695 {
00696     if (thisFact == 1.0 && otherFact == 0.0)
00697       return 0;
00698 #ifdef _G3DEBUG
00699     if ((B.numRows != numRows) || (C.numCols != numCols) || (B.numCols != C.numRows)) {
00700       opserr << "Matrix::addMatrixProduct(): incompatable matrices, this\n";
00701       return -1;
00702     }
00703 #endif
00704     // NOTE: looping as per blas3 dgemm_: j,k,i
00705     if (thisFact == 1.0) {
00706 
00707       // want: this += B * C  otherFact
00708       int numColB = B.numCols;
00709       double *ckjPtr  = &(C.data)[0];
00710       for (int j=0; j<numCols; j++) {
00711         double *aijPtrA = &data[j*numRows];
00712         for (int k=0; k<numColB; k++) {
00713           double tmp = *ckjPtr++ * otherFact;
00714           double *aijPtr = aijPtrA;
00715           double *bikPtr = &(B.data)[k*numRows];
00716           for (int i=0; i<numRows; i++)
00717             *aijPtr++ += *bikPtr++ * tmp;
00718         }
00719       }
00720     }
00721 
00722     else if (thisFact == 0.0) {
00723 
00724       // want: this = B * C  otherFact
00725       double *dataPtr = data;
00726       for (int i=0; i<dataSize; i++)
00727           *dataPtr++ = 0.0;
00728       int numColB = B.numCols;
00729       double *ckjPtr  = &(C.data)[0];
00730       for (int j=0; j<numCols; j++) {
00731         double *aijPtrA = &data[j*numRows];
00732         for (int k=0; k<numColB; k++) {
00733           double tmp = *ckjPtr++ * otherFact;
00734           double *aijPtr = aijPtrA;
00735           double *bikPtr = &(B.data)[k*numRows];
00736           for (int i=0; i<numRows; i++)
00737             *aijPtr++ += *bikPtr++ * tmp;
00738         }
00739       }
00740     } 
00741 
00742     else {
00743       // want: this = B * C  otherFact
00744       double *dataPtr = data;
00745       for (int i=0; i<dataSize; i++)
00746           *dataPtr++ *= thisFact;
00747       int numColB = B.numCols;
00748       double *ckjPtr  = &(C.data)[0];
00749       for (int j=0; j<numCols; j++) {
00750         double *aijPtrA = &data[j*numRows];
00751         for (int k=0; k<numColB; k++) {
00752           double tmp = *ckjPtr++ * otherFact;
00753           double *aijPtr = aijPtrA;
00754           double *bikPtr = &(B.data)[k*numRows];
00755           for (int i=0; i<numRows; i++)
00756             *aijPtr++ += *bikPtr++ * tmp;
00757         }
00758       }
00759     } 
00760 
00761     return 0;
00762 }
00763 
00764 
00765 // to perform this += T' * B * T
00766 int
00767 Matrix::addMatrixTripleProduct(double thisFact, 
00768                                const Matrix &T, 
00769                                const Matrix &B, 
00770                                double otherFact)
00771 {
00772     if (thisFact == 1.0 && otherFact == 0.0)
00773       return 0;
00774 #ifdef _G3DEBUG
00775     if ((numCols != numRows) || (B.numCols != B.numRows) || (T.numCols != numRows) ||
00776         (T.numRows != B.numCols)) {
00777       opserr << "Matrix::addMatrixTripleProduct() - incompatable matrices\n";
00778       return -1;
00779     }
00780 #endif
00781 
00782     // cheack work area can hold the temporary matrix
00783     int dimB = B.numCols;
00784     int sizeWork = dimB * numCols;
00785 
00786     if (sizeWork > sizeDoubleWork) {
00787       this->addMatrix(thisFact, T^B*T, otherFact);
00788       return 0;
00789     }
00790 
00791     // zero out the work area
00792     double *matrixWorkPtr = matrixWork;
00793     for (int l=0; l<sizeWork; l++)
00794       *matrixWorkPtr++ = 0.0;
00795 
00796     // now form B * T * fact store in matrixWork == A area
00797     // NOTE: looping as per blas3 dgemm_: j,k,i
00798 
00799     double *tkjPtr  = &(T.data)[0];
00800     for (int j=0; j<numCols; j++) {
00801       double *aijPtrA = &matrixWork[j*dimB];
00802       for (int k=0; k<dimB; k++) {
00803         double tmp = *tkjPtr++ * otherFact;
00804         double *aijPtr = aijPtrA;
00805         double *bikPtr = &(B.data)[k*dimB];
00806         for (int i=0; i<dimB; i++) 
00807           *aijPtr++ += *bikPtr++ * tmp;
00808       }
00809     }
00810 
00811     // now form T' * matrixWork
00812     // NOTE: looping as per blas3 dgemm_: j,i,k
00813     if (thisFact == 1.0) {
00814       double *dataPtr = &data[0];
00815       for (int j=0; j< numCols; j++) {
00816         double *workkjPtrA = &matrixWork[j*dimB];
00817         for (int i=0; i<numRows; i++) {
00818           double *ckiPtr = &(T.data)[i*dimB];
00819           double *workkjPtr = workkjPtrA;
00820           double aij = 0.0;
00821           for (int k=0; k< dimB; k++)
00822             aij += *ckiPtr++ * *workkjPtr++;
00823           *dataPtr++ += aij;
00824         }
00825       }
00826     } else if (thisFact == 0.0) {
00827       double *dataPtr = &data[0];
00828       for (int j=0; j< numCols; j++) {
00829         double *workkjPtrA = &matrixWork[j*dimB];
00830         for (int i=0; i<numRows; i++) {
00831           double *ckiPtr = &(T.data)[i*dimB];
00832           double *workkjPtr = workkjPtrA;
00833           double aij = 0.0;
00834           for (int k=0; k< dimB; k++)
00835             aij += *ckiPtr++ * *workkjPtr++;
00836           *dataPtr++ = aij;
00837         }
00838       }
00839 
00840     } else {
00841       double *dataPtr = &data[0];
00842       for (int j=0; j< numCols; j++) {
00843         double *workkjPtrA = &matrixWork[j*dimB];
00844         for (int i=0; i<numRows; i++) {
00845           double *ckiPtr = &(T.data)[i*dimB];
00846           double *workkjPtr = workkjPtrA;
00847           double aij = 0.0;
00848           for (int k=0; k< dimB; k++)
00849             aij += *ckiPtr++ * *workkjPtr++;
00850           double value = *dataPtr * thisFact + aij;
00851           *dataPtr++ = value;
00852         }
00853       }
00854     }
00855 
00856     return 0;
00857 }
00858 
00859 
00860 
00861 //
00862 // OVERLOADED OPERATOR () to CONSTRUCT A NEW MATRIX
00863 //
00864 
00865 Matrix
00866 Matrix::operator()(const ID &rows, const ID & cols) const
00867 {
00868     int nRows, nCols;
00869     nRows = rows.Size();
00870     nCols = cols.Size();
00871     Matrix result(nRows,nCols);
00872     double *dataPtr = result.data;
00873     for (int i=0; i<nCols; i++)
00874         for (int j=0; j<nRows; j++)
00875             *dataPtr++ = (*this)(rows(j),cols(i));
00876 
00877     return result;
00878 }
00879                 
00880 // Matrix &operator=(const Matrix  &V):
00881 //      the assignment operator, This is assigned to be a copy of V. if sizes
00882 //      are not compatable this.data [] is deleted. The data pointers will not
00883 //      point to the same area in mem after the assignment.
00884 //
00885 
00886 
00887 
00888 Matrix &
00889 Matrix::operator=(const Matrix &other)
00890 {
00891   // first check we are not trying other = other
00892   if (this == &other) 
00893     return *this;
00894 
00895 /*
00896 #ifdef _G3DEBUG    
00897   if ((numCols != other.numCols) || (numRows != other.numRows)) {
00898     opserr << "Matrix::operator=() - matrix dimensions do not match: [%d %d] != [%d %d]\n",
00899                             numRows, numCols, other.numRows, other.numCols);
00900     return *this;
00901   }
00902 #endif
00903 */
00904 
00905   if ((numCols != other.numCols) || (numRows != other.numRows)) {
00906 #ifdef _G3DEBUG    
00907       opserr << "Matrix::operator=() - matrix dimensions do not match\n";
00908 #endif
00909 
00910       if (this->data != 0)
00911           delete [] this->data;
00912       
00913       int theSize = other.numCols*other.numRows;
00914       
00915       data = new double[theSize];
00916       
00917       this->dataSize = theSize;
00918       this->numCols = other.numCols;
00919       this->numRows = other.numRows;
00920   }
00921 
00922 
00923   // now copy the data
00924   double *dataPtr = data;
00925   double *otherDataPtr = other.data;                
00926   for (int i=0; i<dataSize; i++)
00927       *dataPtr++ = *otherDataPtr++;
00928   
00929   return *this;
00930 }
00931 
00932 
00933 
00934 
00935 Matrix &
00936 Matrix::operator=(const Tensor &V)
00937 {
00938   int rank = V.rank();
00939   if (rank != 4) {
00940     opserr << "Matrix::operator=() - tensor must be of rank 4\n";
00941       return *this;
00942   }
00943   int dim = V.dim(1);
00944   if (dim != V.dim(2) != V.dim(3) != V.dim(4)) {
00945       opserr << "Matrix::operator=() - tensor must have square dimensions\n";
00946       return *this;
00947   }
00948 
00949   if (dim != 2 || dim != 3 || dim != 1) {
00950       opserr << "Matrix::operator=() - tensor must be of dimension 2 or 3\n";
00951       return *this;
00952   }      
00953 
00954   if (dim == 1) {
00955     if ((numCols != 1) || (numRows != 1)) {      
00956       opserr << "Matrix::operator=() - matrix must be 1x1 for tensor of dimension 3\n";
00957       return *this;
00958     }             
00959     (*this)(0,0) = V.cval(1,1,1,1);
00960     
00961   } else if (dim == 2) {
00962     if ((numCols != 3) || (numRows != 3)) {      
00963       opserr << "Matrix::operator=() - matrix must be 1x1 for tensor of dimension 3\n";      
00964       
00965       return *this;
00966     }
00967     (*this)(0,0) = V.cval(1,1,1,1);
00968     (*this)(0,1) = V.cval(1,1,2,2);
00969     (*this)(0,2) = V.cval(1,1,1,2);      
00970     
00971     (*this)(1,0) = V.cval(2,2,1,1);
00972     (*this)(1,1) = V.cval(2,2,2,2);
00973     (*this)(1,2) = V.cval(2,2,1,2);      
00974     
00975     (*this)(2,0) = V.cval(1,2,1,1);
00976     (*this)(2,1) = V.cval(1,2,2,2);
00977     (*this)(2,2) = V.cval(1,2,1,2);            
00978     
00979   } else {
00980     if ((numCols != 6) || (numRows != 6)) {      
00981       opserr << "Matrix::operator=() - matrix must be 1x1 for tensor of dimension 3\n";      
00982         
00983       return *this;
00984     }      
00985     (*this)(0,0) = V.cval(1,1,1,1);
00986     (*this)(0,1) = V.cval(1,1,2,2);
00987     (*this)(0,2) = V.cval(1,1,3,3);      
00988     (*this)(0,3) = V.cval(1,1,1,2);
00989     (*this)(0,4) = V.cval(1,1,1,3);
00990     (*this)(0,5) = V.cval(1,1,2,3);      
00991     
00992     (*this)(1,0) = V.cval(2,2,1,1);
00993     (*this)(1,1) = V.cval(2,2,2,2);
00994     (*this)(1,2) = V.cval(2,2,3,3);      
00995     (*this)(1,3) = V.cval(2,2,1,2);
00996     (*this)(1,4) = V.cval(2,2,1,3);
00997     (*this)(1,5) = V.cval(2,2,2,3);            
00998     
00999     (*this)(2,0) = V.cval(3,3,1,1);
01000     (*this)(2,1) = V.cval(3,3,2,2);
01001     (*this)(2,2) = V.cval(3,3,3,3);      
01002     (*this)(2,3) = V.cval(3,3,1,2);
01003     (*this)(2,4) = V.cval(3,3,1,3);
01004     (*this)(2,5) = V.cval(3,3,2,3);                  
01005     
01006     (*this)(3,0) = V.cval(1,2,1,1);
01007     (*this)(3,1) = V.cval(1,2,2,2);
01008     (*this)(3,2) = V.cval(1,2,3,3);      
01009     (*this)(3,3) = V.cval(1,2,1,2);
01010     (*this)(3,4) = V.cval(1,2,1,3);
01011     (*this)(3,5) = V.cval(1,2,2,3);                        
01012     
01013     (*this)(4,0) = V.cval(1,3,1,1);
01014     (*this)(4,1) = V.cval(1,3,2,2);
01015     (*this)(4,2) = V.cval(1,3,3,3);      
01016     (*this)(4,3) = V.cval(1,3,1,2);
01017     (*this)(4,4) = V.cval(1,3,1,3);
01018     (*this)(4,5) = V.cval(1,3,2,3);                              
01019     
01020     (*this)(5,0) = V.cval(2,3,1,1);
01021     (*this)(5,1) = V.cval(2,3,2,2);
01022     (*this)(5,2) = V.cval(2,3,3,3);      
01023     (*this)(5,3) = V.cval(2,3,1,2);
01024     (*this)(5,4) = V.cval(2,3,1,3);
01025     (*this)(5,5) = V.cval(2,3,2,3);                                    
01026   }
01027   return *this;
01028 }
01029 
01030 
01031 // virtual Matrix &operator+=(double fact);
01032 // virtual Matrix &operator-=(double fact);
01033 // virtual Matrix &operator*=(double fact);
01034 // virtual Matrix &operator/=(double fact); 
01035 //      The above methods all modify the current matrix. If in
01036 //      derived matrices data kept in data and of sizeData no redef necessary.
01037 
01038 Matrix &
01039 Matrix::operator+=(double fact)
01040 {
01041   // check if quick return
01042   if (fact == 0.0)
01043     return *this;
01044 
01045   double *dataPtr = data;
01046   for (int i=0; i<dataSize; i++)
01047     *dataPtr++ += fact;
01048   
01049   return *this;
01050 }
01051 
01052 
01053 
01054 
01055 Matrix &
01056 Matrix::operator-=(double fact)
01057 {
01058   // check if quick return
01059   if (fact == 0.0)
01060     return *this;
01061   
01062   double *dataPtr = data;
01063   for (int i=0; i<dataSize; i++)
01064     *dataPtr++ -= fact;
01065 
01066   return *this;
01067 }
01068 
01069 
01070 Matrix &
01071 Matrix::operator*=(double fact)
01072 {
01073   // check if quick return
01074   if (fact == 1.0)
01075     return *this;
01076   
01077   double *dataPtr = data;
01078   for (int i=0; i<dataSize; i++)
01079     *dataPtr++ *= fact;
01080   
01081   return *this;
01082 }
01083 
01084 Matrix &
01085 Matrix::operator/=(double fact)
01086 {
01087     // check if quick return
01088     if (fact == 1.0)
01089         return *this;
01090 
01091     if (fact != 0.0) {
01092       double val = 1.0/fact;
01093 
01094       double *dataPtr = data;
01095       for (int i=0; i<dataSize; i++)
01096         *dataPtr++ *= val;
01097 
01098       return *this;
01099     } else {
01100       // print out the warining message
01101       opserr << "WARNING:Matrix::operator/= - 0 factor specified all values in Matrix set to ";
01102       opserr << MATRIX_VERY_LARGE_VALUE << endln;
01103 
01104       double *dataPtr = data;
01105       for (int i=0; i<dataSize; i++)
01106         *dataPtr++ = MATRIX_VERY_LARGE_VALUE;
01107       
01108       return *this;
01109     }
01110 }
01111 
01112 
01113 //    virtual Matrix operator+(double fact);
01114 //    virtual Matrix operator-(double fact);
01115 //    virtual Matrix operator*(double fact);
01116 //    virtual Matrix operator/(double fact);
01117 //      The above methods all return a new full general matrix.
01118 
01119 Matrix
01120 Matrix::operator+(double fact) const
01121 {
01122     Matrix result(*this);
01123     result += fact;
01124     return result;
01125 }
01126 
01127 Matrix
01128 Matrix::operator-(double fact) const
01129 {
01130     Matrix result(*this);
01131     result -= fact;
01132     return result;
01133 }
01134 
01135 Matrix
01136 Matrix::operator*(double fact) const
01137 {
01138     Matrix result(*this);
01139     result *= fact;
01140     return result;
01141 }
01142 
01143 Matrix
01144 Matrix::operator/(double fact) const
01145 {
01146     if (fact == 0.0) {
01147         opserr << "Matrix::operator/(const double &fact): ERROR divide-by-zero\n";
01148         exit(0);
01149     }
01150     Matrix result(*this);
01151     result /= fact;
01152     return result;
01153 }
01154 
01155 
01156 //
01157 // MATRIX_VECTOR OPERATIONS
01158 //
01159 
01160 Vector
01161 Matrix::operator*(const Vector &V) const
01162 {
01163     Vector result(numRows);
01164     
01165     if (V.Size() != numCols) {
01166         opserr << "Matrix::operator*(Vector): incompatable sizes\n";
01167         return result;
01168     } 
01169     
01170     double *dataPtr = data;
01171     for (int i=0; i<numCols; i++)
01172       for (int j=0; j<numRows; j++)
01173         result(j) += *dataPtr++ * V(i);
01174 
01175     /*
01176     opserr << "HELLO: " << V;
01177     for (int i=0; i<numRows; i++) {
01178         double sum = 0.0;
01179         for (int j=0; j<numCols; j++) {
01180             sum += (*this)(i,j) * V(j);
01181             if (i == 9) opserr << "sum: " << sum << " " << (*this)(i,j)*V(j) << " " << V(j) << 
01182 ;
01183         }
01184         result(i) += sum;
01185     }
01186     opserr << *this;
01187     opserr << "HELLO result: " << result;    
01188     */
01189 
01190     return result;
01191 }
01192 
01193 Vector
01194 Matrix::operator^(const Vector &V) const
01195 {
01196     Vector result(numCols);
01197     
01198     if (V.Size() != numRows) {
01199       opserr << "Matrix::operator*(Vector): incompatable sizes\n";
01200       return result;
01201     } 
01202 
01203     double *dataPtr = data;
01204     for (int i=0; i<numCols; i++)
01205       for (int j=0; j<numRows; j++)
01206         result(i) += *dataPtr++ * V(j);
01207 
01208     return result;
01209 }
01210 
01211 
01212 //
01213 // MATRIX - MATRIX OPERATIONS
01214 //
01215             
01216 
01217 Matrix
01218 Matrix::operator+(const Matrix &M) const
01219 {
01220     Matrix result(*this);
01221     result.addMatrix(1.0,M,1.0);    
01222     return result;
01223 }
01224             
01225 Matrix
01226 Matrix::operator-(const Matrix &M) const
01227 {
01228     Matrix result(*this);
01229     result.addMatrix(1.0,M,-1.0);    
01230     return result;
01231 }
01232             
01233     
01234 Matrix
01235 Matrix::operator*(const Matrix &M) const
01236 {
01237     Matrix result(numRows,M.numCols);
01238     
01239     if (numCols != M.numRows || result.numRows != numRows) {
01240         opserr << "Matrix::operator*(Matrix): incompatable sizes\n";
01241         return result;
01242     } 
01243 
01244     result.addMatrixProduct(0.0, *this, M, 1.0);
01245     
01246     /****************************************************
01247     double *resDataPtr = result.data;       
01248 
01249     int innerDim = numCols;
01250     int nCols = result.numCols;
01251     for (int i=0; i<nCols; i++) {
01252       double *aStartRowDataPtr = data;
01253       double *bStartColDataPtr = &(M.data[i*innerDim]);
01254       for (int j=0; j<numRows; j++) {
01255         double *bDataPtr = bStartColDataPtr;
01256         double *aDataPtr = aStartRowDataPtr +j;     
01257         double sum = 0.0;
01258         for (int k=0; k<innerDim; k++) {
01259           sum += *aDataPtr * *bDataPtr++;
01260           aDataPtr += numRows;
01261         }
01262         *resDataPtr++ = sum;
01263       }
01264     }
01265     ******************************************************/
01266     return result;
01267 }
01268 
01269 
01270 
01271 // Matrix operator^(const Matrix &M) const
01272 //      We overload the * operator to perform matrix^t-matrix multiplication.
01273 //      reults = (*this)transposed * M.
01274 
01275 Matrix
01276 Matrix::operator^(const Matrix &M) const
01277 {
01278   Matrix result(numCols,M.numCols);
01279   
01280   if (numRows != M.numRows || result.numRows != numCols) {
01281     opserr << "Matrix::operator*(Matrix): incompatable sizes\n";
01282     return result;
01283   } 
01284 
01285     double *resDataPtr = result.data;       
01286 
01287     int innerDim = numRows;
01288     int nCols = result.numCols;
01289     for (int i=0; i<nCols; i++) {
01290       double *aDataPtr = data;
01291       double *bStartColDataPtr = &(M.data[i*innerDim]);
01292       for (int j=0; j<numCols; j++) {
01293         double *bDataPtr = bStartColDataPtr;
01294         double sum = 0.0;
01295         for (int k=0; k<innerDim; k++) {
01296           sum += *aDataPtr++ * *bDataPtr++;
01297         }
01298         *resDataPtr++ = sum;
01299       }
01300     }
01301 
01302     return result;
01303 }
01304     
01305 
01306 
01307 
01308 Matrix &
01309 Matrix::operator+=(const Matrix &M)
01310 {
01311 #ifdef _G3DEBUG
01312   if (numRows != M.numRows || numCols != M.numCols) {
01313     opserr << "Matrix::operator+=(const Matrix &M) - matrices incompatable\n";
01314     return *this;
01315   }
01316 #endif
01317 
01318   double *dataPtr = data;
01319   double *otherData = M.data;
01320   for (int i=0; i<dataSize; i++)
01321     *dataPtr++ += *otherData++;
01322   
01323   return *this;
01324 }
01325 
01326 Matrix &
01327 Matrix::operator-=(const Matrix &M)
01328 {
01329 #ifdef _G3DEBUG
01330   if (numRows != M.numRows || numCols != M.numCols) {
01331     opserr << "Matrix::operator-=(const Matrix &M) - matrices incompatable [" << numRows << " " ;
01332     opserr << numCols << "]" << "[" << M.numRows << "]" << M.numCols << "]\n";
01333 
01334     return *this;
01335   }
01336 #endif
01337 
01338   double *dataPtr = data;
01339   double *otherData = M.data;
01340   for (int i=0; i<dataSize; i++)
01341     *dataPtr++ -= *otherData++;
01342   
01343   return *this;
01344 }
01345 
01346 
01347 //
01348 // Input/Output Methods
01349 //
01350 
01351 void 
01352 Matrix::Output(OPS_Stream &s) const
01353 {
01354     for (int i=0; i<noRows(); i++) {
01355         for (int j=0; j<noCols(); j++)
01356             s <<  (*this)(i,j) << " ";
01357         s << endln;
01358     }
01359 }
01360 
01361 
01362 /*****************
01363 void 
01364 Matrix::Input(istream &s)
01365 {
01366     for (int i=0; i<noRows(); i++)
01367         for (int j=0; j<noCols(); j++)
01368             s >> (*this)(i,j);
01369 }       
01370 *****************/
01371 
01372 //
01373 // friend stream functions for input and output
01374 //
01375 
01376 OPS_Stream &operator<<(OPS_Stream &s, const Matrix &V)
01377 {
01378     s << endln;
01379     V.Output(s);
01380     s << endln;        
01381     return s;
01382 }
01383 
01384         
01385 /****************       
01386 istream &operator>>(istream &s, Matrix &V)
01387 {
01388     V.Input(s);
01389     return s;
01390 }
01391 ****************/
01392 
01393 
01394 
01395 
01396 
01397 int
01398 Matrix::Assemble(const Matrix &V, int init_row, int init_col, double fact) 
01399 {
01400   int pos_Rows, pos_Cols;
01401   int res = 0;
01402   
01403   int VnumRows = V.numRows;
01404   int VnumCols = V.numCols;
01405   
01406   int final_row = init_row + VnumRows - 1;
01407   int final_col = init_col + VnumCols - 1;
01408   
01409   if ((init_row >= 0) && (final_row < numRows) && (init_col >= 0) && (final_col < numCols))
01410   {
01411      for (int i=0; i<VnumCols; i++) 
01412      {
01413         pos_Cols = init_col + i;
01414         for (int j=0; j<VnumRows; j++) 
01415         {
01416            pos_Rows = init_row + j;
01417       
01418            (*this)(pos_Rows,pos_Cols) += V(j,i)*fact;
01419         }
01420      }
01421   }  
01422   else 
01423   {
01424      opserr << "WARNING: Matrix::Assemble(const Matrix &V, int init_row, int init_col, double fact): ";
01425      opserr << "position outside bounds \n";
01426      res = -1;
01427   }
01428 
01429   return res;
01430 }
01431 
01432 
01433 
01434 
01435 int
01436 Matrix::AssembleTranspose(const Matrix &V, int init_row, int init_col, double fact) 
01437 {
01438   int pos_Rows, pos_Cols;
01439   int res = 0;
01440   
01441   int VnumRows = V.numRows;
01442   int VnumCols = V.numCols;
01443   
01444   int final_row = init_row + VnumCols - 1;
01445   int final_col = init_col + VnumRows - 1;
01446   
01447   if ((init_row >= 0) && (final_row < numRows) && (init_col >= 0) && (final_col < numCols))
01448   {
01449      for (int i=0; i<VnumRows; i++) 
01450      {
01451         pos_Cols = init_col + i;
01452         for (int j=0; j<VnumCols; j++) 
01453         {
01454            pos_Rows = init_row + j;
01455       
01456            (*this)(pos_Rows,pos_Cols) += V(i,j)*fact;
01457         }
01458      }
01459   }  
01460   else 
01461   {
01462      opserr << "WARNING: Matrix::AssembleTranspose(const Matrix &V, int init_row, int init_col, double fact): ";
01463      opserr << "position outside bounds \n";
01464      res = -1;
01465   }
01466 
01467   return res;
01468 }
01469 
01470 
01471 
01472 
01473 int
01474 Matrix::Extract(const Matrix &V, int init_row, int init_col, double fact) 
01475 {
01476   int pos_Rows, pos_Cols;
01477   int res = 0;
01478   
01479   int VnumRows = V.numRows;
01480   int VnumCols = V.numCols;
01481   
01482   int final_row = init_row + numRows - 1;
01483   int final_col = init_col + numCols - 1;
01484   
01485   if ((init_row >= 0) && (final_row < VnumRows) && (init_col >= 0) && (final_col < VnumCols))
01486   {
01487      for (int i=0; i<numCols; i++) 
01488      {
01489         pos_Cols = init_col + i;
01490         for (int j=0; j<numRows; j++) 
01491         {
01492            pos_Rows = init_row + j;
01493       
01494            (*this)(j,i) = V(pos_Rows,pos_Cols)*fact;
01495         }
01496      }
01497   }  
01498   else 
01499   {
01500      opserr << "WARNING: Matrix::Extract(const Matrix &V, int init_row, int init_col, double fact): ";
01501      opserr << "position outside bounds \n";
01502      res = -1;
01503   }
01504 
01505   return res;
01506 }
01507 
01508 
01509 Matrix operator*(double a, const Matrix &V)
01510 {
01511   return V * a;
01512 }
01513 
01514 
01515 
01516 

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