coeffmatrix.hh

Go to the documentation of this file.
00001 #ifndef DUNE_COEFFMATRIX_HH
00002 #define DUNE_COEFFMATRIX_HH
00003 #include <cassert>
00004 #include <iostream>
00005 #include <vector>
00006 #include <dune/common/fvector.hh>
00007 #include <dune/localfunctions/utility/field.hh>
00008 #include <dune/localfunctions/utility/tensor.hh>
00009 
00010 namespace Dune 
00011 {
00012   /*************************************************
00013    * Default class for storing a coefficient matrix
00014    * for the PolynomialBasis. Basically a simple
00015    * CRS structure is used. The additional complexity
00016    * is due to the storage and efficient evaluation
00017    * of higher order derivatives. See the remarks
00018    * in tensor.hh which also hold true for this file.
00019    *************************************************/
00020   template <class Field, class Field2>
00021   struct Mult 
00022   {
00023     typedef Field2 BasisEntry;
00024     static void add(const Field &vec1, const BasisEntry &vec2,
00025                     BasisEntry &res) 
00026     {
00027       res += vec1*vec2;
00028     }
00029   };
00030 
00031   template <class Field,class Field2, int dimRange>
00032   struct Mult< Field,FieldVector<Field2,dimRange> > 
00033   {
00034     typedef FieldVector<Field2,dimRange> BasisEntry;
00035     static void add(const Field &vec1, const BasisEntry &vec2,
00036                     BasisEntry &res) 
00037     {
00038       res.axpy(vec1,vec2);
00039     }
00040   };
00041 
00042   template< class F , unsigned int bSize >
00043   class SparseCoeffMatrix
00044   {
00045   public:
00046     typedef F Field;
00047     static const unsigned int blockSize = bSize;
00048     typedef SparseCoeffMatrix<Field,blockSize> This;
00049 
00050     SparseCoeffMatrix() 
00051     : coeff_(0),
00052       rows_(0),
00053       skip_(0),
00054       numRows_(0),
00055       numCols_(0)
00056     {}
00057 
00058     ~SparseCoeffMatrix()
00059     {
00060       delete [] coeff_;
00061       delete [] rows_;
00062       delete [] skip_;
00063     }
00064 
00065     const unsigned int size () const
00066     {
00067       return numRows_/blockSize;
00068     }
00069     const unsigned int baseSize () const
00070     {
00071       return numCols_;
00072     }
00073 
00074     template< class BasisIterator, class FF>
00075     void mult ( const BasisIterator &x, 
00076                 unsigned int numLsg,
00077                 FF *y ) const
00078     {
00079       typedef typename BasisIterator::Derivatives XDerivatives;
00080       assert( numLsg*blockSize <= (size_t)numRows_ );
00081       unsigned int row = 0;
00082       Field *pos = rows_[ 0 ];
00083       unsigned int *skipIt = skip_;
00084       XDerivatives val;
00085       for( size_t i = 0; i < numLsg; ++i)
00086       {
00087         for( unsigned int r = 0; r < blockSize; ++r, ++row )
00088         {
00089           val = 0;
00090           BasisIterator itx = x;
00091           for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt )
00092           {
00093             itx += *skipIt;
00094             val.axpy(*pos,*itx);
00095           }
00096           DerivativeAssign<XDerivatives,FF>::apply(r,val,*(y+i*XDerivatives::size*blockSize));
00097         }
00098       }
00099     }
00100     template< class BasisIterator, class Vector>
00101     void mult ( const BasisIterator &x, 
00102                 Vector &y ) const
00103     {
00104       typedef typename Vector::value_type YDerivatives;
00105       typedef typename BasisIterator::Derivatives XDerivatives;
00106       size_t numLsg = y.size();
00107       assert( numLsg*blockSize <= (size_t)numRows_ );
00108       unsigned int row = 0;
00109       Field *pos = rows_[ 0 ];
00110       unsigned int *skipIt = skip_;
00111       XDerivatives val;
00112       for( size_t i = 0; i < numLsg; ++i)
00113       {
00114         for( unsigned int r = 0; r < blockSize; ++r, ++row )
00115         {
00116           val = 0;
00117           BasisIterator itx = x;
00118           for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt )
00119           {
00120             itx += *skipIt;
00121             val.axpy(*pos,*itx);
00122           }
00123           DerivativeAssign<XDerivatives,YDerivatives>::apply(r,val,y[i]);
00124         }
00125       }
00126     }
00127     template <unsigned int deriv, class BasisIterator, class Vector>
00128     void mult ( const BasisIterator &x, 
00129                 Vector &y ) const
00130     { 
00131       typedef typename Vector::value_type YDerivatives;
00132       typedef typename BasisIterator::Derivatives XDerivatives;
00133       typedef FieldVector<typename XDerivatives::Field,YDerivatives::size> XLFETensor;
00134       size_t numLsg = y.size();
00135       assert( numLsg*blockSize <= (size_t)numRows_ );
00136       unsigned int row = 0;
00137       Field *pos = rows_[ 0 ];
00138       unsigned int *skipIt = skip_;
00139       for( size_t i = 0; i < numLsg; ++i)
00140       {
00141         XLFETensor val(typename XDerivatives::Field(0));
00142         for( unsigned int r = 0; r < blockSize; ++r, ++row )
00143         {
00144           BasisIterator itx = x;
00145           for( ; pos != rows_[ row+1 ]; ++pos, ++skipIt )
00146           {
00147             itx += *skipIt;
00148             LFETensorAxpy<XDerivatives,XLFETensor,deriv>::apply(r,*pos,*itx,val);
00149           }
00150         }
00151         field_cast(val,y[i]);
00152       }
00153     }
00154 
00155     template< class RowMatrix >
00156     void fill ( const RowMatrix &mat, bool verbose=false )
00157     {
00158       numRows_ = mat.rows();
00159       numCols_ = mat.cols();
00160       unsigned int size = numRows_*numCols_;
00161 
00162       delete [] coeff_;
00163       delete [] rows_;
00164       delete [] skip_;
00165 
00166       Field* coeff = new Field[ size ];
00167       // we always initialize the next skip entry to zero,
00168       // including the one following the end, so allocate
00169       // size+1 entries so we will stay within the bounds.
00170       unsigned int *skip = new unsigned int[ size+1 ];
00171       rows_ = new Field*[ numRows_+1 ];
00172       std::vector<Field> row( numCols_ );
00173 
00174       rows_[ 0 ] = coeff;
00175       Field *cit = coeff;
00176       unsigned int *sit = skip;
00177       for( unsigned int r = 0; r < numRows_; ++r )
00178       {
00179         *sit = 0;
00180         mat.row( r, row );
00181         for( unsigned int c = 0; c < numCols_; ++c ) 
00182         {
00183           const Field &val = row[c];
00184           if (val < Zero<Field>() || Zero<Field>() < val) 
00185           {
00186             *cit = val;
00187             ++sit;
00188             ++cit;
00189             *sit = 1;
00190           } else
00191           {
00192             ++(*sit);
00193           }
00194         }
00195         rows_[ r+1 ] = cit;
00196       }
00197       assert( size_t(rows_[numRows_]-rows_[0]) <= size_t(size) );
00198       size = rows_[numRows_]-rows_[0];
00199       coeff_ = new Field[ size ];
00200       skip_ = new unsigned int[ size ];
00201       for (unsigned int i=0;i<size;++i)
00202       {
00203         coeff_[i] = coeff[i];
00204         skip_[i] = skip[i];
00205       }
00206       for (unsigned int i=0;i<=numRows_;++i)
00207         rows_[ i ] = coeff_ + (rows_[ i ] - coeff);
00208       
00209       delete [] coeff;
00210       delete [] skip;
00211 
00212       if (verbose)
00213         std::cout << "Entries: " << (rows_[numRows_]-rows_[0]) 
00214                   << " full: " << numCols_*numRows_
00215                   << std::endl;
00216     }
00217     // b += a*C[k]
00218     template <class Vector>
00219     void addRow( unsigned int k, const Field &a, Vector &b) const
00220     {
00221       assert(k<numRows_);
00222       unsigned int j=0;
00223       unsigned int *skipIt = skip_ + (rows_[ k ]-rows_[ 0 ]);
00224       for( Field *pos = rows_[ k ]; 
00225            pos != rows_[ k+1 ]; 
00226            ++pos, ++skipIt )
00227       {
00228         j += *skipIt;
00229         assert( j < b.size() );
00230         b[j] += field_cast<typename Vector::value_type>( (*pos)*a );  // field_cast
00231       }
00232     }
00233   private:
00234     SparseCoeffMatrix ( const This &other )
00235     : numRows_( other.numRows_ ),
00236       numCols_( other.numCols_ )
00237     {
00238       const unsigned int size = other.rows_[numRows_]-other.rows_[0];
00239       coeff_ = new Field[ size ];
00240       rows_ = new Field*[ numRows_+1 ];
00241       skip_ = new unsigned int[ size ];
00242       for (unsigned int i=0;i<size;++i)
00243       {
00244         coeff_[i] = other.coeff_[i];
00245         skip_[i] = other.skip_[i];
00246       }
00247       for (unsigned int i=0;i<=numRows_;++i)
00248         rows_[ i ] = coeff_ + (other.rows_[ i ] - other.coeff_);
00249     }
00250 
00251     This &operator= (const This&); 
00252     Field *coeff_;
00253     Field **rows_;
00254     unsigned int *skip_;
00255     unsigned int numRows_,numCols_;
00256   };
00257 
00258 }
00259 
00260 #endif // DUNE_COEFFMATRIX_HH
00261 
Generated on Sat Apr 24 11:15:33 2010 for dune-localfunctions by  doxygen 1.6.3