dune-common 2.1.1
fmatrix.hh
Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=8 sw=2 sts=2:
00003 // $Id: fmatrix.hh 6188 2010-10-19 09:08:08Z christi $
00004 #ifndef DUNE_FMATRIX_HH
00005 #define DUNE_FMATRIX_HH
00006 
00007 #include <cmath>
00008 #include <cstddef>
00009 #include <iostream>
00010 
00011 #include <dune/common/misc.hh>
00012 #include <dune/common/exceptions.hh>
00013 #include <dune/common/fvector.hh>
00014 #include <dune/common/densematrix.hh>
00015 #include <dune/common/precision.hh>
00016 #include <dune/common/static_assert.hh>
00017 
00018 namespace Dune
00019 {
00020    
00032   template< class K, int ROWS, int COLS > class FieldMatrix;
00033   template< class K, int ROWS, int COLS >
00034   struct DenseMatVecTraits< FieldMatrix<K,ROWS,COLS> >
00035   {
00036     typedef FieldMatrix<K,ROWS,COLS> derived_type;
00037     typedef FieldVector<K,COLS> row_type;
00038     typedef Dune::array<row_type,ROWS> container_type;
00039     typedef K value_type;
00040     typedef typename container_type::size_type size_type;
00041   };
00042   
00043   template< class K, int ROWS, int COLS >
00044   struct FieldTraits< FieldMatrix<K,ROWS,COLS> >
00045   {
00046     typedef typename FieldTraits<K>::field_type field_type;
00047     typedef typename FieldTraits<K>::real_type real_type;
00048   };
00049 
00058   template<class K, int ROWS, int COLS>
00059   class FieldMatrix : public DenseMatrix< FieldMatrix<K,ROWS,COLS> >
00060   {
00061     Dune::array< FieldVector<K,COLS>, ROWS > _data;
00062     typedef DenseMatrix< FieldMatrix<K,ROWS,COLS> > Base;
00063   public:
00064 
00066     enum {
00068       rows = ROWS, 
00070       cols = COLS
00071     };
00072 
00073     typedef typename Base::size_type size_type;
00074     typedef typename Base::row_type row_type;
00075     
00076     //===== constructors
00079     FieldMatrix () {}
00080 
00083     explicit FieldMatrix (const K& k)
00084     {
00085       for (size_type i=0; i<rows; i++) _data[i] = k;
00086     }
00087 
00088     template<typename T>
00089     explicit FieldMatrix (const T& t)
00090     {
00091       DenseMatrixAssigner<Conversion<T,K>::exists>::assign(*this, t);
00092     }
00093     
00094     //===== assignment
00095     using Base::operator=;
00096 
00097     // To be removed!
00098 #if 0
00099 
00100     FieldMatrix& leftmultiply (const FieldMatrix<K,rows,rows>& M)
00101     {
00102       FieldMatrix<K,rows,cols> C(*this);
00103       
00104       for (size_type i=0; i<rows; i++)
00105         for (size_type j=0; j<cols; j++) {
00106           (*this)[i][j] = 0;
00107           for (size_type k=0; k<rows; k++)
00108             (*this)[i][j] += M[i][k]*C[k][j];
00109         }
00110       
00111       return *this;
00112     }
00113 #endif
00114  
00116     template<int l>
00117     FieldMatrix<K,l,cols> leftmultiplyany (const FieldMatrix<K,l,rows>& M) const
00118     {
00119       FieldMatrix<K,l,cols> C;
00120       
00121       for (size_type i=0; i<l; i++) {
00122         for (size_type j=0; j<cols; j++) {
00123           C[i][j] = 0;
00124           for (size_type k=0; k<rows; k++)
00125             C[i][j] += M[i][k]*(*this)[k][j];
00126         }
00127       }
00128       return C;
00129     }
00130 
00132     FieldMatrix& rightmultiply (const FieldMatrix<K,cols,cols>& M)
00133     {
00134       FieldMatrix<K,rows,cols> C(*this);
00135       
00136       for (size_type i=0; i<rows; i++)
00137         for (size_type j=0; j<cols; j++) {
00138           (*this)[i][j] = 0;
00139           for (size_type k=0; k<cols; k++)
00140             (*this)[i][j] += C[i][k]*M[k][j];
00141         }
00142       return *this;
00143     }
00144 
00146     template<int l>
00147     FieldMatrix<K,rows,l> rightmultiplyany (const FieldMatrix<K,cols,l>& M) const
00148     {
00149       FieldMatrix<K,rows,l> C;
00150       
00151       for (size_type i=0; i<rows; i++) {
00152         for (size_type j=0; j<l; j++) {
00153           C[i][j] = 0;
00154           for (size_type k=0; k<cols; k++)
00155             C[i][j] += (*this)[i][k]*M[k][j];
00156         }
00157       }
00158       return C;
00159     }
00160     
00161     // make this thing a matrix
00162     size_type mat_rows() const { return ROWS; }
00163     size_type mat_cols() const { return COLS; }
00164     row_type & mat_access(size_type i) {
00165       assert(i < ROWS);
00166       return _data[i];
00167     }
00168     const row_type & mat_access(size_type i) const {
00169       assert(i < ROWS);
00170       return _data[i];
00171     }
00172   };
00173 
00174 #ifndef DOXYGEN // hide specialization
00175 
00177   template<class K>
00178   class FieldMatrix<K,1,1> : public DenseMatrix< FieldMatrix<K,1,1> >
00179   {
00180     FieldVector<K,1> _data;
00181     typedef DenseMatrix< FieldMatrix<K,1,1> > Base;
00182   public:
00183     // standard constructor and everything is sufficient ...
00184     
00185     //===== type definitions and constants
00186     
00188     typedef typename Base::size_type size_type;
00189     
00191     enum {
00194       blocklevel = 1
00195     };
00196 
00198     typedef FieldVector<K,1> row_type; 
00199 
00201     enum {
00204       rows = 1,
00207       cols = 1
00208     };
00209 
00210     //===== constructors
00213     FieldMatrix () {}
00214     
00217     FieldMatrix (const K& k)
00218     {
00219       _data[0] = k;
00220     }
00221     template<typename T>
00222     FieldMatrix(const T& t)
00223     {
00224       DenseMatrixAssigner<Conversion<T,K>::exists>::assign(*this, t);
00225     }
00226     
00227     //===== solve
00228 
00230     template<int l>
00231     FieldMatrix<K,l,1> leftmultiplyany (const FieldMatrix<K,l,1>& M) const
00232     {
00233       FieldMatrix<K,l,1> C;
00234       for (size_type j=0; j<l; j++)
00235         C[j][0] = M[j][0]*(*this)[0][0];
00236       return C;
00237     }
00238 
00240     FieldMatrix& rightmultiply (const FieldMatrix& M)
00241     {
00242       _data[0] *= M[0][0];
00243       return *this;
00244     }
00245 
00247     template<int l>
00248     FieldMatrix<K,1,l> rightmultiplyany (const FieldMatrix<K,1,l>& M) const
00249     {
00250       FieldMatrix<K,1,l> C;
00251       
00252       for (size_type j=0; j<l; j++)
00253         C[0][j] = M[0][j]*_data[0];
00254       return C;
00255     }
00256 
00257     // make this thing a matrix
00258     size_type mat_rows() const { return 1; }
00259     size_type mat_cols() const { return 1; }
00260     row_type & mat_access(size_type i) {
00261       assert(i == 0);
00262       return _data;
00263     }
00264     const row_type & mat_access(size_type i) const {
00265       assert(i == 0);
00266       return _data;
00267     }
00268 
00270     FieldMatrix& operator+= (const K& k)
00271     {
00272       _data[0] += k;
00273       return (*this);
00274     }
00275 
00277     FieldMatrix& operator-= (const K& k)
00278     {
00279       _data[0] -= k;
00280       return (*this);
00281     }
00282     
00284     FieldMatrix& operator*= (const K& k)
00285     {
00286       _data[0] *= k;
00287       return (*this);
00288     }
00289 
00291     FieldMatrix& operator/= (const K& k)
00292     {
00293       _data[0] /= k;
00294       return (*this);
00295     }
00296 
00297     //===== conversion operator
00298 
00299     operator K () const { return _data[0]; }
00300 
00301   };
00302 
00304   template<typename K>
00305   std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,1,1>& a)
00306   {
00307     s << a[0][0];
00308     return s;
00309   }
00310 
00311 #endif // DOXYGEN
00312 
00313 namespace FMatrixHelp {
00314 
00316 template <typename K>
00317 static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
00318 {
00319   inverse[0][0] = 1.0/matrix[0][0];
00320   return matrix[0][0];
00321 }
00322 
00324 template <typename K>
00325 static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
00326 {
00327   return invertMatrix(matrix,inverse); 
00328 }
00329 
00330 
00332 template <typename K>
00333 static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
00334 {
00335   // code generated by maple 
00336   K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
00337   K det_1 = 1.0/det;
00338   inverse[0][0] =   matrix[1][1] * det_1;
00339   inverse[0][1] = - matrix[0][1] * det_1;
00340   inverse[1][0] = - matrix[1][0] * det_1;
00341   inverse[1][1] =   matrix[0][0] * det_1;
00342   return det;
00343 }
00344 
00347 template <typename K>
00348 static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
00349 {
00350   // code generated by maple 
00351   K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
00352   K det_1 = 1.0/det;
00353   inverse[0][0] =   matrix[1][1] * det_1;
00354   inverse[1][0] = - matrix[0][1] * det_1;
00355   inverse[0][1] = - matrix[1][0] * det_1;
00356   inverse[1][1] =   matrix[0][0] * det_1;
00357   return det;
00358 }
00359 
00361 template <typename K>
00362 static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
00363 {
00364   // code generated by maple 
00365   K t4  = matrix[0][0] * matrix[1][1];
00366   K t6  = matrix[0][0] * matrix[1][2];
00367   K t8  = matrix[0][1] * matrix[1][0];
00368   K t10 = matrix[0][2] * matrix[1][0];
00369   K t12 = matrix[0][1] * matrix[2][0];
00370   K t14 = matrix[0][2] * matrix[2][0];
00371 
00372   K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
00373            t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
00374   K t17 = 1.0/det;
00375 
00376   inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
00377   inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
00378   inverse[0][2] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
00379   inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
00380   inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
00381   inverse[1][2] = -(t6-t10) * t17;
00382   inverse[2][0] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
00383   inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
00384   inverse[2][2] =  (t4-t8) * t17;
00385 
00386   return det;
00387 }
00388 
00390 template <typename K>
00391 static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
00392 {
00393   // code generated by maple 
00394   K t4  = matrix[0][0] * matrix[1][1];
00395   K t6  = matrix[0][0] * matrix[1][2];
00396   K t8  = matrix[0][1] * matrix[1][0];
00397   K t10 = matrix[0][2] * matrix[1][0];
00398   K t12 = matrix[0][1] * matrix[2][0];
00399   K t14 = matrix[0][2] * matrix[2][0];
00400 
00401   K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
00402            t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
00403   K t17 = 1.0/det;
00404 
00405   inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
00406   inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
00407   inverse[2][0] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
00408   inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
00409   inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
00410   inverse[2][1] = -(t6-t10) * t17;
00411   inverse[0][2] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
00412   inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
00413   inverse[2][2] =  (t4-t8) * t17;
00414 
00415   return det;
00416 }
00417 
00419 template< class K, int m, int n, int p >
00420 static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
00421                                 const FieldMatrix< K, n, p > &B,
00422                                 FieldMatrix< K, m, p > &ret )
00423 {
00424   typedef typename FieldMatrix< K, m, p > :: size_type size_type;
00425 
00426   for( size_type i = 0; i < m; ++i )
00427   {
00428     for( size_type j = 0; j < p; ++j )
00429     {
00430       ret[ i ][ j ] = K( 0 );
00431       for( size_type k = 0; k < n; ++k )
00432         ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
00433     }
00434   }
00435 }
00436 
00438 template <typename K, int rows, int cols>
00439 static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
00440 {
00441   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
00442   
00443   for(size_type i=0; i<cols; i++)
00444     for(size_type j=0; j<cols; j++)
00445     {
00446       ret[i][j]=0.0;
00447       for(size_type k=0; k<rows; k++)
00448         ret[i][j]+=matrix[k][i]*matrix[k][j];
00449     }
00450 }
00451 
00452 #if 0
00453 
00454 template <typename K, int rows, int cols>
00455 static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret) 
00456 {
00457   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
00458   
00459   for(size_type i=0; i<rows; ++i)
00460   {
00461     ret[i] = 0.0;
00462     for(size_type j=0; j<cols; ++j)
00463     {
00464       ret[i] += matrix[i][j]*x[j];
00465     }
00466   }
00467 }
00468 #else
00469 using Dune::DenseMatrixHelp::multAssign;
00470 #endif
00471 
00473 template <typename K, int rows, int cols>
00474 static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret) 
00475 {
00476   typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
00477   
00478   for(size_type i=0; i<cols; ++i)
00479   {
00480     ret[i] = 0.0;
00481     for(size_type j=0; j<rows; ++j)
00482       ret[i] += matrix[j][i]*x[j];
00483   }
00484 }
00485 
00487 template <typename K, int rows, int cols>
00488 static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x) 
00489 {
00490   FieldVector<K,rows> ret;
00491   multAssign(matrix,x,ret);
00492   return ret;
00493 }
00494 
00496 template <typename K, int rows, int cols>
00497 static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x) 
00498 {
00499   FieldVector<K,cols> ret;
00500   multAssignTransposed( matrix, x, ret );
00501   return ret; 
00502 }
00503 
00504 } // end namespace FMatrixHelp 
00505 
00508 } // end namespace
00509 
00510 #include "fmatrixev.hh"
00511 #endif