00001 #ifndef DUNE_MATRIX_HH
00002 #define DUNE_MATRIX_HH
00003
00008 #include <vector>
00009 #include <dune/istl/bvector.hh>
00010
00011 namespace Dune {
00012
00022 template<class T, class A=ISTLAllocator>
00023 class Matrix
00024 {
00025 public:
00026
00028 typedef typename T::field_type field_type;
00029
00031 typedef T block_type;
00032
00034 typedef A allocator_type;
00035
00037 typedef BlockVector<T> row_type;
00038
00040 typedef typename A::size_type size_type;
00041
00043 typedef typename BlockVector<row_type>::iterator RowIterator;
00044
00046 typedef typename row_type::iterator ColIterator;
00047
00049 typedef typename BlockVector<row_type>::const_iterator ConstRowIterator;
00050
00052 typedef typename row_type::const_iterator ConstColIterator;
00053
00054 enum {
00056 blocklevel = T::blocklevel+1
00057 };
00058
00060 Matrix() : data_(0), cols_(0)
00061 {}
00062
00065 Matrix(size_type rows, size_type cols) : data_(rows), cols_(cols)
00066 {
00067 for (size_type i=0; i<rows; i++)
00068 data_[i].resize(cols);
00069 }
00070
00075 void setSize(size_type rows, size_type cols) {
00076 data_.resize(rows);
00077 for (size_type i=0; i<rows; i++)
00078 data_[i].resize(cols);
00079 cols_ = cols;
00080 }
00081
00083 RowIterator begin()
00084 {
00085 return data_.begin();
00086 }
00087
00089 RowIterator end()
00090 {
00091 return data_.end();
00092 }
00093
00095 RowIterator rbegin()
00096 {
00097 return data_.rbegin();
00098 }
00099
00101 RowIterator rend()
00102 {
00103 return data_.rend();
00104 }
00105
00107 ConstRowIterator begin() const
00108 {
00109 return data_.begin();
00110 }
00111
00113 ConstRowIterator end() const
00114 {
00115 return data_.end();
00116 }
00117
00119 ConstRowIterator rbegin() const
00120 {
00121 return data_.rbegin();
00122 }
00123
00125 ConstRowIterator rend() const
00126 {
00127 return data_.rend();
00128 }
00129
00131 Matrix& operator= (const field_type& t)
00132 {
00133 typedef typename BlockVector<row_type,allocator_type>::size_type
00134 size_type;
00135
00136 for (size_type i=0; i<data_.size(); i++)
00137 data_[i] = t;
00138 return *this;
00139 }
00140
00142 row_type& operator[](size_type row) {
00143 #ifdef DUNE_ISTL_WITH_CHECKING
00144 if (row<0)
00145 DUNE_THROW(ISTLError, "Can't access negative rows!");
00146 if (row>=N())
00147 DUNE_THROW(ISTLError, "Row index out of range!");
00148 #endif
00149 return data_[row];
00150 }
00151
00153 const row_type& operator[](size_type row) const {
00154 #ifdef DUNE_ISTL_WITH_CHECKING
00155 if (row<0)
00156 DUNE_THROW(ISTLError, "Can't access negative rows!");
00157 if (row>=N())
00158 DUNE_THROW(ISTLError, "Row index out of range!");
00159 #endif
00160 return data_[row];
00161 }
00162
00164 size_type N() const {
00165 return data_.size();
00166 }
00167
00169 size_type M() const {
00170 return cols_;
00171 }
00172
00174 size_type rowdim() const {
00175 #ifdef DUNE_ISTL_WITH_CHECKING
00176 if (M()==0)
00177 DUNE_THROW(ISTLError, "Can't compute rowdim() when there are no columns!");
00178 #endif
00179 size_type dim = 0;
00180 for (size_type i=0; i<data_.size(); i++)
00181 dim += data_[i][0].rowdim();
00182
00183 return dim;
00184 }
00185
00187 size_type coldim() const {
00188 #ifdef DUNE_ISTL_WITH_CHECKING
00189 if (N()==0)
00190 DUNE_THROW(ISTLError, "Can't compute coldim() when there are no rows!");
00191 #endif
00192 size_type dim = 0;
00193 for (size_type i=0; i<data_[0].size(); i++)
00194 dim += data_[0][i].coldim();
00195
00196 return dim;
00197 }
00198
00200 size_type rowdim(size_type r) const {
00201 #ifdef DUNE_ISTL_WITH_CHECKING
00202 if (r<0 || r>=N())
00203 DUNE_THROW(ISTLError, "Rowdim for nonexisting row " << r << " requested!");
00204 if (M()==0)
00205 DUNE_THROW(ISTLError, "Can't compute rowdim() when there are no columns!");
00206 #endif
00207 return data_[r][0].rowdim();
00208 }
00209
00211 size_type coldim(size_type c) const {
00212 #ifdef DUNE_ISTL_WITH_CHECKING
00213 if (c<0 || c>=M())
00214 DUNE_THROW(ISTLError, "Coldim for nonexisting column " << c << " requested!");
00215 if (N()==0)
00216 DUNE_THROW(ISTLError, "Can't compute coldim() when there are no rows!");
00217 #endif
00218 return data_[0][c].coldim();
00219 }
00220
00222 Matrix<T>& operator*=(const field_type& scalar) {
00223 for (size_type row=0; row<data_.size(); row++)
00224 for (size_type col=0; col<cols_; col++)
00225 (*this)[row][col] *= scalar;
00226
00227 return (*this);
00228 }
00229
00231 Matrix<T>& operator/=(const field_type& scalar) {
00232 for (size_type row=0; row<data_.size(); row++)
00233 for (size_type col=0; col<cols_; col++)
00234 (*this)[row][col] /= scalar;
00235
00236 return (*this);
00237 }
00238
00244 Matrix& operator+= (const Matrix& b) {
00245 #ifdef DUNE_ISTL_WITH_CHECKING
00246 if(N()!=b.N() || M() != b.M())
00247 DUNE_THROW(RangeError, "Matrix sizes do not match!");
00248 #endif
00249 for (size_type row=0; row<data_.size(); row++)
00250 (*this)[row] += b[row];
00251
00252 return (*this);
00253 }
00254
00260 Matrix& operator-= (const Matrix& b) {
00261 #ifdef DUNE_ISTL_WITH_CHECKING
00262 if(N()!=b.N() || M() != b.M())
00263 DUNE_THROW(RangeError, "Matrix sizes do not match!");
00264 #endif
00265 for (size_type row=0; row<data_.size(); row++)
00266 (*this)[row] -= b[row];
00267
00268 return (*this);
00269 }
00270
00272 Matrix transpose() const {
00273 Matrix out(N(), M());
00274 for (size_type i=0; i<M(); i++)
00275 for (size_type j=0; j<N(); j++)
00276 out[j][i] = (*this)[i][j];
00277
00278 return out;
00279 }
00280
00282 template <class X, class Y>
00283 Y transposedMult(const X& vec) {
00284 #ifdef DUNE_ISTL_WITH_CHECKING
00285 if (N()!=vec.size())
00286 DUNE_THROW(ISTLError, "Vector size doesn't match the number of matrix rows!");
00287 #endif
00288 Y out(M());
00289 out = 0;
00290
00291 for (size_type i=0; i<out.size(); i++ ) {
00292 for ( size_type j=0; j<vec.size(); j++ )
00293 out[i] += (*this)[j][i]*vec[j];
00294 }
00295
00296 return out;
00297 }
00298
00300 friend Matrix<T> operator*(const Matrix<T>& m1, const Matrix<T>& m2) {
00301 Matrix<T> out(m1.N(), m2.M());
00302 out.clear();
00303
00304 for (size_type i=0; i<out.N(); i++ ) {
00305 for ( size_type j=0; j<out.M(); j++ )
00306 for (size_type k=0; k<m1.M(); k++)
00307 out[i][j] += m1[i][k]*m2[k][j];
00308 }
00309
00310 return out;
00311 }
00312
00314 template <class X, class Y>
00315 friend Y operator*(const Matrix<T>& m, const X& vec) {
00316 #ifdef DUNE_ISTL_WITH_CHECKING
00317 if (M()!=vec.size())
00318 DUNE_THROW(ISTLError, "Vector size doesn't match the number of matrix columns!");
00319 #endif
00320 Y out(m.N());
00321 out = 0;
00322
00323 for (size_type i=0; i<out.size(); i++ ) {
00324 for ( size_type j=0; j<vec.size(); j++ )
00325 out[i] += m[i][j]*vec[j];
00326 }
00327
00328 return out;
00329 }
00330
00332 template <class X, class Y>
00333 void mv(const X& x, Y& y) const
00334 {
00335 #ifdef DUNE_ISTL_WITH_CHECKING
00336 if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00337 if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00338 #endif
00339
00340 for (size_type i=0; i<data_.size(); i++) {
00341 y[i]=0;
00342 for (size_type j=0; j<cols_; j++)
00343 (*this)[i][j].umv(x[j], y[i]);
00344
00345 }
00346
00347 }
00348
00350 template<class X, class Y>
00351 void mtv (const X& x, Y& y) const
00352 {
00353 #ifdef DUNE_ISTL_WITH_CHECKING
00354 if (x.N()!=N()) DUNE_THROW(ISTLError,"index out of range");
00355 if (y.N()!=M()) DUNE_THROW(ISTLError,"index out of range");
00356 #endif
00357
00358 for(size_type i=0; i<y.N(); ++i)
00359 y[i]=0;
00360 umtv(x,y);
00361 }
00362
00364 template <class X, class Y>
00365 void umv(const X& x, Y& y) const
00366 {
00367 #ifdef DUNE_ISTL_WITH_CHECKING
00368 if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00369 if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00370 #endif
00371
00372 for (size_type i=0; i<data_.size(); i++) {
00373
00374 for (size_type j=0; j<cols_; j++)
00375 (*this)[i][j].umv(x[j], y[i]);
00376
00377 }
00378
00379 }
00380
00382 template<class X, class Y>
00383 void mmv (const X& x, Y& y) const
00384 {
00385 #ifdef DUNE_ISTL_WITH_CHECKING
00386 if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00387 if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00388 #endif
00389 ConstRowIterator endi=end();
00390 for (ConstRowIterator i=begin(); i!=endi; ++i)
00391 {
00392 ConstColIterator endj = (*i).end();
00393 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00394 (*j).mmv(x[j.index()],y[i.index()]);
00395 }
00396 }
00397
00399 template <class X, class Y>
00400 void usmv(const field_type& alpha, const X& x, Y& y) const
00401 {
00402 #ifdef DUNE_ISTL_WITH_CHECKING
00403 if (x.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00404 if (y.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00405 #endif
00406
00407 for (size_type i=0; i<data_.size(); i++) {
00408
00409 for (size_type j=0; j<cols_; j++)
00410 (*this)[i][j].usmv(alpha, x[j], y[i]);
00411
00412 }
00413
00414 }
00415
00417 template<class X, class Y>
00418 void umtv (const X& x, Y& y) const
00419 {
00420 #ifdef DUNE_ISTL_WITH_CHECKING
00421 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00422 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00423 #endif
00424 ConstRowIterator endi=end();
00425 for (ConstRowIterator i=begin(); i!=endi; ++i)
00426 {
00427 ConstColIterator endj = (*i).end();
00428 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00429 (*j).umtv(x[i.index()],y[j.index()]);
00430 }
00431 }
00432
00434 template<class X, class Y>
00435 void mmtv (const X& x, Y& y) const
00436 {
00437 #ifdef DUNE_ISTL_WITH_CHECKING
00438 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00439 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00440 #endif
00441 ConstRowIterator endi=end();
00442 for (ConstRowIterator i=begin(); i!=endi; ++i)
00443 {
00444 ConstColIterator endj = (*i).end();
00445 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00446 (*j).mmtv(x[i.index()],y[j.index()]);
00447 }
00448 }
00449
00451 template<class X, class Y>
00452 void usmtv (const field_type& alpha, const X& x, Y& y) const
00453 {
00454 #ifdef DUNE_ISTL_WITH_CHECKING
00455 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00456 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00457 #endif
00458 ConstRowIterator endi=end();
00459 for (ConstRowIterator i=begin(); i!=endi; ++i)
00460 {
00461 ConstColIterator endj = (*i).end();
00462 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00463 (*j).usmtv(alpha,x[i.index()],y[j.index()]);
00464 }
00465 }
00466
00468 template<class X, class Y>
00469 void umhv (const X& x, Y& y) const
00470 {
00471 #ifdef DUNE_ISTL_WITH_CHECKING
00472 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00473 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00474 #endif
00475 ConstRowIterator endi=end();
00476 for (ConstRowIterator i=begin(); i!=endi; ++i)
00477 {
00478 ConstColIterator endj = (*i).end();
00479 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00480 (*j).umhv(x[i.index()],y[j.index()]);
00481 }
00482 }
00483
00485 template<class X, class Y>
00486 void mmhv (const X& x, Y& y) const
00487 {
00488 #ifdef DUNE_ISTL_WITH_CHECKING
00489 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00490 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00491 #endif
00492 ConstRowIterator endi=end();
00493 for (ConstRowIterator i=begin(); i!=endi; ++i)
00494 {
00495 ConstColIterator endj = (*i).end();
00496 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00497 (*j).mmhv(x[i.index()],y[j.index()]);
00498 }
00499 }
00500
00502 template<class X, class Y>
00503 void usmhv (const field_type& alpha, const X& x, Y& y) const
00504 {
00505 #ifdef DUNE_ISTL_WITH_CHECKING
00506 if (x.N()!=N()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00507 if (y.N()!=M()) DUNE_THROW(ISTLError,"vector/matrix size mismatch!");
00508 #endif
00509 ConstRowIterator endi=end();
00510 for (ConstRowIterator i=begin(); i!=endi; ++i)
00511 {
00512 ConstColIterator endj = (*i).end();
00513 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
00514 (*j).usmhv(alpha,x[i.index()],y[j.index()]);
00515 }
00516 }
00517
00518
00519
00521 double frobenius_norm () const
00522 {
00523 return std::sqrt(frobenius_norm2());
00524 }
00525
00527 double frobenius_norm2 () const
00528 {
00529 double sum=0;
00530 for (size_type i=0; i<N(); ++i)
00531 for (size_type j=0; j<M(); ++j)
00532 sum += data_[i][j].frobenius_norm2();
00533 return sum;
00534 }
00535
00537 double infinity_norm () const
00538 {
00539 double max=0;
00540 for (size_type i=0; i<N(); ++i) {
00541 double sum=0;
00542 for (size_type j=0; j<M(); j++)
00543 sum += data_[i][j].infinity_norm();
00544 max = std::max(max,sum);
00545 }
00546 return max;
00547 }
00548
00550 double infinity_norm_real () const
00551 {
00552 double max=0;
00553 for (size_type i=0; i<N(); ++i) {
00554 double sum=0;
00555 for (size_type j=0; j<M(); j++)
00556 sum += data_[i][j].infinity_norm_real();
00557 max = std::max(max,sum);
00558 }
00559 return max;
00560 }
00561
00562
00563
00565 bool exists (size_type i, size_type j) const
00566 {
00567 #ifdef DUNE_ISTL_WITH_CHECKING
00568 if (i<0 || i>=N()) DUNE_THROW(ISTLError,"row index out of range");
00569 if (j<0 || i>=M()) DUNE_THROW(ISTLError,"column index out of range");
00570 #endif
00571 return true;
00572 }
00573
00574 protected:
00575
00576 BlockVector<row_type, allocator_type> data_;
00577
00578 size_type cols_;
00579 };
00581 }
00582
00583 #endif