Dune Core Modules (2.4.2)

densematrix.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 #ifndef DUNE_DENSEMATRIX_HH
4 #define DUNE_DENSEMATRIX_HH
5 
6 #include <cmath>
7 #include <cstddef>
8 #include <iostream>
9 #include <vector>
10 
12 #include <dune/common/fvector.hh>
13 #include <dune/common/precision.hh>
14 #include <dune/common/classname.hh>
15 #include <dune/common/math.hh>
16 #include <dune/common/unused.hh>
17 
18 
19 namespace Dune
20 {
21 
22  template<typename M> class DenseMatrix;
23 
24  template<typename M>
25  struct FieldTraits< DenseMatrix<M> >
26  {
27  typedef const typename FieldTraits< typename DenseMatVecTraits<M>::value_type >::field_type field_type;
28  typedef const typename FieldTraits< typename DenseMatVecTraits<M>::value_type >::real_type real_type;
29  };
30 
31  /*
32  work around a problem of FieldMatrix/FieldVector,
33  there is no unique way to obtain the size of a class
34  */
35  template<class K, int N, int M> class FieldMatrix;
36  template<class K, int N> class FieldVector;
37  namespace {
38  template<class V>
39  struct VectorSize
40  {
41  static typename V::size_type size(const V & v) { return v.size(); }
42  };
43 
44  template<class K, int N>
45  struct VectorSize< const FieldVector<K,N> >
46  {
47  typedef FieldVector<K,N> V;
48  static typename V::size_type size(const V & v) { return N; }
49  };
50  }
51 
70  template< class DenseMatrix, class RHS >
72 
73 
74 
75  template< class DenseMatrix, class K, int N, int M >
76  void istl_assign_to_fmatrix ( DenseMatrix &denseMatrix, const K (&values)[ M ][ N ] )
77  {
78  for( int i = 0; i < N; ++i )
79  for( int j = 0; j < M; ++j )
80  denseMatrix[ i ][ j ] = values[ i ][ j ];
81  }
82 
83 
84 
85 #ifndef DOXYGEN
86  namespace
87  {
88  template< class DenseMatrix, class RHS,
90  class DenseMatrixAssignerImplementation;
91 
92  template< class DenseMatrix, class RHS >
93  class DenseMatrixAssignerImplementation< DenseMatrix, RHS, true >
94  {
95  public:
96  static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
97  {
98  typedef typename DenseMatrix::field_type field_type;
99  std::fill( denseMatrix.begin(), denseMatrix.end(), static_cast< field_type >( rhs ) );
100  }
101  };
102 
103  template< class DenseMatrix, class RHS >
104  class DenseMatrixAssignerImplementation< DenseMatrix, RHS, false >
105  {
106  template< class M, class T>
107  struct have_istl_assign_to_fmatrix
108  {
109  struct yes { char dummy[ 1 ]; };
110  struct no { char dummy[ 2 ]; };
111 
112  template< class C>
113  static C &get_ref();
114 
115  template< class C>
116  static yes test( decltype( istl_assign_to_fmatrix( get_ref< M >(), get_ref< C >() ) ) * );
117  template< class C >
118  static no test(...);
119 
120  public:
121  static const bool v = sizeof( test< const T >( 0 ) ) == sizeof( yes );
122  };
123 
124  template< class M, class T, bool = have_istl_assign_to_fmatrix< M, T >::v >
125  struct DefaultImplementation;
126 
127  // forward to istl_assign_to_fmatrix()
128  template< class M, class T >
129  struct DefaultImplementation< M, T, true >
130  {
131  static void apply ( M &m, const T &t )
132  {
133  istl_assign_to_fmatrix( m, t );
134  }
135  };
136 
137  // static_cast
138  template< class M, class T >
139  struct DefaultImplementation< M, T, false >
140  {
141  static void apply ( M &m, const T &t )
142  {
143  static_assert( (Conversion< const T, const M >::exists), "No template specialization of DenseMatrixAssigner found" );
144  m = static_cast< const M & >( t );
145  }
146  };
147 
148  public:
149  static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
150  {
151  DefaultImplementation< DenseMatrix, RHS >::apply( denseMatrix, rhs );
152  }
153  };
154  }
155 
156 
157 
158  template< class DenseMatrix, class RHS >
159  struct DenseMatrixAssigner
160  {
161  static void apply ( DenseMatrix &denseMatrix, const RHS &rhs )
162  {
163  DenseMatrixAssignerImplementation< DenseMatrix, RHS >::apply( denseMatrix, rhs );
164  }
165  };
166 #endif // #ifndef DOXYGEN
167 
168 
169 
171  class FMatrixError : public MathError {};
172 
183  template<typename MAT>
185  {
186  typedef DenseMatVecTraits<MAT> Traits;
187 
188  // Curiously recurring template pattern
189  MAT & asImp() { return static_cast<MAT&>(*this); }
190  const MAT & asImp() const { return static_cast<const MAT&>(*this); }
191 
192  public:
193  //===== type definitions and constants
194 
196  typedef typename Traits::derived_type derived_type;
197 
199  typedef typename Traits::value_type value_type;
200 
202  typedef typename Traits::value_type field_type;
203 
205  typedef typename Traits::value_type block_type;
206 
208  typedef typename Traits::size_type size_type;
209 
211  typedef typename Traits::row_type row_type;
212 
214  typedef typename Traits::row_reference row_reference;
215 
217  typedef typename Traits::const_row_reference const_row_reference;
218 
220  enum {
222  blocklevel = 1
223  };
224 
225  //===== access to components
226 
229  {
230  return asImp().mat_access(i);
231  }
232 
234  {
235  return asImp().mat_access(i);
236  }
237 
239  size_type size() const
240  {
241  return rows();
242  }
243 
244  //===== iterator interface to rows of the matrix
252  typedef typename remove_reference<row_reference>::type::Iterator ColIterator;
253 
256  {
257  return Iterator(*this,0);
258  }
259 
262  {
263  return Iterator(*this,rows());
264  }
265 
269  {
270  return Iterator(*this,rows()-1);
271  }
272 
276  {
277  return Iterator(*this,-1);
278  }
279 
287  typedef typename remove_reference<const_row_reference>::type::ConstIterator ConstColIterator;
288 
291  {
292  return ConstIterator(*this,0);
293  }
294 
297  {
298  return ConstIterator(*this,rows());
299  }
300 
304  {
305  return ConstIterator(*this,rows()-1);
306  }
307 
311  {
312  return ConstIterator(*this,-1);
313  }
314 
315  //===== assignment
316 
317  template< class RHS >
318  DenseMatrix &operator= ( const RHS &rhs )
319  {
321  return *this;
322  }
323 
324  //===== vector space arithmetic
325 
327  template <class Other>
329  {
330  for (size_type i=0; i<rows(); i++)
331  (*this)[i] += y[i];
332  return *this;
333  }
334 
336  template <class Other>
338  {
339  for (size_type i=0; i<rows(); i++)
340  (*this)[i] -= y[i];
341  return *this;
342  }
343 
346  {
347  for (size_type i=0; i<rows(); i++)
348  (*this)[i] *= k;
349  return *this;
350  }
351 
354  {
355  for (size_type i=0; i<rows(); i++)
356  (*this)[i] /= k;
357  return *this;
358  }
359 
361  template <class Other>
363  {
364  for( size_type i = 0; i < rows(); ++i )
365  (*this)[ i ].axpy( k, y[ i ] );
366  return *this;
367  }
368 
370  template <class Other>
371  bool operator== (const DenseMatrix<Other>& y) const
372  {
373  for (size_type i=0; i<rows(); i++)
374  if ((*this)[i]!=y[i])
375  return false;
376  return true;
377  }
379  template <class Other>
380  bool operator!= (const DenseMatrix<Other>& y) const
381  {
382  return !operator==(y);
383  }
384 
385 
386  //===== linear maps
387 
389  template<class X, class Y>
390  void mv (const X& x, Y& y) const
391  {
392 #ifdef DUNE_FMatrix_WITH_CHECKING
393  assert( (void*)(&x) != (void*)(&y) );
394  if (x.N()!=M()) DUNE_THROW(FMatrixError,"Index out of range");
395  if (y.N()!=N()) DUNE_THROW(FMatrixError,"Index out of range");
396 #endif
397  for (size_type i=0; i<rows(); ++i)
398  {
399  y[i] = value_type(0);
400  for (size_type j=0; j<cols(); j++)
401  y[i] += (*this)[i][j] * x[j];
402  }
403  }
404 
406  template< class X, class Y >
407  void mtv ( const X &x, Y &y ) const
408  {
409 #ifdef DUNE_FMatrix_WITH_CHECKING
410  assert( (void*)(&x) != (void*)(&y) );
411  if( x.N() != N() )
412  DUNE_THROW( FMatrixError, "Index out of range." );
413  if( y.N() != M() )
414  DUNE_THROW( FMatrixError, "Index out of range." );
415 #endif
416  for( size_type i = 0; i < cols(); ++i )
417  {
418  y[ i ] = value_type(0);
419  for( size_type j = 0; j < rows(); ++j )
420  y[ i ] += (*this)[ j ][ i ] * x[ j ];
421  }
422  }
423 
425  template<class X, class Y>
426  void umv (const X& x, Y& y) const
427  {
428 #ifdef DUNE_FMatrix_WITH_CHECKING
429  if (x.N()!=M())
430  DUNE_THROW(FMatrixError,"y += A x -- index out of range (sizes: x: " << x.N() << ", y: " << y.N() << ", A: " << this->N() << " x " << this->M() << ")" << std::endl);
431  if (y.N()!=N())
432  DUNE_THROW(FMatrixError,"y += A x -- index out of range (sizes: x: " << x.N() << ", y: " << y.N() << ", A: " << this->N() << " x " << this->M() << ")" << std::endl);
433 #endif
434  for (size_type i=0; i<rows(); i++)
435  for (size_type j=0; j<cols(); j++)
436  y[i] += (*this)[i][j] * x[j];
437  }
438 
440  template<class X, class Y>
441  void umtv (const X& x, Y& y) const
442  {
443 #ifdef DUNE_FMatrix_WITH_CHECKING
444  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
445  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
446 #endif
447 
448  for (size_type i=0; i<rows(); i++)
449  for (size_type j=0; j<cols(); j++)
450  y[j] += (*this)[i][j]*x[i];
451  }
452 
454  template<class X, class Y>
455  void umhv (const X& x, Y& y) const
456  {
457 #ifdef DUNE_FMatrix_WITH_CHECKING
458  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
459  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
460 #endif
461 
462  for (size_type i=0; i<rows(); i++)
463  for (size_type j=0; j<cols(); j++)
464  y[j] += conjugateComplex((*this)[i][j])*x[i];
465  }
466 
468  template<class X, class Y>
469  void mmv (const X& x, Y& y) const
470  {
471 #ifdef DUNE_FMatrix_WITH_CHECKING
472  if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
473  if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
474 #endif
475  for (size_type i=0; i<rows(); i++)
476  for (size_type j=0; j<cols(); j++)
477  y[i] -= (*this)[i][j] * x[j];
478  }
479 
481  template<class X, class Y>
482  void mmtv (const X& x, Y& y) const
483  {
484 #ifdef DUNE_FMatrix_WITH_CHECKING
485  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
486  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
487 #endif
488 
489  for (size_type i=0; i<rows(); i++)
490  for (size_type j=0; j<cols(); j++)
491  y[j] -= (*this)[i][j]*x[i];
492  }
493 
495  template<class X, class Y>
496  void mmhv (const X& x, Y& y) const
497  {
498 #ifdef DUNE_FMatrix_WITH_CHECKING
499  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
500  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
501 #endif
502 
503  for (size_type i=0; i<rows(); i++)
504  for (size_type j=0; j<cols(); j++)
505  y[j] -= conjugateComplex((*this)[i][j])*x[i];
506  }
507 
509  template<class X, class Y>
510  void usmv (const field_type& alpha, const X& x, Y& y) const
511  {
512 #ifdef DUNE_FMatrix_WITH_CHECKING
513  if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
514  if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
515 #endif
516  for (size_type i=0; i<rows(); i++)
517  for (size_type j=0; j<cols(); j++)
518  y[i] += alpha * (*this)[i][j] * x[j];
519  }
520 
522  template<class X, class Y>
523  void usmtv (const field_type& alpha, const X& x, Y& y) const
524  {
525 #ifdef DUNE_FMatrix_WITH_CHECKING
526  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
527  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
528 #endif
529 
530  for (size_type i=0; i<rows(); i++)
531  for (size_type j=0; j<cols(); j++)
532  y[j] += alpha*(*this)[i][j]*x[i];
533  }
534 
536  template<class X, class Y>
537  void usmhv (const field_type& alpha, const X& x, Y& y) const
538  {
539 #ifdef DUNE_FMatrix_WITH_CHECKING
540  if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
541  if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
542 #endif
543 
544  for (size_type i=0; i<rows(); i++)
545  for (size_type j=0; j<cols(); j++)
546  y[j] += alpha*conjugateComplex((*this)[i][j])*x[i];
547  }
548 
549  //===== norms
550 
552  typename FieldTraits<value_type>::real_type frobenius_norm () const
553  {
554  typename FieldTraits<value_type>::real_type sum=(0.0);
555  for (size_type i=0; i<rows(); ++i) sum += (*this)[i].two_norm2();
556  return fvmeta::sqrt(sum);
557  }
558 
560  typename FieldTraits<value_type>::real_type frobenius_norm2 () const
561  {
562  typename FieldTraits<value_type>::real_type sum=(0.0);
563  for (size_type i=0; i<rows(); ++i) sum += (*this)[i].two_norm2();
564  return sum;
565  }
566 
568  typename FieldTraits<value_type>::real_type infinity_norm () const
569  {
570  if (size() == 0)
571  return 0.0;
572 
573  ConstIterator it = begin();
574  typename remove_const< typename FieldTraits<value_type>::real_type >::type max = (*it).one_norm();
575  for (it = it + 1; it != end(); ++it)
576  max = std::max(max, (*it).one_norm());
577 
578  return max;
579  }
580 
582  typename FieldTraits<value_type>::real_type infinity_norm_real () const
583  {
584  if (size() == 0)
585  return 0.0;
586 
587  ConstIterator it = begin();
588  typename remove_const< typename FieldTraits<value_type>::real_type >::type max = (*it).one_norm_real();
589  for (it = it + 1; it != end(); ++it)
590  max = std::max(max, (*it).one_norm_real());
591 
592  return max;
593  }
594 
595  //===== solve
596 
601  template <class V>
602  void solve (V& x, const V& b) const;
603 
608  void invert();
609 
612 
614  template<typename M2>
616  {
617  assert(M.rows() == M.cols() && M.rows() == rows());
618  MAT C(asImp());
619 
620  for (size_type i=0; i<rows(); i++)
621  for (size_type j=0; j<cols(); j++) {
622  (*this)[i][j] = 0;
623  for (size_type k=0; k<rows(); k++)
624  (*this)[i][j] += M[i][k]*C[k][j];
625  }
626 
627  return asImp();
628  }
629 
631  template<typename M2>
633  {
634  assert(M.rows() == M.cols() && M.cols() == cols());
635  MAT C(asImp());
636 
637  for (size_type i=0; i<rows(); i++)
638  for (size_type j=0; j<cols(); j++) {
639  (*this)[i][j] = 0;
640  for (size_type k=0; k<cols(); k++)
641  (*this)[i][j] += C[i][k]*M[k][j];
642  }
643  return asImp();
644  }
645 
646 #if 0
648  template<int l>
649  DenseMatrix<K,l,cols> leftmultiplyany (const FieldMatrix<K,l,rows>& M) const
650  {
652 
653  for (size_type i=0; i<l; i++) {
654  for (size_type j=0; j<cols(); j++) {
655  C[i][j] = 0;
656  for (size_type k=0; k<rows(); k++)
657  C[i][j] += M[i][k]*(*this)[k][j];
658  }
659  }
660  return C;
661  }
662 
664  template<int l>
665  FieldMatrix<K,rows,l> rightmultiplyany (const FieldMatrix<K,cols,l>& M) const
666  {
667  FieldMatrix<K,rows,l> C;
668 
669  for (size_type i=0; i<rows(); i++) {
670  for (size_type j=0; j<l; j++) {
671  C[i][j] = 0;
672  for (size_type k=0; k<cols(); k++)
673  C[i][j] += (*this)[i][k]*M[k][j];
674  }
675  }
676  return C;
677  }
678 #endif
679 
680  //===== sizes
681 
683  size_type N () const
684  {
685  return rows();
686  }
687 
689  size_type M () const
690  {
691  return cols();
692  }
693 
695  size_type rows() const
696  {
697  return asImp().mat_rows();
698  }
699 
701  size_type cols() const
702  {
703  return asImp().mat_cols();
704  }
705 
706  //===== query
707 
709  bool exists (size_type i, size_type j) const
710  {
711 #ifdef DUNE_FMatrix_WITH_CHECKING
712  if (i<0 || i>=rows()) DUNE_THROW(FMatrixError,"row index out of range");
713  if (j<0 || j>=cols()) DUNE_THROW(FMatrixError,"column index out of range");
714 #else
717 #endif
718  return true;
719  }
720 
721  private:
722 
723 #ifndef DOXYGEN
724  struct ElimPivot
725  {
726  ElimPivot(std::vector<size_type> & pivot);
727 
728  void swap(int i, int j);
729 
730  template<typename T>
731  void operator()(const T&, int, int)
732  {}
733 
734  std::vector<size_type> & pivot_;
735  };
736 
737  template<typename V>
738  struct Elim
739  {
740  Elim(V& rhs);
741 
742  void swap(int i, int j);
743 
744  void operator()(const typename V::field_type& factor, int k, int i);
745 
746  V* rhs_;
747  };
748 
749  struct ElimDet
750  {
751  ElimDet(field_type& sign) : sign_(sign)
752  { sign_ = 1; }
753 
754  void swap(int, int)
755  { sign_ *= -1; }
756 
757  void operator()(const field_type&, int, int)
758  {}
759 
760  field_type& sign_;
761  };
762 #endif // DOXYGEN
763 
764  template<class Func>
765  void luDecomposition(DenseMatrix<MAT>& A, Func func) const;
766  };
767 
768 #ifndef DOXYGEN
769  template<typename MAT>
770  DenseMatrix<MAT>::ElimPivot::ElimPivot(std::vector<size_type> & pivot)
771  : pivot_(pivot)
772  {
773  typedef typename std::vector<size_type>::size_type size_type;
774  for(size_type i=0; i < pivot_.size(); ++i) pivot_[i]=i;
775  }
776 
777  template<typename MAT>
778  void DenseMatrix<MAT>::ElimPivot::swap(int i, int j)
779  {
780  pivot_[i]=j;
781  }
782 
783  template<typename MAT>
784  template<typename V>
785  DenseMatrix<MAT>::Elim<V>::Elim(V& rhs)
786  : rhs_(&rhs)
787  {}
788 
789  template<typename MAT>
790  template<typename V>
791  void DenseMatrix<MAT>::Elim<V>::swap(int i, int j)
792  {
793  std::swap((*rhs_)[i], (*rhs_)[j]);
794  }
795 
796  template<typename MAT>
797  template<typename V>
798  void DenseMatrix<MAT>::
799  Elim<V>::operator()(const typename V::field_type& factor, int k, int i)
800  {
801  (*rhs_)[k] -= factor*(*rhs_)[i];
802  }
803  template<typename MAT>
804  template<typename Func>
805  inline void DenseMatrix<MAT>::luDecomposition(DenseMatrix<MAT>& A, Func func) const
806  {
807  typedef typename FieldTraits<value_type>::real_type
808  real_type;
809  real_type norm = A.infinity_norm_real(); // for relative thresholds
812 
813  // LU decomposition of A in A
814  for (size_type i=0; i<rows(); i++) // loop over all rows
815  {
816  typename FieldTraits<value_type>::real_type pivmax=fvmeta::absreal(A[i][i]);
817 
818  // pivoting ?
819  if (pivmax<pivthres)
820  {
821  // compute maximum of column
822  size_type imax=i;
823  typename FieldTraits<value_type>::real_type abs(0.0);
824  for (size_type k=i+1; k<rows(); k++)
825  if ((abs=fvmeta::absreal(A[k][i]))>pivmax)
826  {
827  pivmax = abs; imax = k;
828  }
829  // swap rows
830  if (imax!=i) {
831  for (size_type j=0; j<rows(); j++)
832  std::swap(A[i][j],A[imax][j]);
833  func.swap(i, imax); // swap the pivot or rhs
834  }
835  }
836 
837  // singular ?
838  if (pivmax<singthres)
839  DUNE_THROW(FMatrixError,"matrix is singular");
840 
841  // eliminate
842  for (size_type k=i+1; k<rows(); k++)
843  {
844  field_type factor = A[k][i]/A[i][i];
845  A[k][i] = factor;
846  for (size_type j=i+1; j<rows(); j++)
847  A[k][j] -= factor*A[i][j];
848  func(factor, k, i);
849  }
850  }
851  }
852 
853  template<typename MAT>
854  template <class V>
855  inline void DenseMatrix<MAT>::solve(V& x, const V& b) const
856  {
857  // never mind those ifs, because they get optimized away
858  if (rows()!=cols())
859  DUNE_THROW(FMatrixError, "Can't solve for a " << rows() << "x" << cols() << " matrix!");
860 
861  if (rows()==1) {
862 
863 #ifdef DUNE_FMatrix_WITH_CHECKING
864  if (fvmeta::absreal((*this)[0][0])<FMatrixPrecision<>::absolute_limit())
865  DUNE_THROW(FMatrixError,"matrix is singular");
866 #endif
867  x[0] = b[0]/(*this)[0][0];
868 
869  }
870  else if (rows()==2) {
871 
872  field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
873 #ifdef DUNE_FMatrix_WITH_CHECKING
874  if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
875  DUNE_THROW(FMatrixError,"matrix is singular");
876 #endif
877  detinv = 1.0/detinv;
878 
879  x[0] = detinv*((*this)[1][1]*b[0]-(*this)[0][1]*b[1]);
880  x[1] = detinv*((*this)[0][0]*b[1]-(*this)[1][0]*b[0]);
881 
882  }
883  else if (rows()==3) {
884 
885  field_type d = determinant();
886 #ifdef DUNE_FMatrix_WITH_CHECKING
887  if (fvmeta::absreal(d)<FMatrixPrecision<>::absolute_limit())
888  DUNE_THROW(FMatrixError,"matrix is singular");
889 #endif
890 
891  x[0] = (b[0]*(*this)[1][1]*(*this)[2][2] - b[0]*(*this)[2][1]*(*this)[1][2]
892  - b[1] *(*this)[0][1]*(*this)[2][2] + b[1]*(*this)[2][1]*(*this)[0][2]
893  + b[2] *(*this)[0][1]*(*this)[1][2] - b[2]*(*this)[1][1]*(*this)[0][2]) / d;
894 
895  x[1] = ((*this)[0][0]*b[1]*(*this)[2][2] - (*this)[0][0]*b[2]*(*this)[1][2]
896  - (*this)[1][0] *b[0]*(*this)[2][2] + (*this)[1][0]*b[2]*(*this)[0][2]
897  + (*this)[2][0] *b[0]*(*this)[1][2] - (*this)[2][0]*b[1]*(*this)[0][2]) / d;
898 
899  x[2] = ((*this)[0][0]*(*this)[1][1]*b[2] - (*this)[0][0]*(*this)[2][1]*b[1]
900  - (*this)[1][0] *(*this)[0][1]*b[2] + (*this)[1][0]*(*this)[2][1]*b[0]
901  + (*this)[2][0] *(*this)[0][1]*b[1] - (*this)[2][0]*(*this)[1][1]*b[0]) / d;
902 
903  }
904  else {
905 
906  V& rhs = x; // use x to store rhs
907  rhs = b; // copy data
908  Elim<V> elim(rhs);
909  MAT A(asImp());
910 
911  luDecomposition(A, elim);
912 
913  // backsolve
914  for(int i=rows()-1; i>=0; i--) {
915  for (size_type j=i+1; j<rows(); j++)
916  rhs[i] -= A[i][j]*x[j];
917  x[i] = rhs[i]/A[i][i];
918  }
919  }
920  }
921 
922  template<typename MAT>
923  inline void DenseMatrix<MAT>::invert()
924  {
925  // never mind those ifs, because they get optimized away
926  if (rows()!=cols())
927  DUNE_THROW(FMatrixError, "Can't invert a " << rows() << "x" << cols() << " matrix!");
928 
929  if (rows()==1) {
930 
931 #ifdef DUNE_FMatrix_WITH_CHECKING
932  if (fvmeta::absreal((*this)[0][0])<FMatrixPrecision<>::absolute_limit())
933  DUNE_THROW(FMatrixError,"matrix is singular");
934 #endif
935  (*this)[0][0] = field_type( 1 ) / (*this)[0][0];
936 
937  }
938  else if (rows()==2) {
939 
940  field_type detinv = (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0];
941 #ifdef DUNE_FMatrix_WITH_CHECKING
942  if (fvmeta::absreal(detinv)<FMatrixPrecision<>::absolute_limit())
943  DUNE_THROW(FMatrixError,"matrix is singular");
944 #endif
945  detinv = field_type( 1 ) / detinv;
946 
947  field_type temp=(*this)[0][0];
948  (*this)[0][0] = (*this)[1][1]*detinv;
949  (*this)[0][1] = -(*this)[0][1]*detinv;
950  (*this)[1][0] = -(*this)[1][0]*detinv;
951  (*this)[1][1] = temp*detinv;
952 
953  }
954  else {
955 
956  MAT A(asImp());
957  std::vector<size_type> pivot(rows());
958  luDecomposition(A, ElimPivot(pivot));
959  DenseMatrix<MAT>& L=A;
960  DenseMatrix<MAT>& U=A;
961 
962  // initialize inverse
963  *this=field_type();
964 
965  for(size_type i=0; i<rows(); ++i)
966  (*this)[i][i]=1;
967 
968  // L Y = I; multiple right hand sides
969  for (size_type i=0; i<rows(); i++)
970  for (size_type j=0; j<i; j++)
971  for (size_type k=0; k<rows(); k++)
972  (*this)[i][k] -= L[i][j]*(*this)[j][k];
973 
974  // U A^{-1} = Y
975  for (size_type i=rows(); i>0;) {
976  --i;
977  for (size_type k=0; k<rows(); k++) {
978  for (size_type j=i+1; j<rows(); j++)
979  (*this)[i][k] -= U[i][j]*(*this)[j][k];
980  (*this)[i][k] /= U[i][i];
981  }
982  }
983 
984  for(size_type i=rows(); i>0; ) {
985  --i;
986  if(i!=pivot[i])
987  for(size_type j=0; j<rows(); ++j)
988  std::swap((*this)[j][pivot[i]], (*this)[j][i]);
989  }
990  }
991  }
992 
993  // implementation of the determinant
994  template<typename MAT>
995  inline typename DenseMatrix<MAT>::field_type
997  {
998  // never mind those ifs, because they get optimized away
999  if (rows()!=cols())
1000  DUNE_THROW(FMatrixError, "There is no determinant for a " << rows() << "x" << cols() << " matrix!");
1001 
1002  if (rows()==1)
1003  return (*this)[0][0];
1004 
1005  if (rows()==2)
1006  return (*this)[0][0]*(*this)[1][1] - (*this)[0][1]*(*this)[1][0];
1007 
1008  if (rows()==3) {
1009  // code generated by maple
1010  field_type t4 = (*this)[0][0] * (*this)[1][1];
1011  field_type t6 = (*this)[0][0] * (*this)[1][2];
1012  field_type t8 = (*this)[0][1] * (*this)[1][0];
1013  field_type t10 = (*this)[0][2] * (*this)[1][0];
1014  field_type t12 = (*this)[0][1] * (*this)[2][0];
1015  field_type t14 = (*this)[0][2] * (*this)[2][0];
1016 
1017  return (t4*(*this)[2][2]-t6*(*this)[2][1]-t8*(*this)[2][2]+
1018  t10*(*this)[2][1]+t12*(*this)[1][2]-t14*(*this)[1][1]);
1019 
1020  }
1021 
1022  MAT A(asImp());
1023  field_type det;
1024  try
1025  {
1026  luDecomposition(A, ElimDet(det));
1027  }
1028  catch (FMatrixError&)
1029  {
1030  return 0;
1031  }
1032  for (size_type i = 0; i < rows(); ++i)
1033  det *= A[i][i];
1034  return det;
1035  }
1036 
1037 #endif // DOXYGEN
1038 
1039  namespace DenseMatrixHelp {
1040 #if 0
1042  template <typename K>
1043  static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
1044  {
1045  inverse[0][0] = 1.0/matrix[0][0];
1046  return matrix[0][0];
1047  }
1048 
1050  template <typename K>
1051  static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
1052  {
1053  return invertMatrix(matrix,inverse);
1054  }
1055 
1056 
1058  template <typename K>
1059  static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
1060  {
1061  // code generated by maple
1062  field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
1063  field_type det_1 = 1.0/det;
1064  inverse[0][0] = matrix[1][1] * det_1;
1065  inverse[0][1] = - matrix[0][1] * det_1;
1066  inverse[1][0] = - matrix[1][0] * det_1;
1067  inverse[1][1] = matrix[0][0] * det_1;
1068  return det;
1069  }
1070 
1073  template <typename K>
1074  static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
1075  {
1076  // code generated by maple
1077  field_type det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
1078  field_type det_1 = 1.0/det;
1079  inverse[0][0] = matrix[1][1] * det_1;
1080  inverse[1][0] = - matrix[0][1] * det_1;
1081  inverse[0][1] = - matrix[1][0] * det_1;
1082  inverse[1][1] = matrix[0][0] * det_1;
1083  return det;
1084  }
1085 
1087  template <typename K>
1088  static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
1089  {
1090  // code generated by maple
1091  field_type t4 = matrix[0][0] * matrix[1][1];
1092  field_type t6 = matrix[0][0] * matrix[1][2];
1093  field_type t8 = matrix[0][1] * matrix[1][0];
1094  field_type t10 = matrix[0][2] * matrix[1][0];
1095  field_type t12 = matrix[0][1] * matrix[2][0];
1096  field_type t14 = matrix[0][2] * matrix[2][0];
1097 
1098  field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
1099  t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
1100  field_type t17 = 1.0/det;
1101 
1102  inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
1103  inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
1104  inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
1105  inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
1106  inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
1107  inverse[1][2] = -(t6-t10) * t17;
1108  inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
1109  inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
1110  inverse[2][2] = (t4-t8) * t17;
1111 
1112  return det;
1113  }
1114 
1116  template <typename K>
1117  static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
1118  {
1119  // code generated by maple
1120  field_type t4 = matrix[0][0] * matrix[1][1];
1121  field_type t6 = matrix[0][0] * matrix[1][2];
1122  field_type t8 = matrix[0][1] * matrix[1][0];
1123  field_type t10 = matrix[0][2] * matrix[1][0];
1124  field_type t12 = matrix[0][1] * matrix[2][0];
1125  field_type t14 = matrix[0][2] * matrix[2][0];
1126 
1127  field_type det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
1128  t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
1129  field_type t17 = 1.0/det;
1130 
1131  inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
1132  inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
1133  inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
1134  inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
1135  inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
1136  inverse[2][1] = -(t6-t10) * t17;
1137  inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
1138  inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
1139  inverse[2][2] = (t4-t8) * t17;
1140 
1141  return det;
1142  }
1143 
1145  template< class K, int m, int n, int p >
1146  static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
1147  const FieldMatrix< K, n, p > &B,
1148  FieldMatrix< K, m, p > &ret )
1149  {
1150  typedef typename FieldMatrix< K, m, p > :: size_type size_type;
1151 
1152  for( size_type i = 0; i < m; ++i )
1153  {
1154  for( size_type j = 0; j < p; ++j )
1155  {
1156  ret[ i ][ j ] = K( 0 );
1157  for( size_type k = 0; k < n; ++k )
1158  ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
1159  }
1160  }
1161  }
1162 
1164  template <typename K, int rows, int cols>
1165  static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
1166  {
1167  typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
1168 
1169  for(size_type i=0; i<cols(); i++)
1170  for(size_type j=0; j<cols(); j++)
1171  {
1172  ret[i][j]=0.0;
1173  for(size_type k=0; k<rows(); k++)
1174  ret[i][j]+=matrix[k][i]*matrix[k][j];
1175  }
1176  }
1177 #endif
1178 
1180  template <typename MAT, typename V1, typename V2>
1181  static inline void multAssign(const DenseMatrix<MAT> &matrix, const DenseVector<V1> & x, DenseVector<V2> & ret)
1182  {
1183  assert(x.size() == matrix.cols());
1184  assert(ret.size() == matrix.rows());
1185  typedef typename DenseMatrix<MAT>::size_type size_type;
1186 
1187  for(size_type i=0; i<matrix.rows(); ++i)
1188  {
1189  ret[i] = 0.0;
1190  for(size_type j=0; j<matrix.cols(); ++j)
1191  {
1192  ret[i] += matrix[i][j]*x[j];
1193  }
1194  }
1195  }
1196 
1197 #if 0
1199  template <typename K, int rows, int cols>
1200  static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
1201  {
1202  typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
1203 
1204  for(size_type i=0; i<cols(); ++i)
1205  {
1206  ret[i] = 0.0;
1207  for(size_type j=0; j<rows(); ++j)
1208  ret[i] += matrix[j][i]*x[j];
1209  }
1210  }
1211 
1213  template <typename K, int rows, int cols>
1214  static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x)
1215  {
1216  FieldVector<K,rows> ret;
1217  multAssign(matrix,x,ret);
1218  return ret;
1219  }
1220 
1222  template <typename K, int rows, int cols>
1223  static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
1224  {
1225  FieldVector<K,cols> ret;
1226  multAssignTransposed( matrix, x, ret );
1227  return ret;
1228  }
1229 #endif
1230 
1231  } // end namespace DenseMatrixHelp
1232 
1234  template<typename MAT>
1235  std::ostream& operator<< (std::ostream& s, const DenseMatrix<MAT>& a)
1236  {
1237  for (typename DenseMatrix<MAT>::size_type i=0; i<a.rows(); i++)
1238  s << a[i] << std::endl;
1239  return s;
1240  }
1241 
1244 } // end namespace Dune
1245 
1246 #endif
Checks wether a type is convertible to another.
Definition: typetraits.hh:177
@ exists
True if the conversion exists.
Definition: typetraits.hh:187
Generic iterator class for dense vector and matrix implementations.
Definition: densevector.hh:127
A dense n x m matrix.
Definition: densematrix.hh:185
ConstIterator const_iterator
typedef for stl compliant access
Definition: densematrix.hh:283
void usmtv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^T x
Definition: densematrix.hh:523
bool operator!=(const DenseMatrix< Other > &y) const
Binary matrix incomparison.
Definition: densematrix.hh:380
void mv(const X &x, Y &y) const
y = A x
Definition: densematrix.hh:390
Traits::value_type field_type
export the type representing the field
Definition: densematrix.hh:202
void solve(V &x, const V &b) const
Solve system A x = b.
size_type cols() const
number of columns
Definition: densematrix.hh:701
ConstIterator beforeEnd() const
Definition: densematrix.hh:303
bool operator==(const DenseMatrix< Other > &y) const
Binary matrix comparison.
Definition: densematrix.hh:371
void mmtv(const X &x, Y &y) const
y -= A^T x
Definition: densematrix.hh:482
ConstIterator beforeBegin() const
Definition: densematrix.hh:310
Traits::value_type block_type
export the type representing the components
Definition: densematrix.hh:205
FieldTraits< value_type >::real_type infinity_norm_real() const
simplified infinity norm (uses Manhattan norm for complex values)
Definition: densematrix.hh:582
DenseMatrix & operator+=(const DenseMatrix< Other > &y)
vector space addition
Definition: densematrix.hh:328
void mtv(const X &x, Y &y) const
y = A^T x
Definition: densematrix.hh:407
FieldTraits< value_type >::real_type frobenius_norm2() const
square of frobenius norm, need for block recursion
Definition: densematrix.hh:560
remove_reference< const_row_reference >::type::ConstIterator ConstColIterator
rename the iterators for easier access
Definition: densematrix.hh:287
MAT & rightmultiply(const DenseMatrix< M2 > &M)
Multiplies M from the right to this matrix.
Definition: densematrix.hh:632
void usmhv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^H x
Definition: densematrix.hh:537
size_type size() const
size method (number of rows)
Definition: densematrix.hh:239
size_type M() const
number of columns
Definition: densematrix.hh:689
remove_reference< row_reference >::type::Iterator ColIterator
rename the iterators for easier access
Definition: densematrix.hh:252
void usmv(const field_type &alpha, const X &x, Y &y) const
y += alpha A x
Definition: densematrix.hh:510
Iterator end()
end iterator
Definition: densematrix.hh:261
Iterator beforeBegin()
Definition: densematrix.hh:275
DenseMatrix & operator-=(const DenseMatrix< Other > &y)
vector space subtraction
Definition: densematrix.hh:337
Iterator beforeEnd()
Definition: densematrix.hh:268
Traits::value_type value_type
export the type representing the field
Definition: densematrix.hh:199
@ blocklevel
The number of block levels we contain. This is 1.
Definition: densematrix.hh:222
size_type rows() const
number of rows
Definition: densematrix.hh:695
void mmv(const X &x, Y &y) const
y -= A x
Definition: densematrix.hh:469
DenseMatrix & axpy(const field_type &k, const DenseMatrix< Other > &y)
vector space axpy operation (*this += k y)
Definition: densematrix.hh:362
void invert()
Compute inverse.
FieldTraits< value_type >::real_type frobenius_norm() const
frobenius norm: sqrt(sum over squared values of entries)
Definition: densematrix.hh:552
DenseMatrix & operator*=(const field_type &k)
vector space multiplication with scalar
Definition: densematrix.hh:345
void mmhv(const X &x, Y &y) const
y -= A^H x
Definition: densematrix.hh:496
Traits::derived_type derived_type
type of derived matrix class
Definition: densematrix.hh:196
row_reference operator[](size_type i)
random access
Definition: densematrix.hh:228
bool exists(size_type i, size_type j) const
return true when (i,j) is in pattern
Definition: densematrix.hh:709
Iterator RowIterator
rename the iterators for easier access
Definition: densematrix.hh:250
void umv(const X &x, Y &y) const
y += A x
Definition: densematrix.hh:426
DenseIterator< const DenseMatrix, const row_type, const_row_reference > ConstIterator
Iterator class for sequential access.
Definition: densematrix.hh:281
size_type N() const
number of rows
Definition: densematrix.hh:683
Traits::row_type row_type
The type used to represent a row (must fulfill the Dune::DenseVector interface)
Definition: densematrix.hh:211
DenseMatrix & operator/=(const field_type &k)
vector space division by scalar
Definition: densematrix.hh:353
Traits::size_type size_type
The type used for the index access and size operation.
Definition: densematrix.hh:208
Traits::const_row_reference const_row_reference
The type used to represent a reference to a constant row (usually const row_type &)
Definition: densematrix.hh:217
Traits::row_reference row_reference
The type used to represent a reference to a row (usually row_type &)
Definition: densematrix.hh:214
MAT & leftmultiply(const DenseMatrix< M2 > &M)
Multiplies M from the left to this matrix.
Definition: densematrix.hh:615
Iterator iterator
typedef for stl compliant access
Definition: densematrix.hh:248
ConstIterator ConstRowIterator
rename the iterators for easier access
Definition: densematrix.hh:285
field_type determinant() const
calculates the determinant of this matrix
DenseIterator< DenseMatrix, row_type, row_reference > Iterator
Iterator class for sequential access.
Definition: densematrix.hh:246
void umtv(const X &x, Y &y) const
y += A^T x
Definition: densematrix.hh:441
ConstIterator begin() const
begin iterator
Definition: densematrix.hh:290
Iterator begin()
begin iterator
Definition: densematrix.hh:255
void umhv(const X &x, Y &y) const
y += A^H x
Definition: densematrix.hh:455
FieldTraits< value_type >::real_type infinity_norm() const
infinity norm (row sum norm, how to generalize for blocks?)
Definition: densematrix.hh:568
ConstIterator end() const
end iterator
Definition: densematrix.hh:296
Interface for a class of dense vectors over a given field.
Definition: densevector.hh:234
size_type size() const
size method
Definition: densevector.hh:296
size_type N() const
number of blocks in the vector (are of size 1 here)
Definition: densevector.hh:643
Error thrown if operations of a FieldMatrix fail.
Definition: densematrix.hh:171
static ctype pivoting_limit()
return threshold to do pivoting
Definition: precision.hh:26
static ctype absolute_limit()
return threshold to declare matrix singular
Definition: precision.hh:50
static ctype singular_limit()
return threshold to declare matrix singular
Definition: precision.hh:38
A dense n x m matrix.
Definition: fmatrix.hh:67
vector space out of a tensor product of fields.
Definition: fvector.hh:94
FieldVector()
Constructor making default-initialized vector.
Definition: fvector.hh:108
Default exception class for mathematical errors.
Definition: exceptions.hh:266
FieldTraits< field_type >::real_type infinity_norm_real() const
simplified infinity norm (uses Manhattan norm for complex values)
Definition: matrix.hh:518
A free function to provide the demangled class name of a given object or type as a string.
static void multAssign(const DenseMatrix< MAT > &matrix, const DenseVector< V1 > &x, DenseVector< V2 > &ret)
calculates ret = matrix * x
Definition: densematrix.hh:1181
A few common exception classes.
Implements a vector constructed from a given type representing a field and a compile-time given size.
std::ostream & operator<<(std::ostream &s, const array< T, N > &e)
Output operator for array.
Definition: array.hh:26
#define DUNE_THROW(E, m)
Definition: exceptions.hh:243
Some useful basic math stuff.
Dune namespace.
Definition: alignment.hh:10
int sign(const T &val)
Return the sign of the value.
Definition: math.hh:119
K conjugateComplex(const K &x)
compute conjugate complex of x
Definition: math.hh:103
Various precision settings for calculations with FieldMatrix and FieldVector.
you have to specialize this structure for any type that should be assignable to a DenseMatrix
Definition: densematrix.hh:71
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentional unused function parameters with.
Definition: unused.hh:18
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 15, 22:30, 2024)