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
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
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
00084 DiagonalMatrix& operator= (const K& k)
00085 {
00086 diag_ = k;
00087 return *this;
00088 }
00089
00090
00091 bool identical(const DiagonalMatrix<K,n>& other) const
00092 {
00093 return (this==&other);
00094 }
00095
00096
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
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
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
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
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
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
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
00471 FieldVector<K,n> diag_;
00472 };
00473
00474
00478 template< class K, int n >
00479 class DiagonalRowVectorConst
00480 {
00481 public:
00482
00483 enum { dimension = n };
00484
00485
00486
00487
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
00523
00525 const K& operator[] (size_type i) const
00526 {
00527 if (i!=row_)
00528 DUNE_THROW(FMatrixError,"index is read only");
00529
00530 return *p_;
00531 }
00532
00533
00534
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
00549
00550 return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
00551 }
00552
00554 ConstIterator end () const
00555 {
00556
00557
00558 return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_+1);
00559 }
00560
00562 ConstIterator rbegin () const
00563 {
00564
00565
00566 return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),row_);
00567 }
00568
00570 ConstIterator rend () const
00571 {
00572
00573
00574 return ConstIterator(*const_cast<DiagonalRowVectorConst<K,n>*>(this),-1);
00575 }
00576
00578
00579
00580
00581
00582
00583
00584
00585
00587 bool operator== (const DiagonalRowVectorConst& y) const
00588 {
00589 return ((p_==y.p_) and (row_==y.row_));
00590 }
00591
00592
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
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
00631
00632
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
00653 DiagonalRowVector& operator= (const K& k)
00654 {
00655 *p_ = k;
00656 return *this;
00657 }
00658
00659
00660
00662 K& operator[] (size_type i)
00663 {
00664 if (i!=row_)
00665 DUNE_THROW(FMatrixError,"index is read only");
00666
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
00701
00702
00703
00704
00705
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
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
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
00787 bool equals(const MyType& other) const
00788 {
00789
00790 return position_ == other.position_ && container_.identical(other.container_);
00791 }
00792
00793
00794 bool equals(const MyConstType& other) const
00795 {
00796
00797 return position_ == other.position_ && container_.identical(other.container_);
00798 }
00799
00800 R dereference() const
00801 {
00802
00803
00804
00805 return (const_cast< typename remove_const<C>::type& >(container_))[position_];
00806 }
00807
00808 void increment()
00809 {
00810 ++position_;
00811 }
00812
00813
00814 void decrement()
00815 {
00816 --position_;
00817 }
00818
00819
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 }
00863 #endif