dune-common  2.3.0
fmatrix.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // $Id$
4 #ifndef DUNE_FMATRIX_HH
5 #define DUNE_FMATRIX_HH
6 
7 #include <cmath>
8 #include <cstddef>
9 #include <iostream>
10 
12 #include <dune/common/fvector.hh>
14 #include <dune/common/precision.hh>
17 
18 namespace Dune
19 {
20 
32  template< class K, int ROWS, int COLS > class FieldMatrix;
33 
34  template< class K, int ROWS, int COLS >
35  struct DenseMatVecTraits< FieldMatrix<K,ROWS,COLS> >
36  {
38 
39  // each row is implemented by a field vector
41 
43  typedef const row_type &const_row_reference;
44 
46  typedef K value_type;
48  };
49 
50  template< class K, int ROWS, int COLS >
51  struct FieldTraits< FieldMatrix<K,ROWS,COLS> >
52  {
55  };
56 
65  template<class K, int ROWS, int COLS>
66  class FieldMatrix : public DenseMatrix< FieldMatrix<K,ROWS,COLS> >
67  {
70  public:
71 
73  enum {
75  rows = ROWS,
77  cols = COLS
78  };
79 
80  typedef typename Base::size_type size_type;
81  typedef typename Base::row_type row_type;
82 
85 
86  //===== constructors
90 
93  template< class Other >
94  FieldMatrix ( const Other &other )
95  {
96  DenseMatrixAssigner< FieldMatrix< K, ROWS, COLS >, Other >::apply( *this, other );
97  }
98 
99  //===== assignment
100  using Base::operator=;
101 
102  // To be removed!
103 #if 0
104 
106  {
107  FieldMatrix<K,rows,cols> C(*this);
108 
109  for (size_type i=0; i<rows; i++)
110  for (size_type j=0; j<cols; j++) {
111  (*this)[i][j] = 0;
112  for (size_type k=0; k<rows; k++)
113  (*this)[i][j] += M[i][k]*C[k][j];
114  }
115 
116  return *this;
117  }
118 #endif
119 
121  template<int l>
123  {
125 
126  for (size_type i=0; i<l; i++) {
127  for (size_type j=0; j<cols; j++) {
128  C[i][j] = 0;
129  for (size_type k=0; k<rows; k++)
130  C[i][j] += M[i][k]*(*this)[k][j];
131  }
132  }
133  return C;
134  }
135 
138  {
139  FieldMatrix<K,rows,cols> C(*this);
140 
141  for (size_type i=0; i<rows; i++)
142  for (size_type j=0; j<cols; j++) {
143  (*this)[i][j] = 0;
144  for (size_type k=0; k<cols; k++)
145  (*this)[i][j] += C[i][k]*M[k][j];
146  }
147  return *this;
148  }
149 
151  template<int l>
153  {
155 
156  for (size_type i=0; i<rows; i++) {
157  for (size_type j=0; j<l; j++) {
158  C[i][j] = 0;
159  for (size_type k=0; k<cols; k++)
160  C[i][j] += (*this)[i][k]*M[k][j];
161  }
162  }
163  return C;
164  }
165 
166  // make this thing a matrix
167  DUNE_CONSTEXPR size_type mat_rows() const { return ROWS; }
168  DUNE_CONSTEXPR size_type mat_cols() const { return COLS; }
169 
171  {
172  assert(i < ROWS);
173  return _data[i];
174  }
175 
177  {
178  assert(i < ROWS);
179  return _data[i];
180  }
181  };
182 
183 #ifndef DOXYGEN // hide specialization
184 
186  template<class K>
187  class FieldMatrix<K,1,1> : public DenseMatrix< FieldMatrix<K,1,1> >
188  {
189  FieldVector<K,1> _data;
190  typedef DenseMatrix< FieldMatrix<K,1,1> > Base;
191  public:
192  // standard constructor and everything is sufficient ...
193 
194  //===== type definitions and constants
195 
197  typedef typename Base::size_type size_type;
198 
200  enum {
203  blocklevel = 1
204  };
205 
206  typedef typename Base::row_type row_type;
207 
208  typedef typename Base::row_reference row_reference;
210 
212  enum {
215  rows = 1,
218  cols = 1
219  };
220 
221  //===== constructors
224  FieldMatrix () {}
225 
228  FieldMatrix (const K& k)
229  {
230  _data[0] = k;
231  }
232 
233  template< class Other >
234  FieldMatrix ( const Other &other )
235  {
236  DenseMatrixAssigner< FieldMatrix< K, 1, 1 >, Other >::apply( *this, other );
237  }
238 
239  //===== solve
240 
242  template<int l>
243  FieldMatrix<K,l,1> leftmultiplyany (const FieldMatrix<K,l,1>& M) const
244  {
245  FieldMatrix<K,l,1> C;
246  for (size_type j=0; j<l; j++)
247  C[j][0] = M[j][0]*(*this)[0][0];
248  return C;
249  }
250 
253  {
254  _data[0] *= M[0][0];
255  return *this;
256  }
257 
259  template<int l>
260  FieldMatrix<K,1,l> rightmultiplyany (const FieldMatrix<K,1,l>& M) const
261  {
262  FieldMatrix<K,1,l> C;
263 
264  for (size_type j=0; j<l; j++)
265  C[0][j] = M[0][j]*_data[0];
266  return C;
267  }
268 
269  // make this thing a matrix
270  DUNE_CONSTEXPR size_type mat_rows() const { return 1; }
271  DUNE_CONSTEXPR size_type mat_cols() const { return 1; }
272 
274  {
275  assert(i == 0);
276  return _data;
277  }
278 
280  {
281  assert(i == 0);
282  return _data;
283  }
284 
286  FieldMatrix& operator+= (const K& k)
287  {
288  _data[0] += k;
289  return (*this);
290  }
291 
293  FieldMatrix& operator-= (const K& k)
294  {
295  _data[0] -= k;
296  return (*this);
297  }
298 
300  FieldMatrix& operator*= (const K& k)
301  {
302  _data[0] *= k;
303  return (*this);
304  }
305 
307  FieldMatrix& operator/= (const K& k)
308  {
309  _data[0] /= k;
310  return (*this);
311  }
312 
313  //===== conversion operator
314 
315  operator K () const { return _data[0]; }
316 
317  };
318 
320  template<typename K>
321  std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,1,1>& a)
322  {
323  s << a[0][0];
324  return s;
325  }
326 
327 #endif // DOXYGEN
328 
329  namespace FMatrixHelp {
330 
332  template <typename K>
333  static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
334  {
335  inverse[0][0] = 1.0/matrix[0][0];
336  return matrix[0][0];
337  }
338 
340  template <typename K>
341  static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
342  {
343  return invertMatrix(matrix,inverse);
344  }
345 
346 
348  template <typename K>
349  static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
350  {
351  // code generated by maple
352  K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
353  K det_1 = 1.0/det;
354  inverse[0][0] = matrix[1][1] * det_1;
355  inverse[0][1] = - matrix[0][1] * det_1;
356  inverse[1][0] = - matrix[1][0] * det_1;
357  inverse[1][1] = matrix[0][0] * det_1;
358  return det;
359  }
360 
363  template <typename K>
364  static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
365  {
366  // code generated by maple
367  K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
368  K det_1 = 1.0/det;
369  inverse[0][0] = matrix[1][1] * det_1;
370  inverse[1][0] = - matrix[0][1] * det_1;
371  inverse[0][1] = - matrix[1][0] * det_1;
372  inverse[1][1] = matrix[0][0] * det_1;
373  return det;
374  }
375 
377  template <typename K>
378  static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
379  {
380  // code generated by maple
381  K t4 = matrix[0][0] * matrix[1][1];
382  K t6 = matrix[0][0] * matrix[1][2];
383  K t8 = matrix[0][1] * matrix[1][0];
384  K t10 = matrix[0][2] * matrix[1][0];
385  K t12 = matrix[0][1] * matrix[2][0];
386  K t14 = matrix[0][2] * matrix[2][0];
387 
388  K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
389  t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
390  K t17 = 1.0/det;
391 
392  inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
393  inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
394  inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
395  inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
396  inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
397  inverse[1][2] = -(t6-t10) * t17;
398  inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
399  inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
400  inverse[2][2] = (t4-t8) * t17;
401 
402  return det;
403  }
404 
406  template <typename K>
407  static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
408  {
409  // code generated by maple
410  K t4 = matrix[0][0] * matrix[1][1];
411  K t6 = matrix[0][0] * matrix[1][2];
412  K t8 = matrix[0][1] * matrix[1][0];
413  K t10 = matrix[0][2] * matrix[1][0];
414  K t12 = matrix[0][1] * matrix[2][0];
415  K t14 = matrix[0][2] * matrix[2][0];
416 
417  K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
418  t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
419  K t17 = 1.0/det;
420 
421  inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
422  inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
423  inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
424  inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
425  inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
426  inverse[2][1] = -(t6-t10) * t17;
427  inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
428  inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
429  inverse[2][2] = (t4-t8) * t17;
430 
431  return det;
432  }
433 
435  template< class K, int m, int n, int p >
436  static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
437  const FieldMatrix< K, n, p > &B,
439  {
440  typedef typename FieldMatrix< K, m, p > :: size_type size_type;
441 
442  for( size_type i = 0; i < m; ++i )
443  {
444  for( size_type j = 0; j < p; ++j )
445  {
446  ret[ i ][ j ] = K( 0 );
447  for( size_type k = 0; k < n; ++k )
448  ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
449  }
450  }
451  }
452 
454  template <typename K, int rows, int cols>
456  {
457  typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
458 
459  for(size_type i=0; i<cols; i++)
460  for(size_type j=0; j<cols; j++)
461  {
462  ret[i][j]=0.0;
463  for(size_type k=0; k<rows; k++)
464  ret[i][j]+=matrix[k][i]*matrix[k][j];
465  }
466  }
467 
468 #if 0
469 
470  template <typename K, int rows, int cols>
471  static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret)
472  {
473  typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
474 
475  for(size_type i=0; i<rows; ++i)
476  {
477  ret[i] = 0.0;
478  for(size_type j=0; j<cols; ++j)
479  {
480  ret[i] += matrix[i][j]*x[j];
481  }
482  }
483  }
484 #else
486 #endif
487 
489  template <typename K, int rows, int cols>
490  static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
491  {
492  typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
493 
494  for(size_type i=0; i<cols; ++i)
495  {
496  ret[i] = 0.0;
497  for(size_type j=0; j<rows; ++j)
498  ret[i] += matrix[j][i]*x[j];
499  }
500  }
501 
503  template <typename K, int rows, int cols>
505  {
507  multAssign(matrix,x,ret);
508  return ret;
509  }
510 
512  template <typename K, int rows, int cols>
514  {
516  multAssignTransposed( matrix, x, ret );
517  return ret;
518  }
519 
520  } // end namespace FMatrixHelp
521 
524 } // end namespace
525 
526 #include "fmatrixev.hh"
527 #endif