00001 #ifndef DUNE_BCRSMATRIX_HH
00002 #define DUNE_BCRSMATRIX_HH
00003
00004 #include<cmath>
00005 #include<complex>
00006 #include<set>
00007 #include<iostream>
00008 #include<algorithm>
00009 #include<numeric>
00010 #include<vector>
00011
00012 #include "istlexception.hh"
00013 #include "allocator.hh"
00014 #include "bvector.hh"
00015 #include <dune/common/stdstreams.hh>
00016 #include <dune/common/iteratorfacades.hh>
00017 #include <dune/common/typetraits.hh>
00018 #include <dune/common/static_assert.hh>
00019 #include <dune/common/poolallocator.hh>
00020
00025 namespace Dune {
00026
00066 template<typename M>
00067 class MatrixDimension;
00068
00176 #ifdef DUNE_EXPRESSIONTEMPLATES
00177 template<class B, class A>
00178 class BCRSMatrix : public ExprTmpl::Matrix< BCRSMatrix<B,A> >
00179 #else
00180 template<class B, class A=ISTLAllocator>
00181 class BCRSMatrix
00182 #endif
00183 {
00184 friend class MatrixDimension<BCRSMatrix>;
00185
00186 private:
00187 enum BuildStage{
00189 notbuilt=0,
00194 rowSizesBuilt=1,
00196 built=2
00197 };
00198
00199 public:
00200
00201
00202
00204 typedef typename B::field_type field_type;
00205
00207 typedef B block_type;
00208
00210 typedef A allocator_type;
00211
00213 typedef CompressedBlockVectorWindow<B,A> row_type;
00214
00216 typedef typename A::size_type size_type;
00217
00219 enum {
00221 blocklevel = B::blocklevel+1
00222 };
00223
00225 enum BuildMode {
00236 row_wise,
00245 random,
00249 unknown
00250 };
00251
00252
00253
00254
00256 row_type& operator[] (size_type i)
00257 {
00258 #ifdef DUNE_ISTL_WITH_CHECKING
00259 if (r==0) DUNE_THROW(ISTLError,"row not initialized yet");
00260 if (i>=n) DUNE_THROW(ISTLError,"index out of range");
00261 if (r[i].getptr()==0) DUNE_THROW(ISTLError,"row not initialized yet");
00262 #endif
00263 return r[i];
00264 }
00265
00267 const row_type& operator[] (size_type i) const
00268 {
00269 #ifdef DUNE_ISTL_WITH_CHECKING
00270 if (built!=ready) DUNE_THROW(ISTLError,"row not initialized yet");
00271 if (i>=n) DUNE_THROW(ISTLError,"index out of range");
00272 #endif
00273 return r[i];
00274 }
00275
00276
00277
00278
00280 template<class T>
00281 class RealRowIterator
00282 : public RandomAccessIteratorFacade<RealRowIterator<T>, T>
00283 {
00284
00285 public:
00287 typedef typename remove_const<T>::type ValueType;
00288
00289 friend class RandomAccessIteratorFacade<RealRowIterator<const ValueType>, const ValueType>;
00290 friend class RandomAccessIteratorFacade<RealRowIterator<ValueType>, ValueType>;
00291 friend class RealRowIterator<const ValueType>;
00292 friend class RealRowIterator<ValueType>;
00293
00295 RealRowIterator (row_type* _p, size_type _i)
00296 : p(_p), i(_i)
00297 {}
00298
00300 RealRowIterator ()
00301 : p(0), i(0)
00302 {}
00303
00304 RealRowIterator(const RealRowIterator<ValueType>& it)
00305 : p(it.p), i(it.i)
00306 {}
00307
00308
00310 size_type index () const
00311 {
00312 return i;
00313 }
00314
00315 std::ptrdiff_t distanceTo(const RealRowIterator<ValueType>& other) const
00316 {
00317 assert(other.p==p);
00318 return (other.i-i);
00319 }
00320
00321 std::ptrdiff_t distanceTo(const RealRowIterator<const ValueType>& other) const
00322 {
00323 assert(other.p==p);
00324 return (other.i-i);
00325 }
00326
00328 bool equals (const RealRowIterator<ValueType>& other) const
00329 {
00330 assert(other.p==p);
00331 return i==other.i;
00332 }
00333
00335 bool equals (const RealRowIterator<const ValueType>& other) const
00336 {
00337 assert(other.p==p);
00338 return i==other.i;
00339 }
00340
00341 private:
00343 void increment()
00344 {
00345 ++i;
00346 }
00347
00349 void decrement()
00350 {
00351 --i;
00352 }
00353
00354 void advance(std::ptrdiff_t diff)
00355 {
00356 i+=diff;
00357 }
00358
00359 T& elementAt(std::ptrdiff_t diff) const
00360 {
00361 return p[i+diff];
00362 }
00363
00365 row_type& dereference () const
00366 {
00367 return p[i];
00368 }
00369
00370 row_type* p;
00371 size_type i;
00372 };
00373
00375 typedef RealRowIterator<row_type> iterator;
00376 typedef RealRowIterator<row_type> Iterator;
00377
00378
00380 Iterator begin ()
00381 {
00382 return Iterator(r,0);
00383 }
00384
00386 Iterator end ()
00387 {
00388 return Iterator(r,n);
00389 }
00390
00392 Iterator rbegin ()
00393 {
00394 return Iterator(r,n-1);
00395 }
00396
00398 Iterator rend ()
00399 {
00400 return Iterator(r,-1);
00401 }
00402
00404 typedef Iterator RowIterator;
00405
00407 typedef typename row_type::Iterator ColIterator;
00408
00410 typedef RealRowIterator<const row_type> const_iterator;
00411 typedef RealRowIterator<const row_type> ConstIterator;
00412
00413
00415 ConstIterator begin () const
00416 {
00417 return ConstIterator(r,0);
00418 }
00419
00421 ConstIterator end () const
00422 {
00423 return ConstIterator(r,n);
00424 }
00425
00427 ConstIterator rbegin () const
00428 {
00429 return ConstIterator(r,n-1);
00430 }
00431
00433 ConstIterator rend () const
00434 {
00435 return ConstIterator(r,-1);
00436 }
00437
00439 typedef ConstIterator ConstRowIterator;
00440
00442 typedef typename row_type::ConstIterator ConstColIterator;
00443
00444
00445
00447 BCRSMatrix ()
00448 : build_mode(unknown), ready(notbuilt), n(0), m(0), nnz(0),
00449 r(0), a(0), j(0)
00450 {}
00451
00453 BCRSMatrix (size_type _n, size_type _m, size_type _nnz, BuildMode bm)
00454 : build_mode(bm), ready(notbuilt)
00455 {
00456 allocate(_n, _m, _nnz);
00457 }
00458
00460 BCRSMatrix (size_type _n, size_type _m, BuildMode bm)
00461 : build_mode(bm), ready(notbuilt)
00462 {
00463 allocate(_n, _m);
00464 }
00465
00467 BCRSMatrix (const BCRSMatrix& Mat)
00468 : n(Mat.n), nnz(0)
00469 {
00470
00471 size_type _nnz = Mat.nnz;
00472
00473
00474 if (_nnz<=0)
00475 {
00476 _nnz = 0;
00477 for (size_type i=0; i<n; i++)
00478 _nnz += Mat.r[i].getsize();
00479 }
00480
00481 allocate(Mat.n, Mat.m, _nnz);
00482
00483
00484 copyWindowStructure(Mat);
00485 }
00486
00488 ~BCRSMatrix ()
00489 {
00490 deallocate();
00491 }
00492
00497 void setBuildMode(BuildMode bm)
00498 {
00499 if(ready==notbuilt)
00500 build_mode = bm;
00501 else
00502 DUNE_THROW(InvalidStateException, "Matrix structure is already built (ready="<<ready<<").");
00503 }
00504
00520 void setSize(size_type rows, size_type columns, size_type nnz=0)
00521 {
00522
00523 deallocate();
00524
00525
00526 allocate(rows, columns, nnz);
00527 }
00528
00530 BCRSMatrix& operator= (const BCRSMatrix& Mat)
00531 {
00532
00533 if (&Mat==this) return *this;
00534
00535
00536 deallocate(false);
00537
00538
00539 if (n>0 && n!=Mat.n)
00540
00541 A::template free<row_type>(r);
00542
00543 nnz=Mat.nnz;
00544 if (nnz<=0)
00545 {
00546 for (size_type i=0; i<Mat.n; i++)
00547 nnz += Mat.r[i].getsize();
00548 }
00549
00550
00551 allocate(Mat.n, Mat.m, nnz, n!=Mat.n);
00552
00553
00554 copyWindowStructure(Mat);
00555 return *this;
00556 }
00557
00559 BCRSMatrix& operator= (const field_type& k)
00560 {
00561 for (size_type i=0; i<n; i++) r[i] = k;
00562 return *this;
00563 }
00564
00565
00566
00568 class CreateIterator
00569 {
00570 public:
00572 CreateIterator (BCRSMatrix& _Mat, size_type _i)
00573 : Mat(_Mat), i(_i), nnz(0), current_row(Mat.a, Mat.j, 0)
00574 {
00575 if (i==0 && Mat.ready)
00576 DUNE_THROW(ISTLError,"creation only allowed for uninitialized matrix");
00577 if(Mat.build_mode!=row_wise)
00578 {
00579 if(Mat.build_mode==unknown)
00580 Mat.build_mode=row_wise;
00581 else
00582 DUNE_THROW(ISTLError,"creation only allowed if row wise allocation was requested in the constructor");
00583 }
00584 }
00585
00587 CreateIterator& operator++()
00588 {
00589
00590 if (Mat.ready)
00591 DUNE_THROW(ISTLError,"matrix already built up");
00592
00593
00594
00595
00596
00597
00598 size_type s = pattern.size();
00599
00600 if(s>0){
00601
00602 nnz += s;
00603
00604
00605 if (Mat.nnz>0)
00606 {
00607
00608
00609
00610 if (nnz>Mat.nnz)
00611 DUNE_THROW(ISTLError,"allocated nnz too small");
00612
00613
00614 Mat.r[i].set(s,current_row.getptr(),current_row.getindexptr());
00615 current_row.setptr(current_row.getptr()+s);
00616 current_row.setindexptr(current_row.getindexptr()+s);
00617 }else{
00618
00619
00620 B* a = A::template malloc<B>(s);
00621 size_type* j = A::template malloc<size_type>(s);
00622 Mat.r[i].set(s,a,j);
00623 }
00624 }else
00625
00626 Mat.r[i].set(0,0,0);
00627
00628
00629 size_type k=0;
00630 size_type *j = Mat.r[i].getindexptr();
00631 for (typename PatternType::const_iterator it=pattern.begin(); it!=pattern.end(); ++it)
00632 j[k++] = *it;
00633
00634
00635 i++;
00636 pattern.clear();
00637
00638
00639 if (i==Mat.n)
00640 {
00641 Mat.ready = built;
00642 if(Mat.nnz>0)
00643
00644
00645 Mat.nnz=nnz;
00646 }
00647
00648 return *this;
00649 }
00650
00652 bool operator!= (const CreateIterator& it) const
00653 {
00654 return (i!=it.i) || (&Mat!=&it.Mat);
00655 }
00656
00658 bool operator== (const CreateIterator& it) const
00659 {
00660 return (i==it.i) && (&Mat==&it.Mat);
00661 }
00662
00664 size_type index () const
00665 {
00666 return i;
00667 }
00668
00670 void insert (size_type j)
00671 {
00672 pattern.insert(j);
00673 }
00674
00676 bool contains (size_type j)
00677 {
00678 if (pattern.find(j)!=pattern.end())
00679 return true;
00680 else
00681 return false;
00682 }
00688 size_type size() const
00689 {
00690 return pattern.size();
00691 }
00692
00693 private:
00694 BCRSMatrix& Mat;
00695 size_type i;
00696 size_type nnz;
00697 typedef std::set<size_type,std::less<size_type>,PoolAllocator<size_type,10> > PatternType;
00698 PatternType pattern;
00699 row_type current_row;
00700 };
00701
00703 friend class CreateIterator;
00704
00706 CreateIterator createbegin ()
00707 {
00708 return CreateIterator(*this,0);
00709 }
00710
00712 CreateIterator createend ()
00713 {
00714 return CreateIterator(*this,n);
00715 }
00716
00717
00718
00719
00721 void setrowsize (size_type i, size_type s)
00722 {
00723 if (build_mode!=random)
00724 DUNE_THROW(ISTLError,"requires random build mode");
00725 if (ready)
00726 DUNE_THROW(ISTLError,"matrix row sizes already built up");
00727
00728 r[i].setsize(s);
00729 }
00730
00732 size_type getrowsize (size_type i) const
00733 {
00734 #ifdef DUNE_ISTL_WITH_CHECKING
00735 if (r==0) DUNE_THROW(ISTLError,"row not initialized yet");
00736 if (i>=n) DUNE_THROW(ISTLError,"index out of range");
00737 #endif
00738 return r[i].getsize();
00739 }
00740
00742 void incrementrowsize (size_type i, size_type s = 1)
00743 {
00744 if (build_mode!=random)
00745 DUNE_THROW(ISTLError,"requires random build mode");
00746 if (ready)
00747 DUNE_THROW(ISTLError,"matrix row sizes already built up");
00748
00749 r[i].setsize(r[i].getsize()+s);
00750 }
00751
00753 void endrowsizes ()
00754 {
00755 if (build_mode!=random)
00756 DUNE_THROW(ISTLError,"requires random build mode");
00757 if (ready)
00758 DUNE_THROW(ISTLError,"matrix row sizes already built up");
00759
00760
00761 size_type total=0;
00762 for (size_type i=0; i<n; i++)
00763 {
00764 if (r[i].getsize()<0)
00765 DUNE_THROW(ISTLError,"rowsize must be nonnegative");
00766 total += r[i].getsize();
00767 }
00768
00769 if(nnz==0)
00770
00771 allocate(n,m,total,false);
00772 else if(nnz<total)
00773 DUNE_THROW(ISTLError,"Specified number of nonzeros ("<<nnz<<") not "
00774 <<"sufficient for calculated nonzeros ("<<total<<"! ");
00775
00776
00777 setWindowPointers(begin());
00778
00779
00780
00781 for (size_type k=0; k<nnz; k++)
00782 j[k] = m;
00783 ready = rowSizesBuilt;
00784 }
00785
00787
00797 void addindex (size_type row, size_type col)
00798 {
00799 if (build_mode!=random)
00800 DUNE_THROW(ISTLError,"requires random build mode");
00801 if (ready==built)
00802 DUNE_THROW(ISTLError,"matrix already built up");
00803 if (ready==notbuilt)
00804 DUNE_THROW(ISTLError,"matrix row sizes not built up yet");
00805
00806 if (col >= m)
00807 DUNE_THROW(ISTLError,"column index exceeds matrix size");
00808
00809
00810 size_type* const first = r[row].getindexptr();
00811 size_type* const last = first + r[row].getsize();
00812
00813
00814 size_type* pos = std::lower_bound(first,last,col);
00815
00816
00817 if (pos!=last && *pos == col) return;
00818
00819
00820 size_type* end = std::lower_bound(pos,last,m);
00821 if (end==last)
00822 DUNE_THROW(ISTLError,"row is too small");
00823
00824
00825 std::copy_backward(pos,end,end+1);
00826 *pos = col;
00827
00828 }
00829
00831 void endindices ()
00832 {
00833 if (build_mode!=random)
00834 DUNE_THROW(ISTLError,"requires random build mode");
00835 if (ready==built)
00836 DUNE_THROW(ISTLError,"matrix already built up");
00837 if (ready==notbuilt)
00838 DUNE_THROW(ISTLError,"row sizes are not built up yet");
00839
00840
00841 RowIterator endi=end();
00842 for (RowIterator i=begin(); i!=endi; ++i)
00843 {
00844 ColIterator endj = (*i).end();
00845 for (ColIterator j=(*i).begin(); j!=endj; ++j){
00846 if (j.index()<0)
00847 {
00848 std::cout << "j[" << j.offset() << "]=" << j.index() << std::endl;
00849 DUNE_THROW(ISTLError,"undefined index detected");
00850 }
00851 if (j.index()>=m){
00852 dwarn << "WARNING: size of row "<< i.index()<<" is "<<j.offset()<<". But was specified as being "<< (*i).end().offset()
00853 <<". This means you are wasting valuable space and creating additional cache misses!"<<std::endl;
00854 r[i.index()].setsize(j.offset());
00855 break;
00856 }
00857 }
00858 }
00859
00860
00861 ready = built;
00862 }
00863
00864
00865
00867 BCRSMatrix& operator*= (const field_type& k)
00868 {
00869 if (nnz>0)
00870 {
00871
00872 for (size_type i=0; i<nnz; i++)
00873 a[i] *= k;
00874 }
00875 else
00876 {
00877 RowIterator endi=end();
00878 for (RowIterator i=begin(); i!=endi; ++i)
00879 {
00880 ColIterator endj = (*i).end();
00881 for (ColIterator j=(*i).begin(); j!=endj; ++j)
00882 (*j) *= k;
00883 }
00884 }
00885
00886 return *this;
00887 }
00888
00890 BCRSMatrix& operator/= (const field_type& k)
00891 {
00892 if (nnz>0)
00893 {
00894
00895 for (size_type i=0; i<nnz; i++)
00896 a[i] /= k;
00897 }
00898 else
00899 {
00900 RowIterator endi=end();
00901 for (RowIterator i=begin(); i!=endi; ++i)
00902 {
00903 ColIterator endj = (*i).end();
00904 for (ColIterator j=(*i).begin(); j!=endj; ++j)
00905 (*j) /= k;
00906 }
00907 }
00908
00909 return *this;
00910 }
00911
00912
00918 BCRSMatrix& operator+= (const BCRSMatrix& b)
00919 {
00920 #ifdef DUNE_ISTL_WITH_CHECKING
00921 if(N()!=b.N() || M() != b.M())
00922 DUNE_THROW(RangeError, "Matrix sizes do not match!");
00923 #endif
00924 RowIterator endi=end();
00925 ConstRowIterator j=b.begin();
00926 for (RowIterator i=begin(); i!=endi; ++i, ++j){
00927 i->operator+=(*j);
00928 }
00929
00930 return *this;
00931 }
00932
00938 BCRSMatrix& operator-= (const BCRSMatrix& b)
00939 {
00940 #ifdef DUNE_ISTL_WITH_CHECKING
00941 if(N()!=b.N() || M() != b.M())
00942 DUNE_THROW(RangeError, "Matrix sizes do not match!");
00943 #endif
00944 RowIterator endi=end();
00945 ConstRowIterator j=b.begin();
00946 for (RowIterator i=begin(); i!=endi; ++i, ++j){
00947 i->operator-=(*j);
00948 }
00949
00950 return *this;
00951 }
00952
00953
00955 template<class X, class Y>
00956 void mv (const X& x, Y& y) const
00957 {
00958 #ifdef DUNE_ISTL_WITH_CHECKING
00959 if (x.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
00960 if (y.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
00961 #endif
00962 ConstRowIterator endi=end();
00963 for (ConstRowIterator i=begin(); i!=endi; ++i)
00964 {
00965 y[i.index()]=0;
00966 ConstColIterator endj = (*i).end();
00967 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00968 (*j).umv(x[j.index()],y[i.index()]);
00969 }
00970 }
00971
00973 template<class X, class Y>
00974 void umv (const X& x, Y& y) const
00975 {
00976 #ifdef DUNE_ISTL_WITH_CHECKING
00977 if (x.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
00978 if (y.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
00979 #endif
00980 ConstRowIterator endi=end();
00981 for (ConstRowIterator i=begin(); i!=endi; ++i)
00982 {
00983 ConstColIterator endj = (*i).end();
00984 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00985 (*j).umv(x[j.index()],y[i.index()]);
00986 }
00987 }
00988
00990 template<class X, class Y>
00991 void mmv (const X& x, Y& y) const
00992 {
00993 #ifdef DUNE_ISTL_WITH_CHECKING
00994 if (x.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
00995 if (y.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
00996 #endif
00997 ConstRowIterator endi=end();
00998 for (ConstRowIterator i=begin(); i!=endi; ++i)
00999 {
01000 ConstColIterator endj = (*i).end();
01001 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01002 (*j).mmv(x[j.index()],y[i.index()]);
01003 }
01004 }
01005
01007 template<class X, class Y>
01008 void usmv (const field_type& alpha, const X& x, Y& y) const
01009 {
01010 #ifdef DUNE_ISTL_WITH_CHECKING
01011 if (x.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01012 if (y.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01013 #endif
01014 ConstRowIterator endi=end();
01015 for (ConstRowIterator i=begin(); i!=endi; ++i)
01016 {
01017 ConstColIterator endj = (*i).end();
01018 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01019 (*j).usmv(alpha,x[j.index()],y[i.index()]);
01020 }
01021 }
01022
01024 template<class X, class Y>
01025 void umtv (const X& x, Y& y) const
01026 {
01027 #ifdef DUNE_ISTL_WITH_CHECKING
01028 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01029 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01030 #endif
01031 ConstRowIterator endi=end();
01032 for (ConstRowIterator i=begin(); i!=endi; ++i)
01033 {
01034 ConstColIterator endj = (*i).end();
01035 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01036 (*j).umtv(x[i.index()],y[j.index()]);
01037 }
01038 }
01039
01041 template<class X, class Y>
01042 void mmtv (const X& x, Y& y) const
01043 {
01044 #ifdef DUNE_ISTL_WITH_CHECKING
01045 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01046 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01047 #endif
01048 ConstRowIterator endi=end();
01049 for (ConstRowIterator i=begin(); i!=endi; ++i)
01050 {
01051 ConstColIterator endj = (*i).end();
01052 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01053 (*j).mmtv(x[i.index()],y[j.index()]);
01054 }
01055 }
01056
01058 template<class X, class Y>
01059 void usmtv (const field_type& alpha, const X& x, Y& y) const
01060 {
01061 #ifdef DUNE_ISTL_WITH_CHECKING
01062 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01063 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01064 #endif
01065 ConstRowIterator endi=end();
01066 for (ConstRowIterator i=begin(); i!=endi; ++i)
01067 {
01068 ConstColIterator endj = (*i).end();
01069 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01070 (*j).usmtv(alpha,x[i.index()],y[j.index()]);
01071 }
01072 }
01073
01075 template<class X, class Y>
01076 void umhv (const X& x, Y& y) const
01077 {
01078 #ifdef DUNE_ISTL_WITH_CHECKING
01079 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01080 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01081 #endif
01082 ConstRowIterator endi=end();
01083 for (ConstRowIterator i=begin(); i!=endi; ++i)
01084 {
01085 ConstColIterator endj = (*i).end();
01086 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01087 (*j).umhv(x[i.index()],y[j.index()]);
01088 }
01089 }
01090
01092 template<class X, class Y>
01093 void mmhv (const X& x, Y& y) const
01094 {
01095 #ifdef DUNE_ISTL_WITH_CHECKING
01096 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01097 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01098 #endif
01099 ConstRowIterator endi=end();
01100 for (ConstRowIterator i=begin(); i!=endi; ++i)
01101 {
01102 ConstColIterator endj = (*i).end();
01103 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01104 (*j).mmhv(x[i.index()],y[j.index()]);
01105 }
01106 }
01107
01109 template<class X, class Y>
01110 void usmhv (const field_type& alpha, const X& x, Y& y) const
01111 {
01112 #ifdef DUNE_ISTL_WITH_CHECKING
01113 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
01114 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
01115 #endif
01116 ConstRowIterator endi=end();
01117 for (ConstRowIterator i=begin(); i!=endi; ++i)
01118 {
01119 ConstColIterator endj = (*i).end();
01120 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01121 (*j).usmhv(alpha,x[i.index()],y[j.index()]);
01122 }
01123 }
01124
01125
01126
01127
01129 double frobenius_norm2 () const
01130 {
01131 double sum=0;
01132
01133 ConstRowIterator endi=end();
01134 for (ConstRowIterator i=begin(); i!=endi; ++i)
01135 {
01136 ConstColIterator endj = (*i).end();
01137 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01138 sum += (*j).frobenius_norm2();
01139 }
01140
01141 return sum;
01142 }
01143
01145 double frobenius_norm () const
01146 {
01147 return sqrt(frobenius_norm2());
01148 }
01149
01151 double infinity_norm () const
01152 {
01153 double max=0;
01154 ConstRowIterator endi=end();
01155 for (ConstRowIterator i=begin(); i!=endi; ++i)
01156 {
01157 double sum=0;
01158 ConstColIterator endj = (*i).end();
01159 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01160 sum += (*j).infinity_norm();
01161 max = std::max(max,sum);
01162 }
01163 return max;
01164 }
01165
01167 double infinity_norm_real () const
01168 {
01169 double max=0;
01170 ConstRowIterator endi=end();
01171 for (ConstRowIterator i=begin(); i!=endi; ++i)
01172 {
01173 double sum=0;
01174 ConstColIterator endj = (*i).end();
01175 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
01176 sum += (*j).infinity_norm_real();
01177 max = std::max(max,sum);
01178 }
01179 return max;
01180 }
01181
01182
01183
01184
01186 size_type N () const
01187 {
01188 return n;
01189 }
01190
01192 size_type M () const
01193 {
01194 return m;
01195 }
01196
01198 size_type nonzeroes () const
01199 {
01200 return nnz;
01201 }
01202
01203
01204
01205
01207 bool exists (size_type i, size_type j) const
01208 {
01209 #ifdef DUNE_ISTL_WITH_CHECKING
01210 if (i<0 || i>=n) DUNE_THROW(ISTLError,"index out of range");
01211 if (j<0 || i>=m) DUNE_THROW(ISTLError,"index out of range");
01212 #endif
01213 if (r[i].size() && r[i].find(j)!=r[i].end())
01214 return true;
01215 else
01216 return false;
01217 }
01218
01219
01220 private:
01221
01222 BuildMode build_mode;
01223 BuildStage ready;
01224
01225
01226 size_type n;
01227 size_type m;
01228 size_type nnz;
01229
01230
01231
01232 row_type* r;
01233
01234
01235 B* a;
01236 size_type* j;
01237
01238 void setWindowPointers(ConstRowIterator row)
01239 {
01240 row_type current_row(a,j,0);
01241 for (size_type i=0; i<n; i++, ++row){
01242
01243 size_type s = row->getsize();
01244
01245 if (s>0){
01246
01247 r[i].set(s,current_row.getptr(), current_row.getindexptr());
01248
01249 current_row.setptr(current_row.getptr()+s);
01250 current_row.setindexptr(current_row.getindexptr()+s);
01251 } else{
01252
01253 r[i].set(0,0,0);
01254 }
01255 }
01256 }
01257
01259 void copyWindowStructure(const BCRSMatrix& Mat)
01260 {
01261 setWindowPointers(Mat.begin());
01262
01263
01264 for (size_type i=0; i<n; i++) r[i] = Mat.r[i];
01265
01266
01267 build_mode = row_wise;
01268 ready = built;
01269 }
01270
01276 void deallocate(bool deallocateRows=true)
01277 {
01278
01279 if (nnz>0)
01280 {
01281
01282 A::template free<size_type>(j);
01283 A::template free<B>(a);
01284 }
01285 else
01286 {
01287
01288 for (size_type i=0; i<n; i++)
01289 if (r[i].getsize()>0)
01290 {
01291 A::template free<size_type>(r[i].getindexptr());
01292 A::template free<B>(r[i].getptr());
01293 }
01294 }
01295
01296
01297 if (n>0 && deallocateRows) A::template free<row_type>(r);
01298
01299
01300 ready=notbuilt;
01301
01302 }
01303
01321 void allocate(size_type rows, size_type columns, size_type nnz_=0, bool allocateRows=true)
01322 {
01323
01324 n = rows;
01325 m = columns;
01326 nnz = nnz_;
01327
01328
01329 if(allocateRows){
01330 if (n>0){
01331 r = A::template malloc<row_type>(rows);
01332 }else{
01333 r = 0;
01334 }
01335 }
01336
01337
01338
01339 if (nnz>0){
01340 a = A::template malloc<B>(nnz);
01341 j = A::template malloc<size_type>(nnz);
01342 }else{
01343 a = 0;
01344 j = 0;
01345 }
01346
01347 ready = notbuilt;
01348 }
01349
01350 };
01351
01352
01353 #ifdef DUNE_EXPRESSIONTEMPLATES
01354 template <class B, class A>
01355 struct FieldType< BCRSMatrix<B,A> >
01356 {
01357 typedef typename FieldType<B>::type type;
01358 };
01359
01360 template <class B, class A>
01361 struct BlockType< BCRSMatrix<B,A> >
01362 {
01363 typedef B type;
01364 };
01365 template <class B, class A>
01366 struct RowType< BCRSMatrix<B,A> >
01367 {
01368 typedef CompressedBlockVectorWindow<B,A> type;
01369 };
01370 #endif
01371
01374 }
01375
01376 #endif