00001 #ifndef DUNE_DIAGONAL_MATRIX_NEW_HH
00002 #define DUNE_DIAGONAL_MATRIX_NEW_HH
00003
00008 #include<cmath>
00009 #include<cstddef>
00010 #include<complex>
00011 #include<iostream>
00012 #include<memory>
00013 #include <dune/common/exceptions.hh>
00014 #include <dune/common/fmatrix.hh>
00015 #include <dune/common/fvector.hh>
00016 #include <dune/common/genericiterator.hh>
00017
00018
00019
00020 namespace Dune {
00021
00022 template< class K, int n > class DiagonalRowVectorConst;
00023 template< class K, int n > class DiagonalRowVector;
00024 template< class DiagonalMatrixType > class DiagonalMatrixWrapper;
00025 template< class C, class T, class R> class ContainerWrapperIterator;
00026
00027
00031 template<class K, int n>
00032 class DiagonalMatrix
00033 {
00034 typedef DiagonalMatrixWrapper< DiagonalMatrix<K,n> > WrapperType;
00035
00036 public:
00037
00038
00040 typedef K field_type;
00041
00043 typedef K block_type;
00044
00046 typedef std::size_t size_type;
00047
00049 enum {
00051 blocklevel = 1
00052 };
00053
00055 typedef DiagonalRowVector<K,n> row_type;
00056 typedef row_type reference;
00057 typedef DiagonalRowVectorConst<K,n> const_row_type;
00058 typedef const_row_type const_reference;
00059
00061 enum {
00063 rows = n,
00065 cols = n
00066 };
00067
00068
00069
00070
00071
00073 DiagonalMatrix () {}
00074
00076 DiagonalMatrix (const K& k)
00077 : diag_(k)
00078 {}
00079
00081 DiagonalMatrix (const FieldVector<K,n>& diag)
00082 : diag_(diag)
00083 {}
00084
00085
00086
00087 DiagonalMatrix& operator= (const K& k)
00088 {
00089 diag_ = k;
00090 return *this;
00091 }
00092
00093
00094 bool identical(const DiagonalMatrix<K,n>& other) const
00095 {
00096 return (this==&other);
00097 }
00098
00099
00101 typedef ContainerWrapperIterator<const WrapperType, reference, reference> Iterator;
00103 typedef Iterator iterator;
00105 typedef Iterator RowIterator;
00107 typedef typename row_type::Iterator ColIterator;
00108
00110 Iterator begin ()
00111 {
00112 return Iterator(WrapperType(this),0);
00113 }
00114
00116 Iterator end ()
00117 {
00118 return Iterator(WrapperType(this),n);
00119 }
00120
00122 Iterator rbegin ()
00123 {
00124 return Iterator(WrapperType(this),n-1);
00125 }
00126
00128 Iterator rend ()
00129 {
00130 return Iterator(WrapperType(this),-1);
00131 }
00132
00133
00135 typedef ContainerWrapperIterator<const WrapperType, const_reference, const_reference> ConstIterator;
00137 typedef ConstIterator const_iterator;
00139 typedef ConstIterator ConstRowIterator;
00141 typedef typename const_row_type::ConstIterator ConstColIterator;
00142
00144 ConstIterator begin () const
00145 {
00146 return ConstIterator(WrapperType(this),0);
00147 }
00148
00150 ConstIterator end () const
00151 {
00152 return ConstIterator(WrapperType(this),n);
00153 }
00154
00156 ConstIterator rbegin () const
00157 {
00158 return ConstIterator(WrapperType(this),n-1);
00159 }
00160
00162 ConstIterator rend () const
00163 {
00164 return ConstIterator(WrapperType(this),-1);
00165 }
00166
00167
00168
00169
00170
00172 DiagonalMatrix& operator+= (const DiagonalMatrix& y)
00173 {
00174 diag_ += y.diag_;
00175 return *this;
00176 }
00177
00179 DiagonalMatrix& operator-= (const DiagonalMatrix& y)
00180 {
00181 diag_ -= y.diag_;
00182 return *this;
00183 }
00184
00186 DiagonalMatrix& operator+= (const K& k)
00187 {
00188 diag_ += k;
00189 return *this;
00190 }
00191
00193 DiagonalMatrix& operator-= (const K& k)
00194 {
00195 diag_ -= k;
00196 return *this;
00197 }
00198
00200 DiagonalMatrix& operator*= (const K& k)
00201 {
00202 diag_ *= k;
00203 return *this;
00204 }
00205
00207 DiagonalMatrix& operator/= (const K& k)
00208 {
00209 diag_ /= k;
00210 return *this;
00211 }
00212
00213
00214
00215
00216
00218 template<class X, class Y>
00219 void mv (const X& x, Y& y) const
00220 {
00221 #ifdef DUNE_FMatrix_WITH_CHECKING
00222 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00223 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00224 #endif
00225 for (size_type i=0; i<n; ++i)
00226 y[i] = diag_[i] * x[i];
00227 }
00228
00230 template<class X, class Y>
00231 void mtv (const X& x, Y& y) const
00232 {
00233 mv(x, y);
00234 }
00235
00237 template<class X, class Y>
00238 void umv (const X& x, Y& y) const
00239 {
00240 #ifdef DUNE_FMatrix_WITH_CHECKING
00241 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00242 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00243 #endif
00244 for (size_type i=0; i<n; ++i)
00245 y[i] += diag_[i] * x[i];
00246 }
00247
00249 template<class X, class Y>
00250 void umtv (const X& x, Y& y) const
00251 {
00252 #ifdef DUNE_FMatrix_WITH_CHECKING
00253 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00254 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00255 #endif
00256 for (size_type i=0; i<n; ++i)
00257 y[i] += diag_[i] * x[i];
00258 }
00259
00261 template<class X, class Y>
00262 void umhv (const X& x, Y& y) const
00263 {
00264 #ifdef DUNE_FMatrix_WITH_CHECKING
00265 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00266 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00267 #endif
00268 for (size_type i=0; i<n; i++)
00269 y[i] += conjugateComplex(diag_[i])*x[i];
00270 }
00271
00273 template<class X, class Y>
00274 void mmv (const X& x, Y& y) const
00275 {
00276 #ifdef DUNE_FMatrix_WITH_CHECKING
00277 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00278 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00279 #endif
00280 for (size_type i=0; i<n; ++i)
00281 y[i] -= diag_[i] * x[i];
00282 }
00283
00285 template<class X, class Y>
00286 void mmtv (const X& x, Y& y) const
00287 {
00288 #ifdef DUNE_FMatrix_WITH_CHECKING
00289 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00290 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00291 #endif
00292 for (size_type i=0; i<n; ++i)
00293 y[i] -= diag_[i] * x[i];
00294 }
00295
00297 template<class X, class Y>
00298 void mmhv (const X& x, Y& y) const
00299 {
00300 #ifdef DUNE_FMatrix_WITH_CHECKING
00301 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00302 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00303 #endif
00304 for (size_type i=0; i<n; i++)
00305 y[i] -= conjugateComplex(diag_[i])*x[i];
00306 }
00307
00309 template<class X, class Y>
00310 void usmv (const K& alpha, const X& x, Y& y) const
00311 {
00312 #ifdef DUNE_FMatrix_WITH_CHECKING
00313 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00314 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00315 #endif
00316 for (size_type i=0; i<n; i++)
00317 y[i] += alpha * diag_[i] * x[i];
00318 }
00319
00321 template<class X, class Y>
00322 void usmtv (const K& alpha, const X& x, Y& y) const
00323 {
00324 #ifdef DUNE_FMatrix_WITH_CHECKING
00325 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00326 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00327 #endif
00328 for (size_type i=0; i<n; i++)
00329 y[i] += alpha * diag_[i] * x[i];
00330 }
00331
00333 template<class X, class Y>
00334 void usmhv (const K& alpha, const X& x, Y& y) const
00335 {
00336 #ifdef DUNE_FMatrix_WITH_CHECKING
00337 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00338 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00339 #endif
00340 for (size_type i=0; i<n; i++)
00341 y[i] += alpha * conjugateComplex(diag_[i]) * x[i];
00342 }
00343
00344
00345
00347 double frobenius_norm () const
00348 {
00349 return diag_.two_norm();
00350 }
00351
00353 double frobenius_norm2 () const
00354 {
00355 return diag_.two_norm2();
00356 }
00357
00359 double infinity_norm () const
00360 {
00361 return diag_.infinity_norm();
00362 }
00363
00365 double infinity_norm_real () const
00366 {
00367 return diag_.infinity_norm_real();
00368 }
00369
00370
00371
00372
00373
00375 template<class V>
00376 void solve (V& x, const V& b) const
00377 {
00378 for (int i=0; i<n; i++)
00379 x[i] = b[i]/diag_[i];
00380 }
00381
00383 void invert()
00384 {
00385 for (int i=0; i<n; i++)
00386 diag_[i] = 1/diag_[i];
00387 }
00388
00390 K determinant () const
00391 {
00392 K det = diag_[0];
00393 for (int i=1; i<n; i++)
00394 det *= diag_[i];
00395 return det;
00396 }
00397
00398
00399
00400
00401
00403 size_type N () const
00404 {
00405 return n;
00406 }
00407
00409 size_type M () const
00410 {
00411 return n;
00412 }
00413
00414
00415
00416
00417
00419 bool exists (size_type i, size_type j) const
00420 {
00421 #ifdef DUNE_FMatrix_WITH_CHECKING
00422 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00423 if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00424 #endif
00425 return i==j;
00426 }
00427
00428
00429
00431 friend std::ostream& operator<< (std::ostream& s, const DiagonalMatrix<K,n>& a)
00432 {
00433 for (size_type i=0; i<n; i++) {
00434 for (size_type j=0; j<n; j++)
00435 s << ((i==j) ? a.diag_[i] : 0) << " ";
00436 s << std::endl;
00437 }
00438 return s;
00439 }
00440
00442 reference operator[](size_type i)
00443 {
00444 return reference(const_cast<K*>(&diag_[i]), i);
00445 }
00446
00448 const_reference operator[](size_type i) const
00449 {
00450 return const_reference(const_cast<K*>(&diag_[i]), i);
00451 }
00452
00454 const K& diagonal(size_type i) const
00455 {
00456 return diag_[i];
00457 }
00458
00460 K& diagonal(size_type i)
00461 {
00462 return diag_[i];
00463 }
00464
00466 const FieldVector<K,n>& diagonal() const
00467 {
00468 return diag_;
00469 }
00470
00472 FieldVector<K,n>& diagonal()
00473 {
00474 return diag_;
00475 }
00476
00477 private:
00478
00479
00480 FieldVector<K,n> diag_;
00481 };
00482
00483
00484 template<class DiagonalMatrixType>
00485 class DiagonalMatrixWrapper
00486 {
00487 typedef typename DiagonalMatrixType::reference reference;
00488 typedef typename DiagonalMatrixType::const_reference const_reference;
00489 typedef typename DiagonalMatrixType::field_type K;
00490 typedef DiagonalRowVector<K, DiagonalMatrixType::rows> row_type;
00491 typedef std::size_t size_type;
00492 typedef DiagonalMatrixWrapper< DiagonalMatrixType> MyType;
00493
00494 friend class ContainerWrapperIterator<const MyType, reference, reference>;
00495 friend class ContainerWrapperIterator<const MyType, const_reference, const_reference>;
00496
00497 public:
00498
00499 DiagonalMatrixWrapper() :
00500 mat_(0)
00501 {}
00502
00503 DiagonalMatrixWrapper(const DiagonalMatrixType* mat) :
00504 mat_(const_cast<DiagonalMatrixType*>(mat))
00505 {}
00506
00507 size_type realIndex(int i) const
00508 {
00509 return i;
00510 }
00511
00512 row_type* pointer(int i) const
00513 {
00514 row_ = row_type(&(mat_->diagonal(i)), i);
00515 return &row_;
00516 }
00517
00518 bool identical(const DiagonalMatrixWrapper& other) const
00519 {
00520 return mat_==other.mat_;
00521 }
00522
00523 private:
00524
00525 mutable DiagonalMatrixType* mat_;
00526 mutable row_type row_;
00527 };
00528
00532 template< class K, int n >
00533 class DiagonalRowVectorConst
00534 {
00535 template<class DiagonalMatrixType>
00536 friend class DiagonalMatrixWrapper;
00537 friend class ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&>;
00538
00539 public:
00540
00541 enum { dimension = n };
00542
00543
00544
00545
00546
00548 typedef K field_type;
00549
00551 typedef K block_type;
00552
00554 typedef std::size_t size_type;
00555
00557 enum {
00559 blocklevel = 1
00560 };
00561
00563 enum {
00565 size = n
00566 };
00567
00569 DiagonalRowVectorConst() :
00570 p_(0),
00571 row_(0)
00572 {}
00573
00575 explicit DiagonalRowVectorConst (K* p, int col) :
00576 p_(p),
00577 row_(col)
00578 {}
00579
00580
00581
00583 const K& operator[] (size_type i) const
00584 {
00585 #ifdef DUNE_FMatrix_WITH_CHECKING
00586 if (i!=row_)
00587 DUNE_THROW(FMatrixError,"index is contained in pattern");
00588 #endif
00589 return *p_;
00590 }
00591
00592
00593
00594 bool identical(const DiagonalRowVectorConst<K,n>& other) const
00595 {
00596 return ((p_ == other.p_) and (row_ == other.row_));
00597 }
00598
00600 typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
00602 typedef ConstIterator const_iterator;
00603
00605 ConstIterator begin () const
00606 {
00607 return ConstIterator(*this,0);
00608 }
00609
00611 ConstIterator end () const
00612 {
00613 return ConstIterator(*this,1);
00614 }
00615
00617 ConstIterator rbegin () const
00618 {
00619 return ConstIterator(*this,0);
00620 }
00621
00623 ConstIterator rend () const
00624 {
00625 return ConstIterator(*this,-1);
00626 }
00627
00629 bool operator== (const DiagonalRowVectorConst& y) const
00630 {
00631 return ((p_==y.p_) and (row_==y.row_));
00632 }
00633
00634
00635
00637 size_type N () const
00638 {
00639 return n;
00640 }
00641
00643 size_type dim () const
00644 {
00645 return n;
00646 }
00647
00649 size_type rowIndex() const
00650 {
00651 return row_;
00652 }
00653
00655 const K& diagonal() const
00656 {
00657 return *p_;
00658 }
00659
00660 protected:
00661
00662 size_type realIndex(int i) const
00663 {
00664 return rowIndex();
00665 }
00666
00667 K* pointer(size_type i) const
00668 {
00669 return const_cast<K*>(p_);
00670 }
00671
00672 DiagonalRowVectorConst* operator&()
00673 {
00674 return this;
00675 }
00676
00677
00678 K* p_;
00679 size_type row_;
00680 };
00681
00682 template< class K, int n >
00683 class DiagonalRowVector : public DiagonalRowVectorConst<K,n>
00684 {
00685 template<class DiagonalMatrixType>
00686 friend class DiagonalMatrixWrapper;
00687 friend class ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&>;
00688
00689 public:
00690
00691
00692
00693
00695 typedef K field_type;
00696
00698 typedef K block_type;
00699
00701 typedef std::size_t size_type;
00702
00704 DiagonalRowVector() : DiagonalRowVectorConst<K,n>()
00705 {}
00706
00708 explicit DiagonalRowVector (K* p, int col) : DiagonalRowVectorConst<K,n>(p, col)
00709 {}
00710
00711
00713 DiagonalRowVector& operator= (const K& k)
00714 {
00715 *p_ = k;
00716 return *this;
00717 }
00718
00719
00720
00722 K& operator[] (size_type i)
00723 {
00724 #ifdef DUNE_FMatrix_WITH_CHECKING
00725 if (i!=row_)
00726 DUNE_THROW(FMatrixError,"index is contained in pattern");
00727 #endif
00728 return *p_;
00729 }
00730
00732 typedef ContainerWrapperIterator<DiagonalRowVector<K,n>, K, K&> Iterator;
00734 typedef Iterator iterator;
00735
00737 Iterator begin ()
00738 {
00739 return Iterator(*this, 0);
00740 }
00741
00743 Iterator end ()
00744 {
00745 return Iterator(*this, 1);
00746 }
00747
00749 Iterator rbegin ()
00750 {
00751 return Iterator(*this, 0);
00752 }
00753
00755 Iterator rend ()
00756 {
00757 return Iterator(*this, -1);
00758 }
00759
00761 typedef ContainerWrapperIterator<DiagonalRowVectorConst<K,n>, const K, const K&> ConstIterator;
00763 typedef ConstIterator const_iterator;
00764
00765 using DiagonalRowVectorConst<K,n>::identical;
00766 using DiagonalRowVectorConst<K,n>::operator[];
00767 using DiagonalRowVectorConst<K,n>::operator==;
00768 using DiagonalRowVectorConst<K,n>::begin;
00769 using DiagonalRowVectorConst<K,n>::end;
00770 using DiagonalRowVectorConst<K,n>::rbegin;
00771 using DiagonalRowVectorConst<K,n>::rend;
00772 using DiagonalRowVectorConst<K,n>::N;
00773 using DiagonalRowVectorConst<K,n>::dim;
00774 using DiagonalRowVectorConst<K,n>::rowIndex;
00775 using DiagonalRowVectorConst<K,n>::diagonal;
00776
00777 protected:
00778
00779 DiagonalRowVector* operator&()
00780 {
00781 return this;
00782 }
00783
00784 private:
00785
00786 using DiagonalRowVectorConst<K,n>::p_;
00787 using DiagonalRowVectorConst<K,n>::row_;
00788 };
00789
00790
00791
00792 template<class K, int n>
00793 struct const_reference< DiagonalRowVector<K,n> >
00794 {
00795 typedef DiagonalRowVectorConst<K,n> type;
00796 };
00797
00798 template<class K, int n>
00799 struct const_reference< DiagonalRowVectorConst<K,n> >
00800 {
00801 typedef DiagonalRowVectorConst<K,n> type;
00802 };
00803
00804 template<class K, int n>
00805 struct mutable_reference< DiagonalRowVector<K,n> >
00806 {
00807 typedef DiagonalRowVector<K,n> type;
00808 };
00809
00810 template<class K, int n>
00811 struct mutable_reference< DiagonalRowVectorConst<K,n> >
00812 {
00813 typedef DiagonalRowVector<K,n> type;
00814 };
00815
00816
00817
00818
00819 template<class CW, class T, class R>
00820 class ContainerWrapperIterator : public BidirectionalIteratorFacade<ContainerWrapperIterator<CW,T,R>,T, R, int>
00821 {
00822 typedef typename remove_const<CW>::type NonConstCW;
00823
00824 friend class ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type>;
00825 friend class ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type>;
00826
00827 typedef ContainerWrapperIterator<CW, typename mutable_reference<T>::type, typename mutable_reference<R>::type> MyType;
00828 typedef ContainerWrapperIterator<CW, typename const_reference<T>::type, typename const_reference<R>::type> MyConstType;
00829
00830 public:
00831
00832
00833 ContainerWrapperIterator():
00834 containerWrapper_(),
00835 position_(0)
00836 {}
00837
00838 ContainerWrapperIterator(CW containerWrapper, int position) :
00839 containerWrapper_(containerWrapper),
00840 position_(position)
00841 {}
00842
00843 template<class OtherContainerWrapperIteratorType>
00844 ContainerWrapperIterator(OtherContainerWrapperIteratorType& other):
00845 containerWrapper_(other.containerWrapper_),
00846 position_(other.position_)
00847 {}
00848
00849 ContainerWrapperIterator(const MyType& other):
00850 containerWrapper_(other.containerWrapper_),
00851 position_(other.position_)
00852 {}
00853
00854 ContainerWrapperIterator(const MyConstType& other):
00855 containerWrapper_(other.containerWrapper_),
00856 position_(other.position_)
00857 {}
00858
00859 template<class OtherContainerWrapperIteratorType>
00860 ContainerWrapperIterator& operator=(OtherContainerWrapperIteratorType& other)
00861 {
00862 containerWrapper_ = other.containerWrapper_;
00863 position_ = other.position_;
00864 }
00865
00866
00867
00868 T* operator->() const
00869 {
00870 return containerWrapper_.pointer(position_);
00871 }
00872
00873
00874 bool equals(const MyType& other) const
00875 {
00876 return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
00877 }
00878
00879 bool equals(const MyConstType& other) const
00880 {
00881 return position_ == other.position_ && containerWrapper_.identical(other.containerWrapper_);
00882 }
00883
00884 R dereference() const
00885 {
00886 return *containerWrapper_.pointer(position_);
00887 }
00888
00889 void increment()
00890 {
00891 ++position_;
00892 }
00893
00894
00895 void decrement()
00896 {
00897 --position_;
00898 }
00899
00900
00901 R elementAt(int i) const
00902 {
00903 return *containerWrapper_.pointer(position_+i);
00904 }
00905
00906 void advance(int n)
00907 {
00908 position_=position_+n;
00909 }
00910
00911 template<class OtherContainerWrapperIteratorType>
00912 std::ptrdiff_t distanceTo(OtherContainerWrapperIteratorType& other) const
00913 {
00914 assert(containerWrapper_.identical(other));
00915 return other.position_ - position_;
00916 }
00917
00918 std::ptrdiff_t index() const
00919 {
00920 return containerWrapper_.realIndex(position_);
00921 }
00922
00923 private:
00924 NonConstCW containerWrapper_;
00925 size_t position_;
00926 };
00927
00928
00929
00930 template<class K, int n>
00931 void istl_assign_to_fmatrix(FieldMatrix<K,n,n>& fm, const DiagonalMatrix<K,n>& s)
00932 {
00933 fm = K();
00934 for(int i=0; i<n; ++i)
00935 fm[i][i] = s.diagonal()[i];
00936 }
00937
00938 }
00939 #endif