dune-common 2.1.1
|
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