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
00014
00015
00016
00017
00018
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
00168
00169
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
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 );
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