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
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
00053
00054
00055
00056
00057
00058 Matrix::Matrix()
00059 :numRows(0), numCols(0), dataSize(0), data(0), fromFree(0)
00060 {
00061
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
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
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
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
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
00145 }
00146
00147 Matrix::Matrix(const Matrix &other)
00148 :numRows(0), numCols(0), dataSize(0), data(0), fromFree(0)
00149 {
00150
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
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
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
00184
00185
00186 Matrix::~Matrix()
00187 {
00188 if (data != 0)
00189 if (fromFree == 0)
00190 delete [] data;
00191
00192 }
00193
00194
00195
00196
00197
00198
00199 int
00200 Matrix::setData(double *theData, int row, int col)
00201 {
00202
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
00253 if (data != 0)
00254 if (fromFree == 0)
00255 delete [] data;
00256
00257
00258 fromFree = 0;
00259
00260 data = new double[newSize];
00261
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
00273
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
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
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
00402 int i;
00403 for (i=0; i<dataSize; i++)
00404 matrixWork[i] = data[i];
00405
00406
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
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
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
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
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
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
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
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
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
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
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
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
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
00705 if (thisFact == 1.0) {
00706
00707
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
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
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
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
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
00792 double *matrixWorkPtr = matrixWork;
00793 for (int l=0; l<sizeWork; l++)
00794 *matrixWorkPtr++ = 0.0;
00795
00796
00797
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
00812
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
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
00881
00882
00883
00884
00885
00886
00887
00888 Matrix &
00889 Matrix::operator=(const Matrix &other)
00890 {
00891
00892 if (this == &other)
00893 return *this;
00894
00895
00896
00897
00898
00899
00900
00901
00902
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
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
01032
01033
01034
01035
01036
01037
01038 Matrix &
01039 Matrix::operator+=(double fact)
01040 {
01041
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
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
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
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
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
01114
01115
01116
01117
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
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
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
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
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
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266 return result;
01267 }
01268
01269
01270
01271
01272
01273
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
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
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
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
01387
01388
01389
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