OOFEM  2.1
flotmtrx.C
Go to the documentation of this file.
00001 /*
00002  *
00003  *                 #####    #####   ######  ######  ###   ###
00004  *               ##   ##  ##   ##  ##      ##      ## ### ##
00005  *              ##   ##  ##   ##  ####    ####    ##  #  ##
00006  *             ##   ##  ##   ##  ##      ##      ##     ##
00007  *            ##   ##  ##   ##  ##      ##      ##     ##
00008  *            #####    #####   ##      ######  ##     ##
00009  *
00010  *
00011  *             OOFEM : Object Oriented Finite Element Code
00012  *
00013  *               Copyright (C) 1993 - 2013   Borek Patzak
00014  *
00015  *
00016  *
00017  *       Czech Technical University, Faculty of Civil Engineering,
00018  *   Department of Structural Mechanics, 166 29 Prague, Czech Republic
00019  *
00020  *  This program is free software; you can redistribute it and/or modify
00021  *  it under the terms of the GNU General Public License as published by
00022  *  the Free Software Foundation; either version 2 of the License, or
00023  *  (at your option) any later version.
00024  *
00025  *  This program is distributed in the hope that it will be useful,
00026  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028  *  GNU General Public License for more details.
00029  *
00030  *  You should have received a copy of the GNU General Public License
00031  *  along with this program; if not, write to the Free Software
00032  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00033  */
00034 /*
00035  * The original idea for this class comes from
00036  * Dubois-Pelerin, Y.: "Object-Oriented  Finite Elements: Programming concepts and Implementation",
00037  * PhD Thesis, EPFL, Lausanne, 1992.
00038  */
00039 
00040 #include "flotmtrx.h"
00041 #include "flotarry.h"
00042 #include "intarray.h"
00043 #include "mathfem.h"
00044 #include "error.h"
00045 #include "datastream.h"
00046 #include "classtype.h"
00047 #include "freestor.h"
00048 
00049 #ifdef BOOST_PYTHON
00050 #include <boost/python.hpp>
00051 #include <boost/python/extract.hpp>
00052 #endif
00053 
00054 // Some forward declarations for LAPACK. Remember to append the underscore to the function name.
00055 #ifdef __LAPACK_MODULE
00056 extern "C" {
00058 extern void dgecon_(const char *norm, const int *n, const double *a, const int *lda,
00059         const double *anorm, double *rcond, double *work, int *iwork, int *info, int norm_len);
00061 extern int dgetrf_(const int *m, const int *n, double *a, const int *lda, int *lpiv, int *info);
00063 extern int dgetri_( const int *n, double *a, const int *lda, int *ipiv, double *work, const int *lwork, int *info );
00065 extern int dgesv_( const int *n, const int *nrhs, double *a, const int *lda, int *ipiv, const double *b, const int *ldb, int *info );
00067 extern double dlange_(const char *norm, const int *m, const int *n, const double *a, const int *lda, double *work, int norm_len);
00069 extern int dsyevx_(const char *jobz,  const char *range, const char *uplo, const int *n, double *a, const int *lda,
00070         const double *vl, const double *vu, const int *il, const int *iu,
00071         const double *abstol, int *m, double *w, double *z, const int *ldz,
00072         double *work, int *lwork, int *iwork, int *ifail, int *info,
00073         int jobz_len, int range_len, int uplo_len);
00075 extern void dgetrs_(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, int *ipiv, const double *b, const int *ldb, int *info );
00076 }
00077 #endif
00078 
00079 #ifdef __PARALLEL_MODE
00080  #include "combuff.h"
00081 #endif
00082 
00083 namespace oofem {
00084     
00085 FloatMatrix :: FloatMatrix(int n, int m) : Matrix(n, m)
00086 {
00087     allocatedSize = n * m;
00088     values = allocDouble(n * m);
00089 }
00090 
00091 
00092 FloatMatrix :: FloatMatrix() : Matrix(0, 0)
00093 {
00094     allocatedSize = 0;
00095     values = NULL;
00096 }
00097 
00098 
00099 FloatMatrix :: FloatMatrix(const FloatArray *vector, bool transpose)
00100 //
00101 // constructor : creates (vector->giveSize(),1) FloatMatrix
00102 // if transpose = 1 creates (1,vector->giveSize()) FloatMatrix
00103 //
00104 {
00105     if ( transpose ) {
00106         nRows = 1; // column vector
00107         nColumns = vector->giveSize();
00108     } else {
00109         nRows = vector->giveSize(); // row vector- default
00110         nColumns = 1;
00111     }
00112 
00113     allocatedSize = nRows * nColumns;
00114     values = allocDouble(allocatedSize);
00115 
00116     if ( transpose ) {
00117         for ( int i = 1; i <= nColumns; i++ ) {
00118             this->at(1, i) = vector->at(i);
00119         }
00120     } else {
00121         for ( int i = 1; i <= nRows; i++ ) {
00122             this->at(i, 1) = vector->at(i);
00123         }
00124     }
00125 }
00126 
00127 
00128 FloatMatrix :: FloatMatrix(const FloatMatrix &src) : Matrix(src.nRows, src.nColumns)
00129 {
00130     // copy constructor
00131     double *P1, *P2;
00132 
00133     //this->nRows = src.nRows;
00134     //this->nColumns = src.nColumns;
00135 
00136     allocatedSize = nRows * nColumns;
00137     values = allocDouble(allocatedSize);
00138 
00139     P1 = values;
00140     P2 = src.values;
00141     for ( int i = 0; i < nRows * nColumns; i++ ) {
00142         P1 [ i ] = P2 [ i ];
00143     }
00144 }
00145 
00146 
00147 FloatMatrix :: ~FloatMatrix()
00148 {
00149     if ( values ) {
00150         freeDouble(values);
00151     }
00152 }
00153 
00154 
00155 
00156 FloatMatrix & FloatMatrix :: operator = ( const FloatMatrix & src )
00157 {
00158     // assignment: cleanup and copy
00159     this->resize(src.nRows, src.nColumns);
00160 
00161     for ( int i = 0; i < nRows * nColumns; i++ ) {
00162         values [ i ] = src.values [ i ];
00163     }
00164 
00165     return * this;
00166 }
00167 
00168 
00169 #ifdef DEBUG
00170 double &FloatMatrix :: at(int i, int j)
00171 // Returns the coefficient (i,j) of the receiver. Safer but slower than
00172 // the inline version of method 'at'.
00173 {
00174     this->checkBounds(i, j);
00175     return values [ ( j - 1 ) * nRows + i - 1 ];
00176 }
00177 
00178 double FloatMatrix :: at(int i, int j) const
00179 // Returns the coefficient (i,j) of the receiver. Safer but slower than
00180 // the inline version of method 'at'.
00181 {
00182     this->checkBounds(i, j);
00183     return values [ ( j - 1 ) * nRows + i - 1 ];
00184 }
00185 
00186 double &FloatMatrix :: operator() (int i, int j)
00187 {
00188     this->checkBounds(i+1, j+1);
00189     return values [ j * nRows + i ];
00190 }
00191 
00192 double FloatMatrix :: operator() (int i, int j) const
00193 {
00194     this->checkBounds(i+1, j+1);
00195     return values [ j * nRows + i ];
00196 }
00197 #endif
00198 
00199 
00200 void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &loc)
00201 {
00202     int ii, jj, size = src.giveNumberOfRows();
00203 
00204 #if DEBUG
00205     if ( size != loc.giveSize() ) {
00206         OOFEM_ERROR("FloatMatrix :: assemble : dimensions of 'src' and 'loc' mismatch");
00207     }
00208 
00209     if ( !src.isSquare() ) {
00210         OOFEM_ERROR("FloatMatrix :: assemble : 'src' is not sqaure matrix");
00211     }
00212 #endif
00213 
00214     for ( int i = 1; i <= size; i++ ) {
00215         if ( ( ii = loc.at(i) ) ) {
00216             for ( int j = 1; j <= size; j++ ) {
00217                 if ( ( jj = loc.at(j) ) ) {
00218                     this->at(ii, jj) += src.at(i, j);
00219                 }
00220             }
00221         }
00222     }
00223 }
00224 
00225 
00226 void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &rowind, const IntArray &colind)
00227 {
00228     int ii, jj;
00229     int nr = src.giveNumberOfRows();
00230     int nc = src.giveNumberOfColumns();
00231 
00232 #if DEBUG
00233     if ( nr != rowind.giveSize() ) {
00234         OOFEM_ERROR("FloatMatrix :: assemble : row dimensions of 'src' and 'rowind' mismatch");
00235     }
00236 
00237     if ( nc != colind.giveSize() ) {
00238         OOFEM_ERROR("FloatMatrix :: assemble : column dimensions of 'src' and 'colind' mismatch");
00239     }
00240 #endif
00241 
00242     for ( int i = 1; i <= nr; i++ ) {
00243         if ( ( ii = rowind.at(i) ) ) {
00244             for ( int j = 1; j <= nc; j++ ) {
00245                 if ( ( jj = colind.at(j) ) ) {
00246                     this->at(ii, jj) += src.at(i, j);
00247                 }
00248             }
00249         }
00250     }
00251 }
00252 
00253 
00254 void FloatMatrix :: assemble(const FloatMatrix &src, const int *rowind, const int *colind)
00255 {
00256     int ii, jj;
00257     int nr = src.giveNumberOfRows();
00258     int nc = src.giveNumberOfColumns();
00259 
00260     for ( int i = 1; i <= nr; i++ ) {
00261         if ( ( ii = rowind [ i - 1 ] ) ) {
00262             for ( int j = 1; j <= nc; j++ ) {
00263                 if ( ( jj = colind [ j - 1 ] ) ) {
00264                     this->at(ii, jj) += src.at(i, j);
00265                 }
00266             }
00267         }
00268     }
00269 }
00270 
00271 
00272 void FloatMatrix :: beTranspositionOf(const FloatMatrix &src)
00273 {
00274     // receiver becomes a transposition of src
00275     int nrows = src.giveNumberOfColumns(), ncols = src.giveNumberOfRows();
00276     this->resize(nrows, ncols);
00277 
00278     for ( int i = 1; i <= nrows; i++ ) {
00279         for ( int j = 1; j <= ncols; j++ ) {
00280             this->at(i, j) = src.at(j, i);
00281         }
00282     }
00283 }
00284 
00285 
00286 void FloatMatrix :: beProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
00287 // Receiver = aMatrix * bMatrix
00288 {
00289 #  ifdef DEBUG
00290     if ( aMatrix.nColumns != bMatrix.nRows ) {
00291         OOFEM_ERROR("FloatMatrix::beProductOf : error in product A*B : dimensions do not match");
00292     }
00293 #  endif
00294 
00295     this->resize(aMatrix.nRows, bMatrix.nColumns);
00296     for ( int i = 1; i <= aMatrix.nRows; i++ ) {
00297         for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
00298             double coeff = 0.;
00299             for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
00300                 coeff += aMatrix.at(i, k) * bMatrix.at(k, j);
00301             }
00302 
00303             this->at(i, j) = coeff;
00304         }
00305     }
00306 }
00307 
00308 
00309 void FloatMatrix :: addProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
00310 // Receiver = aMatrix * bMatrix
00311 {
00312     int p;
00313     double coeff;
00314 
00315 #  ifdef DEBUG
00316     if ( aMatrix.nColumns != bMatrix.nRows ) {
00317         OOFEM_ERROR("FloatMatrix::addProductOf : error in product A*B : dimensions do not match");
00318     }
00319 #  endif
00320 
00321     p = bMatrix.nColumns;
00322     for ( int i = 1; i <= aMatrix.nRows; i++ ) {
00323         for ( int j = 1; j <= p; j++ ) {
00324             coeff = 0.;
00325             for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
00326                 coeff += aMatrix.at(i, k) * bMatrix.at(k, j);
00327             }
00328 
00329             this->at(i, j) += coeff;
00330         }
00331     }
00332 }
00333 
00334 
00335 void FloatMatrix :: addTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
00336 // Receiver += aMatrix^T * bMatrix
00337 {
00338     int p;
00339     double coeff;
00340 
00341 #  ifdef DEBUG
00342     if ( aMatrix.nRows != bMatrix.nRows ) {
00343         OOFEM_ERROR("FloatMatrix::addTProductOf : error in product A*B : dimensions do not match");
00344     }
00345 #  endif
00346 
00347     p = bMatrix.nColumns;
00348     this->resize(aMatrix.nColumns, p);
00349     for ( int i = 1; i <= aMatrix.nColumns; i++ ) {
00350         for ( int j = 1; j <= p; j++ ) {
00351             coeff = 0.;
00352             for ( int k = 1; k <= aMatrix.nRows; k++ ) {
00353                 coeff += aMatrix.at(k, i) * bMatrix.at(k, j);
00354             }
00355 
00356             this->at(i, j) += coeff;
00357         }
00358     }
00359 }
00360 
00361 
00362 void FloatMatrix :: beDyadicProductOf(const FloatArray &vec1, const FloatArray &vec2)
00363 // Receiver = vec1 * vec2^T
00364 {
00365     int n1 = vec1.giveSize();
00366     int n2 = vec2.giveSize();
00367     this->resize(n1, n2);
00368     for ( int i = 1; i <= n1; i++ ) {
00369         for ( int j = 1; j <= n2; j++ ) {
00370             this->at(i, j) = vec1.at(i) * vec2.at(j);
00371         }
00372     }
00373 }
00374 
00375 void FloatMatrix :: beNMatrixOf(const FloatArray &n, int nsd)
00376 {
00377     this->resize(nsd, n.giveSize()*nsd);
00378     this->zero();
00379     for (int i = 0; i < n.giveSize(); ++i) {
00380         for (int j = 0; j < nsd; ++j) {
00381             (*this)(j, i*nsd+j) = n(i);
00382         }
00383     }
00384 }
00385 
00386 void FloatMatrix :: beLocalCoordSys(const FloatArray &normal)
00387 {
00388     if (normal.giveSize() == 1) {
00389         this->resize(1,1);
00390         this->at(1,1) = normal(0);
00391     } else if (normal.giveSize() == 2) {
00392         this->resize(2,2);
00393         this->at(1,1) = normal(1);
00394         this->at(1,2) = -normal(0);
00395 
00396         this->at(2,1) = normal(0);
00397         this->at(2,2) = normal(1);
00398     } else if (normal.giveSize() == 3) {
00399         // Create a permutated vector of n, *always* length 1 and significantly different from n.
00400         FloatArray t(3), b; // tangent and binormal
00401         t(0) = normal(1);
00402         t(1) = -normal(2);
00403         t(2) = normal(0);
00404 
00405         // Construct orthogonal vector
00406         double npn = t.dotProduct(normal);
00407         t.add(-npn,normal);
00408         t.normalize();
00409         b.beVectorProductOf(t,normal);
00410 
00411         this->resize(3,3);
00412 
00413         this->at(1,1) = t(0);
00414         this->at(1,2) = t(1);
00415         this->at(1,3) = t(2);
00416 
00417         this->at(1,1) = b(0);
00418         this->at(1,2) = b(1);
00419         this->at(1,3) = b(2);
00420 
00421         this->at(2,1) = normal(0);
00422         this->at(2,2) = normal(1);
00423         this->at(2,3) = normal(2);
00424     } else {
00425         OOFEM_ERROR("FloatMatrix :: beLocalCoordinateTransformation - Normal needs 1 to 3 components.");
00426     }
00427 }
00428 
00429 void FloatMatrix :: beTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
00430 // Receiver = aMatrix^T * bMatrix
00431 {
00432 #  ifdef DEBUG
00433     if ( aMatrix.nRows != bMatrix.nRows ) {
00434         OOFEM_ERROR("FloatMatrix::beTProductOf : error in product A*B : dimensions do not match");
00435     }
00436 #  endif
00437 
00438     this->resize(aMatrix.nColumns, bMatrix.nColumns);
00439     for ( int i = 1; i <= aMatrix.nColumns; i++ ) {
00440         for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
00441             double coeff = 0.;
00442             for ( int k = 1; k <= aMatrix.nRows; k++ ) {
00443                 coeff += aMatrix.at(k, i) * bMatrix.at(k, j);
00444             }
00445 
00446             this->at(i, j) = coeff;
00447         }
00448     }
00449 }
00450 
00451 
00452 void FloatMatrix :: beProductTOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
00453 // Receiver = aMatrix * bMatrix^T
00454 {
00455 #  ifdef DEBUG
00456     if ( aMatrix.nColumns != bMatrix.nColumns ) {
00457         OOFEM_ERROR("FloatMatrix::beProductTOf : error in product A*B : dimensions do not match");
00458     }
00459 #  endif
00460 
00461     this->resize(aMatrix.nRows, bMatrix.nRows);
00462     for ( int i = 1; i <= aMatrix.nRows; i++ ) {
00463         for ( int j = 1; j <= bMatrix.nRows; j++ ) {
00464             double coeff = 0.;
00465             for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
00466                 coeff += aMatrix.at(i, k) * bMatrix.at(j, k);
00467             }
00468 
00469             this->at(i, j) = coeff;
00470         }
00471     }
00472 }
00473 
00474 
00475 void FloatMatrix :: setSubMatrix(const FloatMatrix &src, int sr, int sc)
00476 {
00477     sr--;
00478     sc--;
00479 
00480     int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns();
00481 #if DEBUG
00482     int nr = sr + srcRows;
00483     int nc = sc + srcCols;
00484 
00485     if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
00486         OOFEM_ERROR("FloatMatrix :: setSubMatrix  - Sub matrix doesn't fit inside allocated space.");
00487     }
00488 #endif
00489 
00490     // add sub-matrix
00491     for ( int i = 0; i < srcRows; i++ ) {
00492         for ( int j = 0; j < srcCols; j++ ) {
00493             (*this)(sr + i, sc + j) = src(i, j);
00494         }
00495     }
00496 }
00497 
00498 
00499 void FloatMatrix :: setTSubMatrix(const FloatMatrix &src, int sr, int sc)
00500 {
00501     sr--;
00502     sc--;
00503 
00504     int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns();
00505 #if DEBUG
00506     int nr = sr + srcCols;
00507     int nc = sc + srcRows;
00508 
00509     if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
00510         OOFEM_ERROR("FloatMatrix :: setTSubMatrix  - Sub matrix doesn't fit inside allocated space");
00511     }
00512 #endif
00513 
00514     // add sub-matrix
00515     for ( int i = 0; i < srcCols; i++ ) {
00516         for ( int j = 0; j < srcRows; j++ ) {
00517             (*this)(sr + i, sc + j) = src(j, i);
00518         }
00519     }
00520 }
00521 
00522 
00523 void FloatMatrix :: beSubMatrixOf(const FloatMatrix &src,
00524                              int topRow, int bottomRow, int topCol, int bottomCol)
00525 /*
00526  * modifies receiver to be  submatrix of the src matrix
00527  * size of receiver  submatrix is determined from
00528  * input parameters
00529  */
00530 {
00531 #ifdef DEBUG
00532     if ( ( topRow < 1 ) || ( bottomRow < 1 ) || ( topCol < 1 ) || ( bottomCol < 1 ) ) {
00533         OOFEM_ERROR("FloatMatrix::beSubMatrixOf : subindexes size mismatch");
00534     }
00535 
00536     if ( ( src.nRows < bottomRow ) || ( src.nColumns < bottomCol ) || ( ( bottomRow - topRow ) > src.nRows ) ||
00537         ( ( bottomCol - topCol ) > src.nColumns ) ) {
00538         OOFEM_ERROR("FloatMatrix::beSubMatrixOf : subindexes size mismatch");
00539     }
00540 #endif
00541 
00542 
00543     int topRm1, topCm1;
00544     topRm1 = topRow - 1;
00545     topCm1 = topCol - 1;
00546 
00547     // allocate return value
00548     this->resize(bottomRow - topRm1, bottomCol - topCm1);
00549     for ( int i = topRow; i <= bottomRow; i++ ) {
00550         for ( int j = topCol; j <= bottomCol; j++ ) {
00551             this->at(i - topRm1, j - topCm1) = src.at(i, j);
00552         }
00553     }
00554 }
00555 
00556 
00557 void FloatMatrix :: addSubVectorRow(const FloatArray &src, int sr, int sc)
00558 {
00559     sc--;
00560 
00561     int srcCols = src.giveSize();
00562 
00563     int nr = sr;
00564     int nc = sc + srcCols;
00565 
00566     if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
00567         this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
00568     }
00569 
00570     // add sub-matrix
00571     for ( int j = 1; j <= srcCols; j++ ) {
00572         this->at(sr, sc + j) += src.at(j);
00573     }
00574 }
00575 
00576 
00577 void FloatMatrix :: addSubVectorCol(const FloatArray &src, int sr, int sc)
00578 {
00579     sr--;
00580 
00581     int srcRows = src.giveSize();
00582 
00583     int nr = sr + srcRows;
00584     int nc = sc;
00585 
00586     if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
00587         this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
00588     }
00589 
00590     // add sub-matrix
00591     for ( int j = 1; j <= srcRows; j++ ) {
00592         this->at(sr + j, sc) += src.at(j);
00593     }
00594 }
00595 
00596 
00597 
00598 void FloatMatrix :: setColumn(const FloatArray &src, int c)
00599 {
00600     int nr = src.giveSize();
00601 #ifdef DEBUG
00602     if ( this->giveNumberOfRows() != nr || c < 1 || c > this->giveNumberOfColumns()) {
00603         OOFEM_ERROR("FloatMatrix  :: setColumn - Size mismatch");
00604     }
00605 #endif
00606 
00607     double *P = this->values + (c-1)*nr;
00608     double *srcP = src.givePointer();
00609     for (int j = 0; j < nr; ++j )
00610         *P++ = *srcP++;
00611 }
00612 
00613 
00614 void FloatMatrix :: copyColumn(FloatArray &dest, int c) const
00615 {
00616     int nr = this->giveNumberOfRows();
00617 #ifdef DEBUG
00618     if ( c < 1 || c > this->giveNumberOfColumns()) {
00619         OOFEM_ERROR2("FloatMatrix  :: copyColumn - Column outside range (%d)", c);
00620     }
00621 #endif
00622 
00623     dest.resize(nr);
00624     double *P = this->values + (c-1)*nr;
00625     double *destP = dest.givePointer();
00626     for (int j = 0; j < nr; ++j )
00627         *destP++ = *P++;
00628 }
00629 
00630 
00631 void FloatMatrix :: copySubVectorRow(const FloatArray &src, int sr, int sc)
00632 {
00633     sc--;
00634 
00635     int srcCols = src.giveSize();
00636 
00637     int nr = sr;
00638     int nc = sc + srcCols;
00639 
00640     if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
00641         this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
00642     }
00643 
00644     // add sub-matrix
00645     for ( int j = 1; j <= srcCols; j++ ) {
00646         this->at(sr, sc + j) = src.at(j);
00647     }
00648 }
00649 
00650 
00651 
00652 void FloatMatrix :: plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
00653 // Adds to the receiver the product  a(transposed).b dV .
00654 // The receiver size is adjusted, if necessary.
00655 // This method assumes that both the receiver and the product above are
00656 // symmetric matrices, and therefore computes only the upper half of the
00657 // receiver ; the lower half is not modified. Other advantage : it does
00658 // not compute the transposition of matrix a.
00659 {
00660     if ( !this->isNotEmpty() ) {
00661         this->resize(a.nColumns, b.nColumns);
00662         this->zero();
00663     }
00664 
00665     for ( int i = 1; i <= nRows; i++ ) {
00666         for ( int j = i; j <= nColumns; j++ ) {
00667             double summ = 0.;
00668             for ( int k = 1; k <= a.nRows; k++ ) {
00669                 summ += a.at(k, i) * b.at(k, j);
00670             }
00671 
00672             this->at(i, j) += summ * dV;
00673         }
00674     }
00675 }
00676 
00677 
00678 void FloatMatrix :: plusDyadSymmUpper(const FloatArray &a, const FloatArray &b, double dV)
00679 {
00680     if ( !this->isNotEmpty() ) {
00681         this->resize(a.giveSize(), b.giveSize());
00682         this->zero();
00683     }
00684 
00685     for ( int i = 1; i <= nRows; i++ ) {
00686         for ( int j = i; j <= nColumns; j++ ) {
00687             this->at(i, j) += a.at(i)*b.at(j) * dV;
00688         }
00689     }
00690 }
00691 
00692 
00693 
00694 void FloatMatrix :: plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
00695 // Adds to the receiver the product  a(transposed).b dV .
00696 // If the receiver has a null size, it is expanded.
00697 // Advantage : does not compute the transposition of matrix a.
00698 {
00699     if ( !this->isNotEmpty() ) {
00700         this->resize(a.nColumns, b.nColumns);
00701         this->zero();
00702     }
00703 
00704     for ( int i = 1; i <= nRows; i++ ) {
00705         for ( int j = 1; j <= nColumns; j++ ) {
00706             double summ = 0.;
00707             for ( int k = 1; k <= a.nRows; k++ ) {
00708                 summ += a.at(k, i) * b.at(k, j);
00709             }
00710 
00711             this->at(i, j) += summ * dV;
00712         }
00713     }
00714 }
00715 
00716 
00717 void FloatMatrix :: plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
00718 {
00719     if ( !this->isNotEmpty() ) {
00720         this->resize(a.giveSize(), b.giveSize());
00721         this->zero();
00722     }
00723 
00724     for ( int i = 1; i <= nRows; i++ ) {
00725         for ( int j = 1; j <= nColumns; j++ ) {
00726             this->at(i, j) += a.at(i) * b.at(j) * dV;
00727         }
00728     }
00729 }
00730 
00731 
00732 void FloatMatrix :: beInverseOf(const FloatMatrix &src)
00733 // Receiver becomes inverse of given parameter src. If necessary, size is adjusted.
00734 {
00735     double det;
00736 
00737 #  ifdef DEBUG
00738     if ( !src.isSquare() ) {
00739         OOFEM_ERROR3("FloatMatrix::beInverseOf : cannot inverse a %d by %d matrix", src.nRows, src.nColumns);
00740     }
00741 #  endif
00742 
00743     this->resize(src.nRows, src.nColumns);
00744 
00745     if ( nRows == 1 ) {
00746         this->at(1, 1) = 1. / src.at(1, 1);
00747         return;
00748     } else if ( nRows == 2 ) {
00749         det = src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1);
00750         this->at(1, 1) =  src.at(2, 2) / det;
00751         this->at(2, 1) = -src.at(2, 1) / det;
00752         this->at(1, 2) = -src.at(1, 2) / det;
00753         this->at(2, 2) =  src.at(1, 1) / det;
00754         return;
00755     } else if ( nRows == 3 ) {
00756         det = src.at(1, 1) * src.at(2, 2) * src.at(3, 3) + src.at(1, 2) * src.at(2, 3) * src.at(3, 1) +
00757               src.at(1, 3) * src.at(2, 1) * src.at(3, 2) - src.at(1, 3) * src.at(2, 2) * src.at(3, 1) -
00758               src.at(2, 3) * src.at(3, 2) * src.at(1, 1) - src.at(3, 3) * src.at(1, 2) * src.at(2, 1);
00759 
00760         this->at(1, 1) = ( src.at(2, 2) * src.at(3, 3) - src.at(2, 3) * src.at(3, 2) ) / det;
00761         this->at(2, 1) = ( src.at(2, 3) * src.at(3, 1) - src.at(2, 1) * src.at(3, 3) ) / det;
00762         this->at(3, 1) = ( src.at(2, 1) * src.at(3, 2) - src.at(2, 2) * src.at(3, 1) ) / det;
00763         this->at(1, 2) = ( src.at(1, 3) * src.at(3, 2) - src.at(1, 2) * src.at(3, 3) ) / det;
00764         this->at(2, 2) = ( src.at(1, 1) * src.at(3, 3) - src.at(1, 3) * src.at(3, 1) ) / det;
00765         this->at(3, 2) = ( src.at(1, 2) * src.at(3, 1) - src.at(1, 1) * src.at(3, 2) ) / det;
00766         this->at(1, 3) = ( src.at(1, 2) * src.at(2, 3) - src.at(1, 3) * src.at(2, 2) ) / det;
00767         this->at(2, 3) = ( src.at(1, 3) * src.at(2, 1) - src.at(1, 1) * src.at(2, 3) ) / det;
00768         this->at(3, 3) = ( src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1) ) / det;
00769 
00770         //p[0]= (values[4]*values[8]-values[7]*values[5])/det ;
00771         //p[1]= (values[7]*values[2]-values[1]*values[8])/det ;
00772         //p[2]= (values[1]*values[5]-values[4]*values[2])/det ;
00773         //p[3]= (values[6]*values[5]-values[3]*values[8])/det ;
00774         //p[4]= (values[0]*values[8]-values[6]*values[2])/det ;
00775         //p[5]= (values[3]*values[2]-values[0]*values[5])/det ;
00776         //p[6]= (values[3]*values[7]-values[6]*values[4])/det ;
00777         //p[7]= (values[6]*values[1]-values[0]*values[7])/det ;
00778         //p[8]= (values[0]*values[4]-values[3]*values[1])/det ;
00779         return;
00780     } else {
00781 #ifdef __LAPACK_MODULE
00782         int n = this->nRows;
00783         IntArray ipiv(n);
00784         int lwork, info;
00785         *this = src;
00786 
00787         // LU-factorization
00788         dgetrf_(&n, &n, this->values, &n, ipiv.givePointer(), &info);
00789         if (info != 0) {
00790             OOFEM_ERROR2("FloatMatrix::beInverseOf : dgetrf error %d", info);
00791         }
00792 
00793         // Inverse
00794         lwork = n*n;
00795         FloatArray work(lwork);
00796         dgetri_( &this->nRows, this->values, &this->nRows, ipiv.givePointer(), work.givePointer(), &lwork, &info );
00797         if (info > 0) {
00798             OOFEM_ERROR2("FloatMatrix::beInverseOf : Singular at %d", info);
00799         } else if (info < 0) {
00800             OOFEM_ERROR2("FloatMatrix::beInverseOf : Error on input %d", info);
00801         }
00802 #else
00803         // size >3 ... gaussian elimination - slow but safe
00804         //
00805         double piv, linkomb;
00806         FloatMatrix tmp = src;
00807         this->zero();
00808         // initialize answer to be unity matrix;
00809         for ( int i = 1; i <= nRows; i++ ) {
00810             this->at(i, i) = 1.0;
00811         }
00812 
00813         // lower triangle elimination by columns
00814         for ( int i = 1; i < nRows; i++ ) {
00815             piv = tmp.at(i, i);
00816             if ( fabs(piv) < 1.e-20 ) {
00817                 OOFEM_ERROR3("FloatMatrix::beInverseOf : cannot inverse a %d by %d matrix", nRows, nColumns);
00818             }
00819 
00820             for ( int j = i + 1; j <= nRows; j++ ) {
00821                 linkomb = tmp.at(j, i) / tmp.at(i, i);
00822                 for ( int k = i; k <= nRows; k++ ) {
00823                     tmp.at(j, k) -= tmp.at(i, k) * linkomb;
00824                 }
00825 
00826                 for ( int k = 1; k <= nRows; k++ ) {
00827                     this->at(j, k) -= this->at(i, k) * linkomb;
00828                 }
00829             }
00830         }
00831 
00832         // upper triangle elimination by columns
00833         for ( int i = nRows; i > 1; i-- ) {
00834             piv = tmp.at(i, i);
00835             for ( int j = i - 1; j > 0; j-- ) {
00836                 linkomb = tmp.at(j, i) / piv;
00837                 for ( int k = i; k > 0; k-- ) {
00838                     tmp.at(j, k) -= tmp.at(i, k) * linkomb;
00839                 }
00840 
00841                 for ( int k = nRows; k > 0; k-- ) {
00842                     // tmp -> at(j,k)-= tmp  ->at(i,k)*linkomb;
00843                     this->at(j, k) -= this->at(i, k) * linkomb;
00844                 }
00845             }
00846         }
00847 
00848         // diagonal scaling
00849         for ( int i = 1; i <= nRows; i++ ) {
00850             for ( int j = 1; j <= nRows; j++ ) {
00851                 this->at(i, j) /= tmp.at(i, i);
00852             }
00853         }
00854 #endif
00855     }
00856 }
00857 
00858 
00859 void
00860 FloatMatrix :: beSubMatrixOf(const FloatMatrix &src, const IntArray &indx)
00861 /*
00862  * modifies receiver to be  (sub)matrix of the src.
00863  * (sub)matrix has size of max value in indx
00864  * and on its position (indx->at(i),indx->at(j)) are values from src at (i, j).
00865  * if indx->at(i) or indx->at(j) are <= 0 then at position i,j is zero.
00866  *
00867  * Warning:
00868  * This method should produce also bigger matrix than src
00869  * Works only for square matrices.
00870  */
00871 {
00872     int size, n, ii, jj;
00873 
00874     if ( ( n = indx.giveSize() ) == 0 ) {
00875         this->resize(0, 0);
00876         return;
00877     }
00878 
00879 #  ifdef DEBUG
00880     if ( !src.isSquare() ) {
00881         OOFEM_ERROR("FloatMatrix::beSubMatrixOf : cannot construct required submatrix");
00882     }
00883 # endif
00884 
00885     if ( n != src.nRows ) {
00886         OOFEM_ERROR("FloatMatrix::beSubMatrixOf : giveSubMatrix size mismatch");
00887     }
00888 
00889     size = indx.maximum();
00890 
00891     this->resize(size, size);
00892 
00893     for ( int i = 1; i <= n; i++ ) {
00894         for ( int j = 1; j <= n; j++ ) {
00895             if ( ( ( ii = indx.at(i) ) != 0 ) && ( ( jj = indx.at(j) ) != 0 ) ) {
00896                 this->at(ii, jj) = src.at(i, j);
00897             }
00898         }
00899     }
00900 }
00901 
00902 
00903 
00904 void
00905 FloatMatrix :: beSubMatrixOfSizeOf(const FloatMatrix &src, const IntArray &indx, int size)
00906 /*
00907  * modifies receiver to be  (sub)matrix of the src matrix.
00908  * (sub)matrix has size size
00909  * and on its position (indx->at(i),indx->at(j)) are values from src at (i, j).
00910  * if indx->at(i) or indx->at(j) are <= 0 then at position i,j is zero.
00911  *
00912  * Warning:
00913  * This method should produce also bigger matrix than src
00914  * Works only for square matrices.
00915  */
00916 {
00917     int n, ii, jj;
00918 
00919     if ( ( n = indx.giveSize() ) == 0 ) {
00920         this->resize(0, 0);
00921         return;
00922     }
00923 
00924 #  ifdef DEBUG
00925     if ( !src.isSquare() ) {
00926         OOFEM_ERROR("FloatMatrix::beSubMatrixOfSizeOf : cannot construct submatrix");
00927     }
00928 
00929     if ( n != src.nRows ) {
00930         OOFEM_ERROR("FloatMatrix::beSubMatrixOfSizeOf : giveSubMatrix size mismatch");
00931     }
00932 
00933     if ( indx.maximum() > size ) {
00934         OOFEM_ERROR("FloatMatrix::beSubMatrixOfSizeOf : index in mask exceed size");
00935     }
00936 # endif
00937 
00938     this->resize(size, size);
00939 
00940     for ( int i = 1; i <= n; i++ ) {
00941         for ( int j = 1; j <= n; j++ ) {
00942             if ( ( ( ii = indx.at(i) ) != 0 ) && ( ( jj = indx.at(j) ) != 0 ) ) {
00943                 this->at(ii, jj) = src.at(i, j);
00944             }
00945         }
00946     }
00947 }
00948 
00949 void FloatMatrix :: add(const FloatMatrix &aMatrix)
00950 // Adds aMatrix to the receiver. If the receiver has a null size,
00951 // adjusts its size to that of aMatrix. Returns the modified receiver.
00952 {
00953     register int i;
00954     int n, m;
00955     double *P1, *P2;
00956 
00957     n = aMatrix.nRows;
00958     m = aMatrix.nColumns;
00959     if ( nRows * nColumns == 0 ) {
00960         this->operator = ( aMatrix );
00961     } else {
00962 #     ifdef DEBUG
00963         if ( (n != nRows || m != nColumns) && aMatrix.isNotEmpty() )
00964             OOFEM_ERROR5("FloatMatrix::add : dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, n, m);
00965 #     endif
00966 
00967         P1 = values;
00968         P2 = aMatrix.values;
00969         i  = n * m;
00970         while ( i-- ) {
00971             * P1++ += * P2++;
00972         }
00973     }
00974 }
00975 
00976 
00977 void FloatMatrix :: add(double s, const FloatMatrix &aMatrix)
00978 // Adds aMatrix to the receiver. If the receiver has a null size,
00979 // adjusts its size to that of aMatrix. Returns the modified receiver.
00980 {
00981     register int i;
00982     int n, m;
00983     double *P1, *P2;
00984 
00985     n = aMatrix.nRows;
00986     m = aMatrix.nColumns;
00987     if ( nRows * nColumns == 0 ) {
00988         this->operator = ( aMatrix );
00989         this->times(s);
00990     } else {
00991         #     ifdef DEBUG
00992         if ( (n != nRows || m != nColumns) && aMatrix.isNotEmpty() )
00993             OOFEM_ERROR5("FloatMatrix::add : dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, n, m);
00994         #     endif
00995 
00996             P1 = values;
00997             P2 = aMatrix.values;
00998             i  = n * m;
00999             while ( i-- ) {
01000                 * P1++ += s *(* P2++);
01001             }
01002     }
01003 }
01004 
01005 void FloatMatrix :: subtract(const FloatMatrix &aMatrix)
01006 // Adds aMatrix to the receiver. If the receiver has a null size,
01007 // adjusts its size to that of aMatrix. Returns the modified receiver.
01008 {
01009     register int i;
01010     int n, m;
01011     double *P1, *P2;
01012 
01013     n = aMatrix.nRows;
01014     m = aMatrix.nColumns;
01015     if ( nRows * nColumns == 0 ) {
01016         this->operator=(aMatrix);
01017     } else {
01018 #     ifdef DEBUG
01019         if ( (n != nRows || m != nColumns) && aMatrix.isNotEmpty() )
01020             OOFEM_ERROR5("FloatMatrix::subtract : dimensions mismatch : (r1,c1)-(r2,c2) : (%d,%d)-(%d,%d)", nRows, nColumns, n, m);
01021 #     endif
01022 
01023         P1 = values;
01024         P2 = aMatrix.values;
01025         i  = n * m;
01026         while ( i-- ) {
01027             * P1++ -= * P2++;
01028         }
01029     }
01030 }
01031 
01032 
01033 void FloatMatrix :: solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose)
01034 // solves equation b = this * x
01035 {
01036 #  ifdef DEBUG
01037     if ( !this->isSquare() ) {
01038         OOFEM_ERROR3("FloatMatrix::solveForRhs : cannot solve a %d by %d matrix", nRows, nColumns);
01039     }
01040 
01041     if ( nRows != b.giveSize() ) {
01042         OOFEM_ERROR("FloatMatrix::solveForRhs : dimension mismatch");
01043     }
01044 #  endif
01045 
01046 #ifdef __LAPACK_MODULE
01047     int info, nrhs = 1;
01048     IntArray ipiv(this->nRows);
01049     answer = b;
01050     //dgesv_( &this->nRows, &nrhs, this->values, &this->nRows, ipiv.givePointer(), answer.givePointer(), &this->nRows, &info );
01051     dgetrf_( &this->nRows, &this->nRows, this->values, &this->nRows, ipiv.givePointer(), &info );
01052     if (info == 0)
01053         dgetrs_( transpose ? "Transpose" : "No transpose", &this->nRows, &nrhs, this->values, &this->nRows, ipiv.givePointer(), answer.givePointer(), &this->nRows, &info );
01054     if (info != 0) {
01055         OOFEM_ERROR2("FloatMatrix::solveForRhs : error %d", info);
01056     }
01057 #else
01058     int pivRow;
01059     double piv, linkomb, help;
01060     FloatMatrix *mtrx, trans;
01061     if (transpose) {
01062         trans.beTranspositionOf(*this);
01063         mtrx = &trans;
01064     } else {
01065         mtrx = this;
01066     }
01067 
01068     answer = b;
01069 
01070     // initialize answer to be unity matrix;
01071     // lower triangle elimination by columns
01072     for ( int i = 1; i < nRows; i++ ) {
01073         // find the suitable row and pivot
01074         piv = fabs( mtrx->at(i, i) );
01075         pivRow = i;
01076         for ( int j = i + 1; j <= nRows; j++ ) {
01077             if ( fabs( mtrx->at(j, i) ) > piv ) {
01078                 pivRow = j;
01079                 piv = fabs( mtrx->at(j, i) );
01080             }
01081         }
01082 
01083         if ( piv < 1.e-20 ) {
01084             OOFEM_ERROR2("FloatMatrix::solveForRhs : cannot solve, seems to be singular at row %d", pivRow);
01085         }
01086 
01087         // exchange rows
01088         if ( pivRow != i ) {
01089             for ( int j = i; j <= nRows; j++ ) {
01090                 help = mtrx->at(i, j);
01091                 mtrx->at(i, j) = mtrx->at(pivRow, j);
01092                 mtrx->at(pivRow, j) = help;
01093             }
01094             help = answer.at(i);
01095             answer.at(i) = answer.at(pivRow);
01096             answer.at(pivRow) = help;
01097         }
01098 
01099         for ( int j = i + 1; j <= nRows; j++ ) {
01100             linkomb = mtrx->at(j, i) / mtrx->at(i, i);
01101             for ( int k = i; k <= nRows; k++ ) {
01102                 this->at(j, k) -= mtrx->at(i, k) * linkomb;
01103             }
01104 
01105             answer.at(j) -= answer.at(i) * linkomb;
01106         }
01107     }
01108 
01109     // back substitution
01110     for ( int i = nRows; i >= 1; i-- ) {
01111         help = 0.;
01112         for ( int j = i + 1; j <= nRows; j++ ) {
01113             help += mtrx->at(i, j) * answer.at(j);
01114         }
01115 
01116         answer.at(i) = ( answer.at(i) - help ) / mtrx->at(i, i);
01117     }
01118 #endif
01119 }
01120 
01121 
01122 void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool transpose)
01123 // solves equation b = this * x
01124 // returns x. this and b are kept untouched
01125 //
01126 // gaussian elimination - slow but safe
01127 //
01128 {
01129 #  ifdef DEBUG
01130     if ( !this->isSquare() ) {
01131         OOFEM_ERROR3("FloatMatrix::solveForRhs : cannot solve a %d by %d matrix", nRows, nColumns);
01132     }
01133 
01134     if ( nRows != b.giveNumberOfRows() ) {
01135         OOFEM_ERROR("FloatMatrix::solveForRhs : dimension mismatch");
01136     }
01137 #  endif
01138 
01139 #ifdef __LAPACK_MODULE
01140     int info;
01141     IntArray ipiv(this->nRows);
01142     answer = b;
01143     dgetrf_( &this->nRows, &this->nRows, this->values, &this->nRows, ipiv.givePointer(), &info );
01144     if (info == 0)
01145         dgetrs_( transpose ? "Transpose" : "No transpose", &this->nRows, &this->nRows, this->values, &this->nRows, ipiv.givePointer(), answer.givePointer(), &this->nRows, &info );
01146     if (info != 0) {
01147         OOFEM_ERROR2("FloatMatrix::solveForRhs : error %d", info);
01148     }
01149 #else
01150     int pivRow, nPs;
01151     double piv, linkomb, help;
01152     FloatMatrix *mtrx, trans;
01153     if (transpose) {
01154         trans.beTranspositionOf(*this);
01155         mtrx = &trans;
01156     } else {
01157         mtrx = this;
01158     }
01159 
01160     nPs = b.giveNumberOfColumns();
01161     answer = b;
01162     // initialize answer to be unity matrix;
01163     // lower triangle elimination by columns
01164     for ( int i = 1; i < nRows; i++ ) {
01165         // find the suitable row and pivot
01166         piv = fabs( mtrx->at(i, i) );
01167         pivRow = i;
01168         for ( int j = i + 1; j <= nRows; j++ ) {
01169             if ( fabs( mtrx->at(j, i) ) > piv ) {
01170                 pivRow = j;
01171                 piv = fabs( mtrx->at(j, i) );
01172             }
01173         }
01174 
01175         if ( fabs(piv) < 1.e-20 ) {
01176             OOFEM_ERROR3("FloatMatrix::solveForRhs : pivot too small, cannot solve %d by %d matrix", nRows, nColumns);
01177         }
01178 
01179         // exchange rows
01180         if ( pivRow != i ) {
01181             for ( int j = i; j <= nRows; j++ ) {
01182                 help = mtrx->at(i, j);
01183                 mtrx->at(i, j) = mtrx->at(pivRow, j);
01184                 mtrx->at(pivRow, j) = help;
01185             }
01186 
01187             for ( int j = 1; j <= nPs; j++ ) {
01188                 help = answer.at(i, j);
01189                 answer.at(i, j) = answer.at(pivRow, j);
01190                 answer.at(pivRow, j) = help;
01191             }
01192         }
01193 
01194         if ( fabs(piv) < 1.e-20 ) {
01195             OOFEM_ERROR("FloatMatrix::solveForRhs : cannot solve, zero pivot encountered");
01196         }
01197 
01198         for ( int j = i + 1; j <= nRows; j++ ) {
01199             linkomb = mtrx->at(j, i) / mtrx->at(i, i);
01200             for ( int k = i; k <= nRows; k++ ) {
01201                 mtrx->at(j, k) -= mtrx->at(i, k) * linkomb;
01202             }
01203 
01204             for ( int k = 1; k <= nPs; k++ ) {
01205                 answer.at(j, k) -= answer.at(i, k) * linkomb;
01206             }
01207         }
01208     }
01209 
01210     // back substitution
01211     for ( int i = nRows; i >= 1; i-- ) {
01212         for ( int k = 1; k <= nPs; k++ ) {
01213             help = 0.;
01214             for ( int j = i + 1; j <= nRows; j++ ) {
01215                 help += mtrx->at(i, j) * answer.at(j, k);
01216             }
01217 
01218             answer.at(i, k) = ( answer.at(i, k) - help ) / mtrx->at(i, i);
01219         }
01220     }
01221 #endif
01222 }
01223 
01224 
01225 void FloatMatrix :: initFromVector(const FloatArray &vector, bool transposed)
01226 //
01227 // constructor : creates (vector->giveSize(),1) FloatMatrix
01228 // if transpose = 1 creates (1,vector->giveSize()) FloatMatrix
01229 //
01230 {
01231     if ( transposed ) {
01232         resize( 1, vector.giveSize() );
01233     } else {
01234         resize(vector.giveSize(), 1); // row vector- default
01235     }
01236 
01237     if ( transposed ) {
01238         for ( int i = 1; i <= nColumns; i++ ) {
01239             this->at(1, i) = vector.at(i);
01240         }
01241     } else {
01242         for ( int i = 1; i <= nRows; i++ ) {
01243             this->at(i, 1) = vector.at(i);
01244         }
01245     }
01246 }
01247 
01248 
01249 void FloatMatrix :: zero() const
01250 {
01251     // zeroing the receiver - fast implementation
01252     double *P1;
01253     int i;
01254 
01255     P1 = this->values;
01256     i  = nRows * nColumns;
01257     while ( i-- ) {
01258         * P1++ = 0.;
01259     }
01260 }
01261 
01262 
01263 void FloatMatrix :: beUnitMatrix()
01264 {
01265 #ifdef DEBUG
01266     if ( !this->isSquare() ) {
01267         OOFEM_ERROR3("FloatMatrix::beUnitMatrix : cannot make unit matrix of %d by %d matrix", nRows, nColumns);
01268     }
01269 #endif
01270 
01271     this->zero();
01272     for ( int i = 1; i <= nRows; i++ ) {
01273         this->at(i, i) = 1.0;
01274     }
01275 }
01276 
01277 
01278 void FloatMatrix :: bePinvID()
01279 // this matrix is the product of the 6x6 deviatoric projection matrix ID
01280 // and the inverse scaling matrix Pinv
01281 {
01282     this->resize(6, 6);
01283     this->zero();
01284     values [ 0 ] = values [ 7 ] = values [ 14 ] = 2. / 3.;
01285     values [ 1 ] = values [ 2 ] = values [ 6 ] = values [ 8 ] = values [ 12 ] = values [ 13 ] = -1. / 3.;
01286     values [ 21 ] = values [ 28 ] = values [ 35 ] = 0.5;
01287 }
01288 
01289 
01290 void FloatMatrix :: resize(int rows, int columns, int allocChunk)
01291 //
01292 // resizes receiver, all data will be lost
01293 //
01294 {
01295     if ( rows * columns > allocatedSize ) {
01296         // memory realocation necessary
01297         if ( values ) {
01298             freeDouble(values);
01299         }
01300 
01301         if ( allocChunk < 0 ) {
01302             allocChunk = 0;
01303         }
01304 
01305         allocatedSize = rows * columns + allocChunk; // REMEMBER NEW ALLOCATED SIZE
01306         values = allocDouble(allocatedSize);
01307     } else {
01308         // reuse previously allocated space
01309     }
01310 
01311     this->nRows = rows;
01312     this->nColumns = columns;
01313 }
01314 
01315 
01316 void FloatMatrix :: resizeWithData(int rows, int columns)
01317 //
01318 // resizes receiver, all data kept
01319 //
01320 {
01321     FloatMatrix old(*this);
01322 
01323     if ( rows * columns > allocatedSize ) {
01324         // memory realocation necessary
01325         if ( values ) {
01326             freeDouble(values);
01327         }
01328 
01329         allocatedSize = rows * columns; // REMEMBER NEW ALLOCATED SIZE
01330         values = allocDouble(allocatedSize);
01331     } else {
01332         // reuse previously allocated space
01333     }
01334 
01335     this->nRows = rows;
01336     this->nColumns = columns;
01337 
01338     int ii, jj;
01339 
01340     ii = min( rows, old.giveNumberOfRows() );
01341     jj = min( columns, old.giveNumberOfColumns() );
01342     // copy old values if possible
01343     for ( int i = 1; i <= ii; i++ ) {
01344         for ( int j = 1; j <= jj; j++ ) {
01345             this->at(i, j) = old.at(i, j);
01346         }
01347     }
01348 }
01349 
01350 
01351 void FloatMatrix :: hardResize(int rows, int columns)
01352 //
01353 // resizes receiver, all data will be lost
01354 //
01355 {
01356     // memory realocation necessary
01357     if ( values ) {
01358         freeDouble(values);
01359     }
01360 
01361     allocatedSize = rows * columns; // REMEMBER NEW ALLOCATED SIZE
01362     values = allocDouble(allocatedSize);
01363 
01364     this->nRows = rows;
01365     this->nColumns = columns;
01366 }
01367 
01368 
01369 double FloatMatrix :: giveDeterminant() const
01370 // Returns the determinant of the receiver.
01371 {
01372 #  ifdef DEBUG
01373     if ( !this->isSquare() ) {
01374         OOFEM_ERROR3("FloatMatrix::giveDeterminant : cannot compute determinant of a %d by %d matrix", nRows, nColumns);
01375     }
01376 
01377 #  endif
01378 
01379     if ( nRows == 1 ) {
01380         return values [ 0 ];
01381     } else if ( nRows == 2 ) {
01382         return  ( values [ 0 ] * values [ 3 ] - values [ 1 ] * values [ 2 ] );
01383     } else if ( nRows == 3 ) {
01384         return ( values [ 0 ] * values [ 4 ] * values [ 8 ] + values [ 3 ] * values [ 7 ] * values [ 2 ] +
01385                  values [ 6 ] * values [ 1 ] * values [ 5 ] - values [ 6 ] * values [ 4 ] * values [ 2 ] -
01386                  values [ 7 ] * values [ 5 ] * values [ 0 ] - values [ 8 ] * values [ 3 ] * values [ 1 ] );
01387     } else {
01388         OOFEM_ERROR3("FloatMatrix::giveDeterminant : sorry, cannot inverse %d by %d matrices", nRows, nColumns);
01389     }
01390 
01391     return 0.;
01392 }
01393 
01394 
01395 void FloatMatrix :: printYourself() const
01396 // Prints the receiver on screen.
01397 {
01398     printf("FloatMatrix with dimensions : %d %d\n",
01399            nRows, nColumns);
01400     if ( nRows <= 250 && nColumns <= 250 ) {
01401         for ( int i = 1; i <= nRows; ++i ) {
01402             for ( int j = 1; j <= nColumns && j <= 50; ++j ) {
01403                 printf( "%10.3e  ", this->at(i, j) );
01404             }
01405 
01406             printf("\n");
01407         }
01408     } else {
01409         printf("   large matrix : coefficients not printed \n");
01410     }
01411 }
01412 
01413 
01414 void FloatMatrix :: pY() const
01415 // Prints the receiver on screen with higher accuracy than printYourself.
01416 {
01417     printf("[");
01418     for ( int i = 1; i <= nRows; ++i ) {
01419         for ( int j = 1; j <= nColumns; ++j ) {
01420             printf( "%20.15e", this->at(i, j) );
01421             if ( j < nColumns ) {
01422                 printf(",");
01423             } else {
01424                 printf(";");
01425             }
01426         }
01427     }
01428 
01429     printf("];\n");
01430 }
01431 
01432 
01433 void FloatMatrix :: rotatedWith(const FloatMatrix &r)
01434 // Returns the receiver 'a' rotated according the change-of-base matrix r.
01435 // The method performs the operation  a = r^T . a . r .
01436 {
01437     FloatMatrix rta;
01438 
01439     rta.beTProductOf(r, * this);     //  r^T . a
01440     this->beProductOf(rta, r);       //  r^T . a . r
01441 }
01442 
01443 
01444 void FloatMatrix :: symmetrized()
01445 // Initializes the lower half of the receiver to the upper half.
01446 {
01447 #  ifdef DEBUG
01448     if ( nRows != nColumns ) {
01449         OOFEM_ERROR("FloatMatrix::symmetrized : cannot symmetrize a non-square matrix");
01450     }
01451 
01452 #   endif
01453 
01454     for ( int i = 2; i <= nRows; i++ ) {
01455         for ( int j = 1; j < i; j++ ) {
01456             this->at(i, j) = this->at(j, i);
01457         }
01458     }
01459 }
01460 
01461 
01462 void FloatMatrix :: times(double factor)
01463 // Multiplies every coefficient of the receiver by factor. Answers the
01464 // modified receiver.
01465 {
01466     int i;
01467     double *p;
01468 
01469     p = values;
01470     i = nRows * nColumns;
01471     while ( i-- ) {
01472         * p++ *= factor;
01473     }
01474 }
01475 
01476 
01477 void FloatMatrix :: negated()
01478 {
01479     int i;
01480     double *p;
01481 
01482     p = values;
01483     i = nRows * nColumns;
01484     while ( i-- ) {
01485         *p = -(*p);
01486         p++;
01487     }
01488 }
01489 
01490 
01491 double FloatMatrix :: computeFrobeniusNorm() const
01492 {
01493     int i, j;
01494     double answer = 0.0;
01495     for ( i = 1; i <= nRows; i++ ) {
01496         for ( j = 1; j <= nColumns; j++ ) {
01497             answer += this->at(i, j) * this->at(i, j);
01498         }
01499     }
01500 
01501     return sqrt(answer);
01502 }
01503 
01504 double FloatMatrix :: computeNorm(char p) const
01505 {
01506 #  ifdef __LAPACK_MODULE
01507     FloatArray work(this->giveNumberOfRows());
01508     int lda = max(this->nRows, 1);
01509     double norm = dlange_(&p, &this->nRows, &this->nColumns, this->values, &lda, work.givePointer(), 1);
01510     return norm;
01511 #  else
01512     if (p == '1') { // Maximum absolute column sum.
01513         double col_sum, max_col = 0.0;
01514         for (int j = 1; j <= this->nColumns; j++) {
01515             col_sum  = 0.0;
01516             for (int i = 1; i <= this->nRows; i++) {
01517                 col_sum += fabs(this->at(i, j));
01518             }
01519             if (col_sum > max_col) {
01520                 max_col = col_sum;
01521             }
01522         }
01523         return max_col;
01524     }
01526     /*else if (p == '2') {
01527         double lambda_max;
01528         FloatMatrix AtA;
01529         FloatArray eigs;
01530         AtA.beTProductOf(*this,this);
01531         Ata.eigenValues(eigs, 1);
01532         return sqrt(eigs(0));
01533     } */else {
01534         OOFEM_ERROR2("FloatMatrix::computeNorm(p) : p == %d not implemented.\n",p);
01535         return 0.0;
01536     }
01537 #  endif
01538 }
01539 
01540 double FloatMatrix :: computeReciprocalCondition(char p) const
01541 {
01542 #  ifdef DEBUG
01543     if ( !this->isSquare() ) {
01544         OOFEM_ERROR3("FloatMatrix::computeReciprocalCondition : receiver must be square (is %d by %d)", this->nRows, this->nColumns);
01545     }
01546 #  endif
01547     double anorm = this->computeNorm(p);
01548 
01549 #  ifdef __LAPACK_MODULE
01550     int n = this->nRows;
01551     FloatArray work(4*n);
01552     IntArray iwork(n);
01553     int info;
01554     double rcond;
01555 
01556     if (n > 3) { // Only use this routine for larger matrices. (not sure if it's suitable for n = 3) // Mikael
01557         FloatMatrix a_cpy = *this;
01558         dgetrf_(&n, &n, a_cpy.values, &n, iwork.givePointer(), &info);
01559         if (info < 0) {
01560             OOFEM_ERROR2("FloatMatrix::computeReciprocalCondition : dgetfr error %d\n",info);
01561         }
01562         dgecon_(&p, &(this->nRows), a_cpy.values, &this->nRows, &anorm, &rcond, work.givePointer(), iwork.givePointer(), &info, 1);
01563         if (info < 0) {
01564             OOFEM_ERROR2("FloatMatrix::computeReciprocalCondition : dgecon error %d\n",info);
01565         }
01566         return rcond;
01567     }
01568 #  endif
01569     if (this->giveDeterminant() <= 1e-6*anorm) {
01570         return 0.0;
01571     }
01572     FloatMatrix inv;
01573     inv.beInverseOf(*this);
01574     return 1.0/(inv.computeNorm(p)*anorm);
01575 }
01576 
01577 void FloatMatrix ::beMatrixForm(const FloatArray &aArray)
01578 {
01579     // Revrites the  matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12
01580 #  ifdef DEBUG
01581     if ( aArray.giveSize() !=6 && aArray.giveSize() !=9 ) {
01582         OOFEM_ERROR("FloatArray :: beMatrixForm : matrix dimension is not 3x3");
01583     }
01584 #  endif
01585     this->resize(3,3);
01586     if ( aArray.giveSize() == 9 ) {
01587         this->at(1,1) = aArray.at(1); this->at(2,2) = aArray.at(2); this->at(3,3) = aArray.at(3);
01588         this->at(2,3) = aArray.at(4); this->at(1,3) = aArray.at(5); this->at(1,2) = aArray.at(6);
01589         this->at(3,2) = aArray.at(7); this->at(3,1) = aArray.at(8); this->at(2,1) = aArray.at(9);
01590     }
01591     else if ( aArray.giveSize() == 6 ) {
01592         this->at(1,1) = aArray.at(1); this->at(2,2) = aArray.at(2); this->at(3,3) = aArray.at(3);
01593         this->at(2,3) = aArray.at(4); this->at(1,3) = aArray.at(5); this->at(1,2) = aArray.at(6);
01594         this->at(3,2) = aArray.at(4); this->at(3,1) = aArray.at(5); this->at(2,1) = aArray.at(6);
01595     }
01596 }
01597 
01598 #if 0
01599 bool FloatMatrix :: computeEigenValuesSymmetric(FloatArray &lambda, FloatMatrix &v, int neigs) const
01600 {
01601 #ifdef __LAPACK_MODULE
01602     double abstol = 1.0; 
01603     int lda, n, ldz, info, found, lwork;
01604     n = this->nRows;
01605     lda = n;
01606     ldz = n;
01607     FloatMatrix a;
01608     a = *this;
01609     if (neigs == 0) {
01610         neigs = n;
01611     }
01612 
01613     lambda.resize(neigs);
01614     v.resize(n, neigs);
01615 
01616     IntArray ifail(n), iwork(5*n);
01617     FloatArray work((n+3)*n); // maximum block size should be less than n (?)
01618     lwork = (n+3)*n;
01619     if ( neigs > 0 ) {
01620         int one = 1;
01621         dsyevx_("N", "I", "U",
01622                 &n, a.values, &n,
01623                 NULL, NULL, &one, &neigs,
01624                 &abstol, &found, lambda.givePointer(), v.givePointer(), &ldz,
01625                 work.givePointer(), &lwork, iwork.givePointer(), ifail.givePointer(), &info, 1, 1, 1);
01626     } else {
01627         dsyevx_("N", "A", "U",
01628                 &n, a.values, &n,
01629                 NULL, NULL, NULL, NULL,
01630                 &abstol, &found, lambda.givePointer(), v.givePointer(), &ldz,
01631                 work.givePointer(), &lwork, iwork.givePointer(), ifail.givePointer(), &info, 1, 1, 1);
01632     }
01633 
01634     return info == 0;
01635 #else
01636     OOFEM_ERROR("FloatMatrix::computeEigenValuesSymmetric : Requires LAPACK\n");
01637     return false;
01638 #endif
01639 }
01640 #endif
01641 
01642 contextIOResultType FloatMatrix :: storeYourself(DataStream *stream, ContextMode mode)
01643 // writes receiver's binary image into stream
01644 // use id to distinguish some instances
01645 // return value >0 success
01646 //              =0 file i/o error
01647 {
01648     // write size
01649     if ( !stream->write(& nRows, 1) ) {
01650         return ( CIO_IOERR );
01651     }
01652 
01653     if ( !stream->write(& nColumns, 1) ) {
01654         return ( CIO_IOERR );
01655     }
01656 
01657     // write raw data
01658     if ( !stream->write(values, nRows * nColumns) ) {
01659         return ( CIO_IOERR );
01660     }
01661 
01662     // return result back
01663     return CIO_OK;
01664 }
01665 
01666 
01667 contextIOResultType FloatMatrix :: restoreYourself(DataStream *stream, ContextMode mode)
01668 // reads receiver from stream
01669 // warning - overwrites existing data!
01670 // returns 0 if file i/o error
01671 //        -1 if id of class id is not correct
01672 {
01673     // read size
01674     if ( !stream->read(& nRows, 1) ) {
01675         return ( CIO_IOERR );
01676     }
01677 
01678     if ( !stream->read(& nColumns, 1) ) {
01679         return ( CIO_IOERR );
01680     }
01681 
01682     if ( values != NULL ) {
01683         freeDouble(values);
01684     }
01685 
01686     if ( nRows * nColumns ) {
01687         values = allocDouble(nRows * nColumns);
01688         allocatedSize = nRows * nColumns;
01689     } else {
01690         values = NULL;
01691         allocatedSize = 0;
01692     }
01693 
01694     // read raw data
01695     if ( !stream->read(values, nRows * nColumns) ) {
01696         return ( CIO_IOERR );
01697     }
01698 
01699     // return result back
01700     return CIO_OK;
01701 }
01702 
01703 
01704 bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf)
01705 {
01706     /*
01707      * Solves the eigenvalues and eigenvectors of real
01708      * symmetric matrix by jacobi method.
01709      *  Written by bp. Inspired by ED WILSON jaco_ procedure.
01710      *
01711      * Parameters (input):
01712      * nf - number of significant figures
01713      *
01714      * Output params:
01715      * eval - eigen values (not sorted)
01716      * v    - eigenvectors (stored columvise)
01717      */
01718 
01719 
01720     /* Local variables */
01721     double ssum, aa, co, si, tt, tol, sum, aij, aji;
01722     int ite, i, j, k, ih;
01723     int neq = this->giveNumberOfRows();
01724 
01725     double c_b2 = .10;
01726     //double c_b27 = .01;
01727 
01728     /* Function Body */
01729 #ifdef DEBUG
01730     if ( !isSquare() ) {
01731         OOFEM_ERROR("FloatMatrix::jaco_: Not square matrix");
01732     }
01733     // check for symmetry
01734     for ( i = 1; i <= neq; i++ ) {
01735         for ( j = i + 1; j <= neq; j++ ) {
01736             //if ( this->at(i, j) != this->at(j, i) ) {
01737             if ( fabs( this->at(i, j) - this->at(j, i) ) > 1.0e-6 ) {
01738                 OOFEM_ERROR("FloatMatrix::jaco_: Not Symmetric matrix");
01739             }
01740         }
01741     }
01742 
01743 #endif
01744 
01745     eval.resize(neq);
01746     v.resize(neq, neq);
01747 
01748     for ( i = 1; i <= neq; i++ ) {
01749         eval.at(i) = this->at(i, i);
01750     }
01751 
01752     tol = pow(c_b2, nf);
01753     sum = 0.0;
01754     for ( i = 1; i <= neq; ++i ) {
01755         for ( j = 1; j <= neq; ++j ) {
01756             sum += fabs( this->at(i, j) );
01757             v.at(i, j) = 0.0;
01758         }
01759 
01760         v.at(i, i) = 1.0;
01761     }
01762 
01763     if ( sum <= 0.0 ) {
01764         return 0;
01765     }
01766 
01767 
01768     /* ---- REDUCE MATRIX TO DIAGONAL ---------------- */
01769     ite = 0;
01770     do {
01771         ssum = 0.0;
01772         for ( j = 2; j <= neq; ++j ) {
01773             ih = j - 1;
01774             for ( i = 1; i <= ih; ++i ) {
01775                 if ( ( fabs( this->at(i, j) ) / sum ) > tol ) {
01776                     ssum += fabs( this->at(i, j) );
01777                     /* ---- CALCULATE ROTATION ANGLE ----------------- */
01778                     aa = atan2( this->at(i, j) * 2.0, eval.at(i) - eval.at(j) ) /  2.0;
01779                     si = sin(aa);
01780                     co = cos(aa);
01781                     /*
01782                      *   // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
01783                      *   for (k = 1; k <= neq; ++k) {
01784                      *    tt = this->at(k, i);
01785                      *    this->at(k, i) = co * tt + si * this->at(k, j);
01786                      *    this->at(k, j) = -si * tt + co * this->at(k, j);
01787                      *    tt = v.at(k, i);
01788                      *    v.at(k, i) = co * tt + si * v.at(k, j);
01789                      *    // L500:
01790                      *    v.at(k, j) = -si * tt + co * v.at(k, j);
01791                      *   }
01792                      *   // ---- MODIFY DIAGONAL TERMS --------------------
01793                      *   this->at(i, i) = co * this->at(i, i) + si * this->at(j, i);
01794                      *   this->at(j, j) = -si * this->at(i, j) + co * this->at(j, j);
01795                      *   this->at(i, j) = 0.0;
01796                      *   // ---- MAKE "A" MATRIX SYMMETRICAL --------------
01797                      *   for (k = 1; k <= neq; ++k) {
01798                      *    this->at(i, k) = this->at(k, i);
01799                      *    this->at(j, k) = this->at(k, j);
01800                      *    // L600:
01801                      *   }
01802                      */
01803                     // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
01804                     for ( k = 1; k < i; ++k ) {
01805                         tt = this->at(k, i);
01806                         this->at(k, i) = co * tt + si *this->at(k, j);
01807                         this->at(k, j) = -si * tt + co *this->at(k, j);
01808                         tt = v.at(k, i);
01809                         v.at(k, i) = co * tt + si *v.at(k, j);
01810                         v.at(k, j) = -si * tt + co *v.at(k, j);
01811                     }
01812 
01813                     // diagonal term (i,i)
01814                     tt = eval.at(i);
01815                     eval.at(i) = co * tt + si *this->at(i, j);
01816                     aij = -si * tt + co *this->at(i, j);
01817                     tt = v.at(i, i);
01818                     v.at(i, i) = co * tt + si *v.at(i, j);
01819                     v.at(i, j) = -si * tt + co *v.at(i, j);
01820 
01821                     for ( k = i + 1; k < j; ++k ) {
01822                         tt = this->at(i, k);
01823                         this->at(i, k) = co * tt + si *this->at(k, j);
01824                         this->at(k, j) = -si * tt + co *this->at(k, j);
01825                         tt = v.at(k, i);
01826                         v.at(k, i) = co * tt + si *v.at(k, j);
01827                         v.at(k, j) = -si * tt + co *v.at(k, j);
01828                     }
01829 
01830                     // diagonal term (j,j)
01831                     tt = this->at(i, j);
01832                     aji = co * tt + si *eval.at(j);
01833                     eval.at(j) = -si * tt + co *eval.at(j);
01834 
01835                     tt = v.at(j, i);
01836                     v.at(j, i) = co * tt + si *v.at(j, j);
01837                     v.at(j, j) = -si * tt + co *v.at(j, j);
01838                     //
01839                     for ( k = j + 1; k <= neq; ++k ) {
01840                         tt = this->at(i, k);
01841                         this->at(i, k) = co * tt + si *this->at(j, k);
01842                         this->at(j, k) = -si * tt + co *this->at(j, k);
01843                         tt = v.at(k, i);
01844                         v.at(k, i) = co * tt + si *v.at(k, j);
01845                         v.at(k, j) = -si * tt + co *v.at(k, j);
01846                     }
01847 
01848                     // ---- MODIFY DIAGONAL TERMS --------------------
01849                     eval.at(i) = co * eval.at(i) + si * aji;
01850                     eval.at(j) = -si * aij + co *eval.at(j);
01851                     this->at(i, j) = 0.0;
01852                 } else {
01853                     /* ---- A(I,J) MADE ZERO BY ROTATION ------------- */
01854                     ;
01855                 }
01856             }
01857         }
01858 
01859         /* ---- CHECK FOR CONVERGENCE -------------------- */
01860         if ( ++ite > 50 ) {
01861             OOFEM_ERROR("FloatMatrix::jaco_: too many iterations");
01862         }
01863     } while ( fabs(ssum) / sum > tol );
01864 
01865     // restore original matrix
01866     for ( i = 1; i <= neq; i++ ) {
01867         for ( j = i; j <= neq; j++ ) {
01868             this->at(i, j) = this->at(j, i);
01869         }
01870     }
01871 
01872     return 0;
01873 } /* jaco_ */
01874 
01875 
01876 
01877 #ifdef __PARALLEL_MODE
01878 int
01879 FloatMatrix :: packToCommBuffer(CommunicationBuffer &buff) const
01880 {
01881     int result = 1;
01882     // pack size
01883     result &= buff.packInt(nRows);
01884     result &= buff.packInt(nColumns);
01885     // pack data
01886     result &= buff.packArray(this->values, nRows * nColumns);
01887 
01888     return result;
01889 }
01890 
01891 int
01892 FloatMatrix :: unpackFromCommBuffer(CommunicationBuffer &buff)
01893 {
01894     int newNRows, newNColumns, result = 1;
01895     // unpack size
01896     result &= buff.unpackInt(newNRows);
01897     result &= buff.unpackInt(newNColumns);
01898     // resize yourself
01899     this->resize(newNRows, newNColumns);
01900     result &= buff.unpackArray(this->values, newNRows * newNColumns);
01901 
01902     return result;
01903 }
01904 
01905 int
01906 FloatMatrix :: givePackSize(CommunicationBuffer &buff)
01907 {
01908     return buff.givePackSize(MPI_INT, 1) + buff.givePackSize(MPI_INT, 1) +
01909            buff.givePackSize(MPI_DOUBLE, nRows * nColumns);
01910 }
01911 #endif
01912 
01913 #ifdef BOOST_PYTHON
01914 void
01915 FloatMatrix :: __setitem__ (boost::python::api::object t, double val)
01916 {
01917     this->at(boost::python::extract<int>(t[0])+1, boost::python::extract<int>(t[1])+1 ) = val;
01918 }
01919 
01920 double
01921 FloatMatrix :: __getitem__ (boost::python::api::object t)
01922 {
01923     return this->at(boost::python::extract<int>(t[0])+1, boost::python::extract<int>(t[1])+1 );
01924 }
01925 #endif
01926 
01927 } // end namespace oofem

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Sun Mar 10 2013 18:16:54 for OOFEM by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2011