diagonalmatrix.hh

Go to the documentation of this file.
00001 #ifndef DUNE_DIAGONAL_MATRIX_HH
00002 #define DUNE_DIAGONAL_MATRIX_HH
00003 
00008 #include<cmath>
00009 #include<cstddef>
00010 #include<complex>
00011 #include<iostream>
00012 #include <dune/common/exceptions.hh>
00013 #include <dune/common/fmatrix.hh>
00014 #include <dune/common/fvector.hh>
00015 #include <dune/common/genericiterator.hh>
00016 
00017 
00018 
00019 namespace Dune {
00020 
00021 template< class K, int n > class DiagonalRowVectorConst;
00022 template< class K, int n > class DiagonalRowVector;
00023 template< class C, class T, class R, class S> class ReferenceStorageIterator;
00024 
00025 
00029 template<class K, int n>
00030 class DiagonalMatrix
00031 {
00032 
00033     public:
00034     //===== type definitions and constants
00035 
00037     typedef K field_type;
00038 
00040     typedef K block_type;
00041 
00043     typedef std::size_t size_type;
00044 
00046     enum {
00048         blocklevel = 1
00049     };
00050 
00052     typedef DiagonalRowVector<K,n> row_type;
00053     typedef row_type reference;
00054     typedef DiagonalRowVectorConst<K,n> const_row_type;
00055     typedef const_row_type const_reference;
00056 
00058     enum {
00060         rows = n,
00062         cols = n
00063     };
00064 
00065 
00066 
00067     //===== constructors
00068 
00070     DiagonalMatrix () {}
00071 
00073     DiagonalMatrix (const K& k)
00074         : diag_(k)
00075     {}
00076 
00078     DiagonalMatrix (const FieldVector<K,n>& diag)
00079         : diag_(diag)
00080     {}
00081 
00082 
00083     //===== assignment from scalar
00084     DiagonalMatrix& operator= (const K& k)
00085     {
00086         diag_ = k;
00087         return *this;
00088     }
00089 
00090     // check if matrix is identical to other matrix (not only identical values)
00091     bool identical(const DiagonalMatrix<K,n>& other) const
00092     {
00093         return (this==&other);
00094     }
00095 
00096     //===== iterator interface to rows of the matrix
00098     typedef ReferenceStorageIterator<DiagonalMatrix<K,n>,reference,reference,DiagonalMatrix<K,n>&> Iterator;
00100     typedef Iterator iterator;
00102     typedef Iterator RowIterator;
00104     typedef typename row_type::Iterator ColIterator;
00105 
00107     Iterator begin ()
00108     {
00109         return Iterator(*this,0);
00110     }
00111 
00113     Iterator end ()
00114     {
00115         return Iterator(*this,n);
00116     }
00117 
00119     Iterator rbegin ()
00120     {
00121         return Iterator(*this,n-1);
00122     }
00123 
00125     Iterator rend ()
00126     {
00127         return Iterator(*this,-1);
00128     }
00129 
00130 
00132     typedef ReferenceStorageIterator<const DiagonalMatrix<K,n>,const_reference,const_reference,const DiagonalMatrix<K,n>&> ConstIterator;
00134     typedef ConstIterator const_iterator;
00136     typedef ConstIterator ConstRowIterator;
00138     typedef typename const_row_type::ConstIterator ConstColIterator;
00139 
00141     ConstIterator begin () const
00142     {
00143         return ConstIterator(*this,0);
00144     }
00145 
00147     ConstIterator end () const
00148     {
00149         return ConstIterator(*this,n);
00150     }
00151 
00153     ConstIterator rbegin () const
00154     {
00155         return ConstIterator(*this,n-1);
00156     }
00157 
00159     ConstIterator rend () const
00160     {
00161         return ConstIterator(*this,-1);
00162     }
00163 
00164 
00165 
00166     //===== vector space arithmetic
00167 
00169     DiagonalMatrix& operator+= (const DiagonalMatrix& y)
00170     {
00171         diag_ += y.diag_;
00172         return *this;
00173     }
00174 
00176     DiagonalMatrix& operator-= (const DiagonalMatrix& y)
00177     {
00178         diag_ -= y.diag_;
00179         return *this;
00180     }
00181 
00183     DiagonalMatrix& operator+= (const K& k)
00184     {
00185         diag_ += k;
00186         return *this;
00187     }
00188 
00190     DiagonalMatrix& operator-= (const K& k)
00191     {
00192         diag_ -= k;
00193         return *this;
00194     }
00195 
00197     DiagonalMatrix& operator*= (const K& k)
00198     {
00199         diag_ *= k;
00200         return *this;
00201     }
00202 
00204     DiagonalMatrix& operator/= (const K& k)
00205     {
00206         diag_ /= k;
00207         return *this;
00208     }
00209 
00210 
00211 
00212     //===== linear maps
00213 
00215     template<class X, class Y>
00216     void mv (const X& x, Y& y) const
00217     {
00218 #ifdef DUNE_FMatrix_WITH_CHECKING
00219         if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00220         if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00221 #endif
00222         for (size_type i=0; i<n; ++i)
00223             y[i] = diag_[i] * x[i];
00224     }
00225 
00227     template<class X, class Y>
00228     void umv (const X& x, Y& y) const
00229     {
00230 #ifdef DUNE_FMatrix_WITH_CHECKING
00231         if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00232         if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00233 #endif
00234         for (size_type i=0; i<n; ++i)
00235             y[i] += diag_[i] * x[i];
00236     }
00237 
00239     template<class X, class Y>
00240     void umtv (const X& x, Y& y) const
00241     {
00242 #ifdef DUNE_FMatrix_WITH_CHECKING
00243         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00244         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00245 #endif
00246         for (size_type i=0; i<n; ++i)
00247             y[i] += diag_[i] * x[i];
00248     }
00249 
00251     template<class X, class Y>
00252     void umhv (const X& x, Y& y) const
00253     {
00254 #ifdef DUNE_FMatrix_WITH_CHECKING
00255         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00256         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00257 #endif
00258         for (size_type i=0; i<n; i++)
00259             y[i] += fm_ck(diag_[i])*x[i];
00260     }
00261 
00263     template<class X, class Y>
00264     void mmv (const X& x, Y& y) const
00265     {
00266 #ifdef DUNE_FMatrix_WITH_CHECKING
00267         if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00268         if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00269 #endif
00270         for (size_type i=0; i<n; ++i)
00271             y[i] -= diag_[i] * x[i];
00272     }
00273 
00275     template<class X, class Y>
00276     void mmtv (const X& x, Y& y) const
00277     {
00278 #ifdef DUNE_FMatrix_WITH_CHECKING
00279         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00280         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00281 #endif
00282         for (size_type i=0; i<n; ++i)
00283             y[i] -= diag_[i] * x[i];
00284     }
00285 
00287     template<class X, class Y>
00288     void mmhv (const X& x, Y& y) const
00289     {
00290 #ifdef DUNE_FMatrix_WITH_CHECKING
00291         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00292         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00293 #endif
00294 
00295         for (size_type i=0; i<n; i++)
00296             y[i] -= fm_ck(diag_[i])*x[i];
00297     }
00298 
00300     template<class X, class Y>
00301     void usmv (const K& alpha, const X& x, Y& y) const
00302     {
00303 #ifdef DUNE_FMatrix_WITH_CHECKING
00304         if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00305         if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00306 #endif
00307         for (size_type i=0; i<n; i++)
00308             y[i] += alpha * diag_[i] * x[i];
00309     }
00310 
00312     template<class X, class Y>
00313     void usmtv (const K& alpha, const X& x, Y& y) const
00314     {
00315 #ifdef DUNE_FMatrix_WITH_CHECKING
00316         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00317         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00318 #endif
00319         for (size_type i=0; i<n; i++)
00320             y[i] += alpha * diag_[i] * x[i];
00321     }
00322 
00324     template<class X, class Y>
00325     void usmhv (const K& alpha, const X& x, Y& y) const
00326     {
00327 #ifdef DUNE_FMatrix_WITH_CHECKING
00328         if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00329         if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00330 #endif
00331         for (size_type i=0; i<n; i++)
00332             y[i] += alpha * fm_ck(diag_[i]) * x[i];
00333     }
00334 
00335     //===== norms
00336 
00338     double frobenius_norm () const
00339     {
00340         return diag_.two_norm();
00341     }
00342 
00344     double frobenius_norm2 () const
00345     {
00346         return diag_.two_norm2();
00347     }
00348 
00350     double infinity_norm () const
00351     {
00352         return diag_.infinity_norm();
00353     }
00354 
00356     double infinity_norm_real () const
00357     {
00358         return diag_.infinity_norm_real();
00359     }
00360 
00361 
00362 
00363     //===== solve
00364 
00366     template<class V>
00367     void solve (V& x, const V& b) const
00368     {
00369         for (int i=0; i<n; i++)
00370             x[i] = b[i]/diag_[i];
00371     }
00372 
00374     void invert()
00375     {
00376         for (int i=0; i<n; i++)
00377             diag_[i] = 1/diag_[i];
00378     }
00379 
00381     K determinant () const
00382     {
00383         K det = diag_[0];
00384         for (int i=1; i<n; i++)
00385             det *= diag_[i];
00386         return det;
00387     }
00388 
00389 
00390 
00391     //===== sizes
00392 
00394     size_type N () const
00395     {
00396         return n;
00397     }
00398 
00400     size_type M () const
00401     {
00402         return n;
00403     }
00404 
00405 
00406 
00407     //===== query
00408 
00410     bool exists (size_type i, size_type j) const
00411     {
00412 #ifdef DUNE_FMatrix_WITH_CHECKING
00413         if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00414         if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00415 #endif
00416         return i==j;
00417     }
00418 
00419 
00420 
00422     friend std::ostream& operator<< (std::ostream& s, const DiagonalMatrix<K,n>& a)
00423     {
00424         for (size_type i=0; i<n; i++) {
00425             for (size_type j=0; j<n; j++)
00426                 s << ((i==j) ? a.diag_[i] : 0) << " ";
00427             s << std::endl;
00428         }
00429         return s;
00430     }
00431 
00433     reference operator[](size_type i)
00434     {
00435         return reference(const_cast<K*>(&diag_[i]), i);
00436     }
00437 
00439     const_reference operator[](size_type i) const
00440     {
00441         return const_reference(const_cast<K*>(&diag_[i]), i);
00442     }
00443 
00445     const K& diagonal(size_type i) const
00446     {
00447         return diag_[i];
00448     }
00449 
00451     K& diagonal(size_type i)
00452     {
00453         return diag_[i];
00454     }
00455 
00457     const FieldVector<K,n>& diagonal() const
00458     {
00459         return diag_;
00460     }
00461 
00463     FieldVector<K,n>& diagonal()
00464     {
00465         return diag_;
00466     }
00467 
00468     private:
00469 
00470     // the data, a FieldVector storing the diagonal
00471     FieldVector<K,n> diag_;
00472 };
00473 
00474 
00478 template< class K, int n >
00479 class DiagonalRowVectorConst
00480 {
00481 public:
00482     // remember size of vector 
00483     enum { dimension = n };
00484 
00485     // standard constructor and everything is sufficient ...
00486 
00487     //===== type definitions and constants
00488 
00490     typedef K field_type;
00491 
00493     typedef K block_type;
00494 
00496     typedef std::size_t size_type;
00497 
00499     enum {
00501         blocklevel = 1
00502     };
00503 
00505     enum {
00507         size = n
00508     };
00509 
00511     DiagonalRowVectorConst() :
00512         p_(0),
00513         row_(0)
00514     {}
00515 
00517     explicit DiagonalRowVectorConst (K* p, int col) :
00518         p_(p),
00519         row_(col)
00520     {}
00521 
00522     //===== access to components
00523 
00525     const K& operator[] (size_type i) const
00526     {
00527         if (i!=row_)
00528             DUNE_THROW(FMatrixError,"index is read only");
00529 //            return ZERO<K>::Value;
00530         return *p_;
00531     }
00532 
00533     // check if row is identical to other row (not only identical values)
00534     // since this is a proxy class we need to check equality of the stored pointer
00535     bool identical(const DiagonalRowVectorConst<K,n>& other) const
00536     {
00537         return ((p_ == other.p_) and (row_ == other.row_));
00538     }
00539 
00541     typedef ReferenceStorageIterator<DiagonalRowVectorConst<K,n>,const K,const K&,DiagonalRowVectorConst<K,n> > ConstIterator;
00543     typedef ConstIterator const_iterator;
00544 
00546     ConstIterator begin () const
00547     {
00548         // the iterator gets this type as '[...]Const' and not as 'const [...]'
00549         // thus we must remove constness
00550         return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
00551     }
00552 
00554     ConstIterator end () const
00555     {
00556         // the iterator gets this type as '[...]Const' and not as 'const [...]'
00557         // thus we must remove constness
00558         return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_+1);
00559     }
00560 
00562     ConstIterator rbegin () const
00563     {
00564         // the iterator gets this type as '[...]Const' and not as 'const [...]'
00565         // thus we must remove constness
00566         return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
00567     }
00568 
00570     ConstIterator rend () const
00571     {
00572         // the iterator gets this type as '[...]Const' and not as 'const [...]'
00573         // thus we must remove constness
00574         return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),-1);
00575     }
00576 
00578 //    ConstIterator find (size_type i) const
00579 //    {
00580 //        if (i<n)
00581 //            return ConstIterator(*this,i);
00582 //        else
00583 //            return ConstIterator(*this,n);
00584 //    }
00585 
00587     bool operator== (const DiagonalRowVectorConst& y) const
00588     {
00589         return ((p_==y.p_) and (row_==y.row_));
00590     }
00591 
00592     //===== sizes
00593 
00595     size_type N () const
00596     {
00597         return n;
00598     }
00599 
00601     size_type dim () const
00602     {
00603         return n;
00604     }
00605 
00607     size_type rowIndex() const
00608     {
00609         return row_;
00610     }
00611 
00613     const K& diagonal() const
00614     {
00615         return *p_;
00616     }
00617 
00618 protected:
00619     // the data, very simply a pointer to the diagonal value and the row number
00620     K* p_;
00621     size_type row_;
00622 
00623     void operator & ();
00624 };
00625 
00626 template< class K, int n >
00627 class DiagonalRowVector : public DiagonalRowVectorConst<K,n>
00628 {
00629 public:
00630     // standard constructor and everything is sufficient ...
00631 
00632     //===== type definitions and constants
00633 
00635     typedef K field_type;
00636 
00638     typedef K block_type;
00639 
00641     typedef std::size_t size_type;
00642 
00644     DiagonalRowVector() : DiagonalRowVectorConst<K,n>()
00645     {}
00646 
00648     explicit DiagonalRowVector (K* p, int col) : DiagonalRowVectorConst<K,n>(p, col)
00649     {}
00650 
00651     //===== assignment from scalar
00653     DiagonalRowVector& operator= (const K& k)
00654     {
00655         *p_ = k;
00656         return *this;
00657     }
00658 
00659     //===== access to components
00660 
00662     K& operator[] (size_type i)
00663     {
00664         if (i!=row_)
00665             DUNE_THROW(FMatrixError,"index is read only");
00666 //            return ZERO<K>::Value;
00667         return *p_;
00668     }
00669 
00671     typedef ReferenceStorageIterator<DiagonalRowVector<K,n>,K,K&,DiagonalRowVector<K,n> > Iterator;
00673     typedef Iterator iterator;
00674 
00676     Iterator begin ()
00677     {
00678         return Iterator(*this,row_);
00679     }
00680 
00682     Iterator end ()
00683     {
00684         return Iterator(*this,row_+1);
00685     }
00686 
00688     Iterator rbegin ()
00689     {
00690         return Iterator(*this,row_);
00691     }
00692 
00694     Iterator rend ()
00695     {
00696         return Iterator(*this,row_-1);
00697     }
00698 
00700 //    Iterator find (size_type i)
00701 //    {
00702 //        if (i<n)
00703 //            return Iterator(*this,i);
00704 //        else
00705 //            return Iterator(*this,n);
00706 //    }
00707 
00709     typedef ReferenceStorageIterator<DiagonalRowVectorConst<K,n>,const K,const K&,DiagonalRowVectorConst<K,n> > ConstIterator;
00711     typedef ConstIterator const_iterator;
00712 
00713     using DiagonalRowVectorConst<K,n>::identical;
00714     using DiagonalRowVectorConst<K,n>::operator[];
00715     using DiagonalRowVectorConst<K,n>::operator==;
00716     using DiagonalRowVectorConst<K,n>::begin;
00717     using DiagonalRowVectorConst<K,n>::end;
00718     using DiagonalRowVectorConst<K,n>::rbegin;
00719     using DiagonalRowVectorConst<K,n>::rend;
00720     using DiagonalRowVectorConst<K,n>::N;
00721     using DiagonalRowVectorConst<K,n>::dim;
00722     using DiagonalRowVectorConst<K,n>::rowIndex;
00723     using DiagonalRowVectorConst<K,n>::diagonal;
00724 
00725 private:
00726     using DiagonalRowVectorConst<K,n>::p_;
00727     using DiagonalRowVectorConst<K,n>::row_;
00728 
00729     void operator & ();
00730 };
00731 
00732 
00733 // implement type traits
00734 template<class K, int n>
00735 struct const_reference< DiagonalRowVector<K,n> >
00736 {
00737     typedef DiagonalRowVectorConst<K,n> type;
00738 };
00739 
00740 template<class K, int n>
00741 struct const_reference< DiagonalRowVectorConst<K,n> >
00742 {
00743     typedef DiagonalRowVectorConst<K,n> type;
00744 };
00745 
00746 template<class K, int n>
00747 struct mutable_reference< DiagonalRowVector<K,n> >
00748 {
00749     typedef DiagonalRowVector<K,n> type;
00750 };
00751 
00752 template<class K, int n>
00753 struct mutable_reference< DiagonalRowVectorConst<K,n> >
00754 {
00755     typedef DiagonalRowVector<K,n> type;
00756 };
00757 
00758 
00759 template<class C, class T, class R, class S>
00760 class ReferenceStorageIterator : public BidirectionalIteratorFacade<ReferenceStorageIterator<C,T,R,S>,T, R, int>
00761 {
00762     friend class ReferenceStorageIterator<typename mutable_reference<C>::type, typename mutable_reference<T>::type, typename mutable_reference<R>::type, typename mutable_reference<S>::type>;
00763     friend class ReferenceStorageIterator<typename const_reference<C>::type, typename const_reference<T>::type, typename const_reference<R>::type, typename const_reference<S>::type>;
00764 
00765     typedef ReferenceStorageIterator<typename mutable_reference<C>::type, typename mutable_reference<T>::type, typename mutable_reference<R>::type, typename mutable_reference<S>::type> MyType;
00766     typedef ReferenceStorageIterator<typename const_reference<C>::type, typename const_reference<T>::type, typename const_reference<R>::type, typename const_reference<S>::type> MyConstType;
00767 
00768     public:
00769 
00770     // Constructors needed by the facade iterators.
00771     ReferenceStorageIterator(): container_(0), position_(0)
00772     {}
00773 
00774     ReferenceStorageIterator(C& cont, int pos)
00775         : container_(cont), position_(pos)
00776     {}
00777 
00778     ReferenceStorageIterator(const MyType& other)
00779         : container_(other.container_), position_(other.position_)
00780     {}
00781 
00782     ReferenceStorageIterator(const MyConstType& other)
00783         : container_(other.container_), position_(other.position_)
00784     {}
00785 
00786     // Methods needed by the forward iterator
00787     bool equals(const MyType& other) const
00788     {
00789         // check for identity since we store references/objects
00790         return position_ == other.position_ && container_.identical(other.container_);
00791     }
00792 
00793 
00794     bool equals(const MyConstType& other) const
00795     {
00796         // check for identity since we store references/objects
00797         return position_ == other.position_ && container_.identical(other.container_);
00798     }
00799 
00800     R dereference() const
00801     {
00802         // iterator facedes cast to const
00803         // thus this costness must be removed since the 'const'
00804         // container is '[...]Const' and not 'const [...]'
00805         return (const_cast< typename remove_const<C>::type& >(container_))[position_];
00806     }
00807 
00808     void increment()
00809     {
00810         ++position_;
00811     }
00812 
00813     // Additional function needed by BidirectionalIterator
00814     void decrement()
00815     {
00816         --position_;
00817     }
00818 
00819     // Additional function needed by RandomAccessIterator
00820     R elementAt(int i) const
00821     {
00822         return (const_cast< typename remove_const<C>::type& >(container_))[position_+i];
00823     }
00824 
00825     void advance(int n)
00826     {
00827         position_=position_+n;
00828     }
00829 
00830     std::ptrdiff_t distanceTo(const MyType& other) const
00831     {
00832         assert(container_.identical(other.container_));
00833         return other.position_ - position_;
00834     }
00835 
00836     std::ptrdiff_t distanceTo(const MyConstType& other) const
00837     {
00838         assert(container_.identical(other.container_));
00839         return other.position_ - position_;
00840     }
00841 
00842     std::ptrdiff_t index() const
00843     {
00844         return position_;
00845     }
00846 
00847     private:
00848     S container_;
00849     size_t position_;
00850 };
00851 
00852 
00853 
00854 template<class K, int n>
00855 void istl_assign_to_fmatrix(FieldMatrix<K,n,n>& fm, const DiagonalMatrix<K,n>& s)
00856 {
00857     fm = K();
00858     for(int i=0; i<n; ++i)
00859         fm[i][i] = s.diagonal()[i];
00860 }
00861 
00862 } // end namespace
00863 #endif

Generated on Thu Apr 2 10:40:14 2009 for dune-istl by  doxygen 1.5.6