bcrsmatrix.hh

Go to the documentation of this file.
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         //===== type definitions and constants
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         //===== random access interface to rows of the matrix
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         //===== iterator interface to rows of the matrix
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         //===== constructors & resizers
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           // deep copy in global array
00471           size_type _nnz = Mat.nnz;
00472 
00473           // in case of row-wise allocation
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           // build window structure
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       // deallocate already setup memory
00523       deallocate();
00524       
00525       // allocate matrix memory
00526       allocate(rows, columns, nnz);
00527     }
00528     
00530     BCRSMatrix& operator= (const BCRSMatrix& Mat)
00531     {
00532       // return immediately when self-assignment
00533       if (&Mat==this) return *this;
00534       
00535       // make it simple: ALWAYS throw away memory for a and j
00536       deallocate(false);
00537       
00538       // reallocate the rows if required
00539       if (n>0 && n!=Mat.n)
00540         // free rows
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       // allocate a,j
00551       allocate(Mat.n, Mat.m, nnz, n!=Mat.n);
00552       
00553       // build window structure
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         //===== row-wise creation interface 
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                 // this should only be called if matrix is in creation
00590                 if (Mat.ready)
00591                   DUNE_THROW(ISTLError,"matrix already built up");
00592 
00593                 // row i is defined through the pattern
00594                 // get memory for the row and initialize the j array
00595                 // this depends on the allocation mode
00596 
00597                 // compute size of the row
00598                 size_type s = pattern.size();
00599 
00600                 if(s>0){                  
00601                   // update number of nonzeroes including this row
00602                   nnz += s;
00603                   
00604                   // alloc memory / set window
00605                   if (Mat.nnz>0)
00606                     {
00607                       // memory is allocated in one long array
00608 
00609                       // check if that memory is sufficient
00610                       if (nnz>Mat.nnz) 
00611                         DUNE_THROW(ISTLError,"allocated nnz too small");
00612                       
00613                       // set row i
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                       // memory is allocated individually per row
00619                       // allocate and set row i
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                   // setup empty row
00626                   Mat.r[i].set(0,0,0);
00627 
00628                 // initialize the j array for row i from pattern
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                 // now go to next row
00635         i++;
00636                 pattern.clear();
00637 
00638                 // check if this was last row
00639                 if (i==Mat.n)
00640                   {
00641                         Mat.ready = built;
00642                         if(Mat.nnz>0)
00643                           // Set nnz to the exact number of nonzero blocks inserted
00644                           // as some methods rely on it
00645                           Mat.nnz=nnz;
00646                   }
00647                 // done
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; // the matrix we are defining
00695           size_type i;           // current row to be defined 
00696           size_type nnz;         // count total number of nonzeros
00697           typedef std::set<size_type,std::less<size_type>,PoolAllocator<size_type,10> > PatternType;
00698           PatternType pattern; // used to compile entries in a row
00699           row_type current_row; // row poiting to the current row to setup
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         //===== random creation interface 
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           // compute total size, check positivity
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             // allocate/check memory
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           // set the window pointers correctly
00777           setWindowPointers(begin());
00778           
00779           // initialize j array with m (an invalid column index)
00780           // this indicates an unused entry
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           // get row range
00810           size_type* const first = r[row].getindexptr();
00811           size_type* const last = first + r[row].getsize();
00812 
00813           // find correct insertion position for new column index
00814           size_type* pos = std::lower_bound(first,last,col);
00815 
00816           // check if index is already in row
00817           if (pos!=last && *pos == col) return;
00818 
00819           // find end of already inserted column indices
00820           size_type* end = std::lower_bound(pos,last,m);
00821           if (end==last)
00822             DUNE_THROW(ISTLError,"row is too small");
00823 
00824           // insert new column index at correct position
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           // check if there are undefined indices
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           // if not, set matrix to built
00861           ready = built;
00862         }
00863 
00864         //===== vector space arithmetic
00865 
00867         BCRSMatrix& operator*= (const field_type& k)
00868         {
00869           if (nnz>0)
00870                 {
00871                   // process 1D array
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                   // process 1D array
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         //===== linear maps
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         //===== norms
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         //===== sizes
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         //===== query
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         // state information
01222         BuildMode build_mode; // row wise or whole matrix
01223         BuildStage ready;           // indicate the stage the matrix building is in
01224 
01225         // size of the matrix
01226         size_type  n;  // number of rows
01227         size_type  m;  // number of columns
01228         size_type nnz; // number of nonzeros allocated in the a and j array below
01229              // zero means that memory is allocated separately for each row.
01230 
01231         // the rows are dynamically allocated
01232         row_type* r; // [n] the individual rows having pointers into a,j arrays
01233 
01234         // dynamically allocated memory
01235         B*   a;  // [nnz] non-zero entries of the matrix in row-wise ordering
01236         size_type* j;  // [nnz] column indices of entries
01237 
01238     void setWindowPointers(ConstRowIterator row)
01239     {
01240       row_type current_row(a,j,0); // Pointers to current row data
01241       for (size_type i=0; i<n; i++, ++row){               
01242         // set row i
01243         size_type s = row->getsize();
01244         
01245         if (s>0){
01246           // setup pointers and size
01247           r[i].set(s,current_row.getptr(), current_row.getindexptr());
01248           // update pointer for next row
01249           current_row.setptr(current_row.getptr()+s);
01250           current_row.setindexptr(current_row.getindexptr()+s);
01251         } else{
01252           // empty row
01253           r[i].set(0,0,0);
01254         }
01255       }
01256     }
01257     
01259     void copyWindowStructure(const BCRSMatrix& Mat)
01260     {
01261       setWindowPointers(Mat.begin());
01262             
01263       // copy data
01264       for (size_type i=0; i<n; i++) r[i] = Mat.r[i];
01265 
01266       // finish off
01267       build_mode = row_wise; // dummy
01268       ready = built;
01269     }
01270   
01276     void deallocate(bool deallocateRows=true)
01277     {
01278       
01279       if (nnz>0)
01280         {
01281           // a,j have been allocated as one long vector
01282           A::template free<size_type>(j); 
01283           A::template free<B>(a); 
01284         }
01285       else
01286         {
01287           // check if memory for rows have been allocated individually
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       // deallocate the rows
01297       if (n>0 && deallocateRows) A::template free<row_type>(r); 
01298       
01299       // Mark matrix as not built at all.
01300       ready=notbuilt;
01301       
01302     }
01303     
01321     void allocate(size_type rows, size_type columns, size_type nnz_=0, bool allocateRows=true)
01322     {
01323       // Store size
01324       n = rows;
01325       m = columns;
01326       nnz = nnz_;
01327 
01328       // allocate rows
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       // allocate a and j array
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       // Mark the matrix as not built.
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 } // end namespace
01375 
01376 #endif

Generated on Sun Nov 15 22:29:35 2009 for dune-istl by  doxygen 1.5.6