00001
00002 #ifndef DUNE_FMATRIX_HH
00003 #define DUNE_FMATRIX_HH
00004
00005 #include<cmath>
00006 #include<cstddef>
00007 #include<complex>
00008 #include<iostream>
00009 #include "exceptions.hh"
00010 #include "fvector.hh"
00011 #include "precision.hh"
00012
00013 namespace Dune {
00014
00026 template<class K, int n, int m> class FieldMatrix;
00027
00029 class FMatrixError : public Exception {};
00030
00031
00032 template<class K>
00033 inline K fm_ck (const K& k)
00034 {
00035 return k;
00036 }
00037
00038
00039 template<class K>
00040 inline std::complex<K> fm_ck (const std::complex<K>& c)
00041 {
00042 return std::complex<K>(c.real(),-c.imag());
00043 }
00044
00055 template<class K, int n, int m>
00056 class FieldMatrix
00057 {
00058 public:
00059
00060
00061
00062
00064 typedef K field_type;
00065
00067 typedef K block_type;
00068
00070 typedef std::size_t size_type;
00071
00073 enum {
00075 blocklevel = 1
00076 };
00077
00079 typedef FieldVector<K,m> row_type;
00080
00082 enum {
00084 rows = n,
00086 cols = m
00087 };
00088
00089
00092 FieldMatrix () {}
00093
00096 FieldMatrix (const K& k)
00097 {
00098 for (size_type i=0; i<n; i++) p[i] = k;
00099 }
00100
00101
00102
00104 row_type& operator[] (size_type i)
00105 {
00106 #ifdef DUNE_FMatrix_WITH_CHECKING
00107 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00108 #endif
00109 return p[i];
00110 }
00111
00113 const row_type& operator[] (size_type i) const
00114 {
00115 #ifdef DUNE_FMatrix_WITH_CHECKING
00116 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00117 #endif
00118 return p[i];
00119 }
00120
00121
00122
00124 typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00126 typedef Iterator iterator;
00128 typedef Iterator RowIterator;
00130 typedef typename row_type::Iterator ColIterator;
00131
00133 Iterator begin ()
00134 {
00135 return Iterator(*this,0);
00136 }
00137
00139 Iterator end ()
00140 {
00141 return Iterator(*this,n);
00142 }
00143
00145 Iterator rbegin ()
00146 {
00147 return Iterator(*this,n-1);
00148 }
00149
00151 Iterator rend ()
00152 {
00153 return Iterator(*this,-1);
00154 }
00155
00157 typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00159 typedef ConstIterator const_iterator;
00161 typedef ConstIterator ConstRowIterator;
00163 typedef typename row_type::ConstIterator ConstColIterator;
00164
00166 ConstIterator begin () const
00167 {
00168 return ConstIterator(*this,0);
00169 }
00170
00172 ConstIterator end () const
00173 {
00174 return ConstIterator(*this,n);
00175 }
00176
00178 ConstIterator rbegin () const
00179 {
00180 return ConstIterator(*this,n-1);
00181 }
00182
00184 ConstIterator rend () const
00185 {
00186 return ConstIterator(*this,-1);
00187 }
00188
00189
00190 FieldMatrix& operator= (const K& k)
00191 {
00192 for (size_type i=0; i<n; i++)
00193 p[i] = k;
00194 return *this;
00195 }
00196
00197
00198
00200 FieldMatrix& operator+= (const FieldMatrix& y)
00201 {
00202 for (size_type i=0; i<n; i++)
00203 p[i] += y.p[i];
00204 return *this;
00205 }
00206
00208 FieldMatrix& operator-= (const FieldMatrix& y)
00209 {
00210 for (size_type i=0; i<n; i++)
00211 p[i] -= y.p[i];
00212 return *this;
00213 }
00214
00216 FieldMatrix& operator*= (const K& k)
00217 {
00218 for (size_type i=0; i<n; i++)
00219 p[i] *= k;
00220 return *this;
00221 }
00222
00224 FieldMatrix& operator/= (const K& k)
00225 {
00226 for (int i=0; i<n; i++)
00227 p[i] /= k;
00228 return *this;
00229 }
00230
00231
00232
00234 template<class X, class Y>
00235 void umv (const X& x, Y& y) const
00236 {
00237 #ifdef DUNE_FMatrix_WITH_CHECKING
00238 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00239 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00240 #endif
00241 for (size_type i=0; i<n; i++)
00242 for (size_type j=0; j<m; j++)
00243 y[i] += (*this)[i][j] * x[j];
00244 }
00245
00247 template<class X, class Y>
00248 void umtv (const X& x, Y& y) const
00249 {
00250 #ifdef DUNE_FMatrix_WITH_CHECKING
00251 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00252 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00253 #endif
00254
00255 for (size_type i=0; i<n; i++)
00256 for (size_type j=0; j<m; j++)
00257 y[j] += p[i][j]*x[i];
00258 }
00259
00261 template<class X, class Y>
00262 void umhv (const X& x, Y& y) const
00263 {
00264 #ifdef DUNE_FMatrix_WITH_CHECKING
00265 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00266 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00267 #endif
00268
00269 for (size_type i=0; i<n; i++)
00270 for (size_type j=0; j<m; j++)
00271 y[j] += fm_ck(p[i][j])*x[i];
00272 }
00273
00275 template<class X, class Y>
00276 void mmv (const X& x, Y& y) const
00277 {
00278 #ifdef DUNE_FMatrix_WITH_CHECKING
00279 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00280 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00281 #endif
00282 for (size_type i=0; i<n; i++)
00283 for (size_type j=0; j<m; j++)
00284 y[i] -= (*this)[i][j] * x[j];
00285 }
00286
00288 template<class X, class Y>
00289 void mmtv (const X& x, Y& y) const
00290 {
00291 #ifdef DUNE_FMatrix_WITH_CHECKING
00292 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00293 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00294 #endif
00295
00296 for (size_type i=0; i<n; i++)
00297 for (size_type j=0; j<m; j++)
00298 y[j] -= p[i][j]*x[i];
00299 }
00300
00302 template<class X, class Y>
00303 void mmhv (const X& x, Y& y) const
00304 {
00305 #ifdef DUNE_FMatrix_WITH_CHECKING
00306 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00307 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00308 #endif
00309
00310 for (size_type i=0; i<n; i++)
00311 for (size_type j=0; j<m; j++)
00312 y[j] -= fm_ck(p[i][j])*x[i];
00313 }
00314
00316 template<class X, class Y>
00317 void usmv (const K& alpha, const X& x, Y& y) const
00318 {
00319 #ifdef DUNE_FMatrix_WITH_CHECKING
00320 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00321 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00322 #endif
00323 for (size_type i=0; i<n; i++)
00324 for (size_type j=0; j<m; j++)
00325 y[i] += alpha * (*this)[i][j] * x[j];
00326 }
00327
00329 template<class X, class Y>
00330 void usmtv (const K& alpha, const X& x, Y& y) const
00331 {
00332 #ifdef DUNE_FMatrix_WITH_CHECKING
00333 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00334 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00335 #endif
00336
00337 for (size_type i=0; i<n; i++)
00338 for (size_type j=0; j<m; j++)
00339 y[j] += alpha*p[i][j]*x[i];
00340 }
00341
00343 template<class X, class Y>
00344 void usmhv (const K& alpha, const X& x, Y& y) const
00345 {
00346 #ifdef DUNE_FMatrix_WITH_CHECKING
00347 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00348 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00349 #endif
00350
00351 for (size_type i=0; i<n; i++)
00352 for (size_type j=0; j<m; j++)
00353 y[j] += alpha*fm_ck(p[i][j])*x[i];
00354 }
00355
00356
00357
00359 double frobenius_norm () const
00360 {
00361 double sum=0;
00362 for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00363 return sqrt(sum);
00364 }
00365
00367 double frobenius_norm2 () const
00368 {
00369 double sum=0;
00370 for (size_type i=0; i<n; ++i) sum += p[i].two_norm2();
00371 return sum;
00372 }
00373
00375 double infinity_norm () const
00376 {
00377 double max=0;
00378 for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm());
00379 return max;
00380 }
00381
00383 double infinity_norm_real () const
00384 {
00385 double max=0;
00386 for (size_type i=0; i<n; ++i) max = std::max(max,p[i].one_norm_real());
00387 return max;
00388 }
00389
00390
00391
00396 template<class V>
00397 void solve (V& x, const V& b) const;
00398
00403 void invert();
00404
00406 K determinant () const;
00407
00409 FieldMatrix& leftmultiply (const FieldMatrix<K,n,n>& M)
00410 {
00411 FieldMatrix<K,n,m> C(*this);
00412
00413 for (size_type i=0; i<n; i++)
00414 for (size_type j=0; j<m; j++) {
00415 (*this)[i][j] = 0;
00416 for (size_type k=0; k<n; k++)
00417 (*this)[i][j] += M[i][k]*C[k][j];
00418 }
00419
00420 return *this;
00421 }
00422
00424 FieldMatrix& rightmultiply (const FieldMatrix<K,m,m>& M)
00425 {
00426 FieldMatrix<K,n,m> C(*this);
00427
00428 for (size_type i=0; i<n; i++)
00429 for (size_type j=0; j<m; j++) {
00430 (*this)[i][j] = 0;
00431 for (size_type k=0; k<m; k++)
00432 (*this)[i][j] += C[i][k]*M[k][j];
00433 }
00434 return *this;
00435 }
00436
00437
00438
00439
00441 size_type N () const
00442 {
00443 return n;
00444 }
00445
00447 size_type M () const
00448 {
00449 return m;
00450 }
00451
00453 size_type rowdim (size_type r) const
00454 {
00455 return 1;
00456 }
00457
00459 size_type coldim (size_type c) const
00460 {
00461 return 1;
00462 }
00463
00465 size_type rowdim () const
00466 {
00467 return n;
00468 }
00469
00471 size_type coldim () const
00472 {
00473 return m;
00474 }
00475
00476
00477
00479 bool exists (size_type i, size_type j) const
00480 {
00481 #ifdef DUNE_FMatrix_WITH_CHECKING
00482 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00483 if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00484 #endif
00485 return true;
00486 }
00487
00488
00489
00491 friend std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,n,m>& a)
00492 {
00493 for (size_type i=0; i<n; i++)
00494 s << a.p[i] << std::endl;
00495 return s;
00496 }
00497
00498 private:
00499
00500 row_type p[(n > 0) ? n : 1];
00501
00502 struct ElimPivot
00503 {
00504 ElimPivot(size_type pivot[n]);
00505
00506 void swap(int i, int j);
00507
00508 template<typename T>
00509 void operator()(const T&, int k, int i)
00510 {}
00511
00512 size_type* pivot_;
00513 };
00514
00515 template<typename V>
00516 struct Elim
00517 {
00518 Elim(V& rhs);
00519
00520 void swap(int i, int j);
00521
00522 void operator()(const typename V::field_type& factor, int k, int i);
00523
00524 V* rhs_;
00525 };
00526
00527 template<class Func>
00528 void luDecomposition(FieldMatrix<K,n,n>& A, Func func) const;
00529 };
00530
00531 template<typename K, int n, int m>
00532 FieldMatrix<K,n,m>::ElimPivot::ElimPivot(size_type pivot[n])
00533 : pivot_(pivot)
00534 {
00535 for(int i=0; i < n; ++i) pivot[i]=i;
00536 }
00537
00538 template<typename K, int n, int m>
00539 void FieldMatrix<K,n,m>::ElimPivot::swap(int i, int j)
00540 {
00541 pivot_[i]=j;
00542 }
00543
00544 template<typename K, int n, int m>
00545 template<typename V>
00546 FieldMatrix<K,n,m>::Elim<V>::Elim(V& rhs)
00547 : rhs_(&rhs)
00548 {}
00549
00550 template<typename K, int n, int m>
00551 template<typename V>
00552 void FieldMatrix<K,n,m>::Elim<V>::swap(int i, int j)
00553 {
00554 std::swap((*rhs_)[i], (*rhs_)[j]);
00555 }
00556
00557 template<typename K, int n, int m>
00558 template<typename V>
00559 void FieldMatrix<K,n,m>::
00560 Elim<V>::operator()(const typename V::field_type& factor, int k, int i)
00561 {
00562 (*rhs_)[k] -= factor*(*rhs_)[i];
00563 }
00564 template<typename K, int n, int m>
00565 template<typename Func>
00566 inline void FieldMatrix<K,n,m>::luDecomposition(FieldMatrix<K,n,n>& A, Func func) const
00567 {
00568 double norm=A.infinity_norm_real();
00569 double pivthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::pivoting_limit());
00570 double singthres = std::max(FMatrixPrecision<>::absolute_limit(),norm*FMatrixPrecision<>::singular_limit());
00571
00572
00573 for (int i=0; i<n; i++)
00574 {
00575 double pivmax=fvmeta_absreal(A[i][i]);
00576
00577
00578 if (pivmax<pivthres)
00579 {
00580
00581 int imax=i; double abs;
00582 for (int k=i+1; k<n; k++)
00583 if ((abs=fvmeta_absreal(A[k][i]))>pivmax)
00584 {
00585 pivmax = abs; imax = k;
00586 }
00587
00588 if (imax!=i){
00589 for (int j=0; j<n; j++)
00590 std::swap(A[i][j],A[imax][j]);
00591 func.swap(i, imax);
00592 }
00593 }
00594
00595
00596 if (pivmax<singthres)
00597 DUNE_THROW(FMatrixError,"matrix is singular");
00598
00599
00600 for (int k=i+1; k<n; k++)
00601 {
00602 K factor = A[k][i]/A[i][i];
00603 A[k][i] = factor;
00604 for (int j=i+1; j<n; j++)
00605 A[k][j] -= factor*A[i][j];
00606 func(factor, k, i);
00607 }
00608 }
00609 }
00610
00611 template <class K, int n, int m>
00612 template <class V>
00613 inline void FieldMatrix<K,n,m>::solve(V& x, const V& b) const
00614 {
00615
00616 if (n!=m)
00617 DUNE_THROW(FMatrixError, "Can't solve for a " << n << "x" << m << " matrix!");
00618
00619
00620
00621
00622 if (n==2) {
00623
00624 #ifdef DUNE_FMatrix_WITH_CHECKING
00625 K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00626 if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00627 DUNE_THROW(FMatrixError,"matrix is singular");
00628 detinv = 1/detinv;
00629 #else
00630 K detinv = 1.0/(p[0][0]*p[1][1]-p[0][1]*p[1][0]);
00631 #endif
00632
00633 x[0] = detinv*(p[1][1]*b[0]-p[0][1]*b[1]);
00634 x[1] = detinv*(p[0][0]*b[1]-p[1][0]*b[0]);
00635
00636 } else {
00637 V& rhs = x;
00638 rhs = b;
00639 Elim<V> elim(rhs);
00640 FieldMatrix<K,n,n> A(*this);
00641
00642 luDecomposition(A, elim);
00643
00644
00645 for(int i=n-1; i>=0; i--){
00646 for (int j=i+1; j<n; j++)
00647 rhs[i] -= A[i][j]*x[j];
00648 x[i] = rhs[i]/A[i][i];
00649 }
00650 }
00651 }
00652
00653 template <class K, int n, int m>
00654 inline void FieldMatrix<K,n,m>::invert()
00655 {
00656
00657 if (n!=m)
00658 DUNE_THROW(FMatrixError, "Can't invert a " << n << "x" << m << " matrix!");
00659
00660
00661
00662
00663 if (n==2) {
00664
00665 K detinv = p[0][0]*p[1][1]-p[0][1]*p[1][0];
00666 #ifdef DUNE_FMatrix_WITH_CHECKING
00667 if (fvmeta_absreal(detinv)<FMatrixPrecision<>::absolute_limit())
00668 DUNE_THROW(FMatrixError,"matrix is singular");
00669 #endif
00670 detinv = 1/detinv;
00671
00672 K temp=p[0][0];
00673 p[0][0] = p[1][1]*detinv;
00674 p[0][1] = -p[0][1]*detinv;
00675 p[1][0] = -p[1][0]*detinv;
00676 p[1][1] = temp*detinv;
00677
00678 } else {
00679
00680 FieldMatrix<K,n,n> A(*this);
00681 size_type pivot[n];
00682 luDecomposition(A, ElimPivot(pivot));
00683 FieldMatrix<K,n,m>& L=A;
00684 FieldMatrix<K,n,m>& U=A;
00685
00686
00687 *this=0;
00688
00689 for(size_type i=0; i<n; ++i)
00690 p[i][i]=1;
00691
00692
00693 for (size_type i=0; i<n; i++){
00694 for (size_type j=0; j<i; j++)
00695 for (size_type k=0; k<n; k++)
00696 p[i][k] -= L[i][j]*p[j][k];
00697 }
00698
00699
00700 for (size_type i=n; i>0;){
00701 --i;
00702 for (size_type k=0; k<n; k++){
00703 for (size_type j=i+1; j<n; j++)
00704 p[i][k] -= U[i][j]*p[j][k];
00705 p[i][k] /= U[i][i];
00706 }
00707 }
00708
00709 for(size_type i=n; i>0; ){
00710 --i;
00711 if(i!=pivot[i])
00712 for(size_type j=0; j<n; ++j)
00713 std::swap(p[j][pivot[i]], p[j][i]);
00714 }
00715 }
00716 }
00717
00718
00719 template <class K, int n, int m>
00720 inline K FieldMatrix<K,n,m>::determinant() const
00721 {
00722
00723 if (n!=m)
00724 DUNE_THROW(FMatrixError, "There is no determinant for a " << n << "x" << m << " matrix!");
00725
00726
00727
00728
00729 if (n==2)
00730 return p[0][0]*p[1][1] - p[0][1]*p[1][0];
00731
00732 if (n==3) {
00733
00734 K t4 = p[0][0] * p[1][1];
00735 K t6 = p[0][0] * p[1][2];
00736 K t8 = p[0][1] * p[1][0];
00737 K t10 = p[0][2] * p[1][0];
00738 K t12 = p[0][1] * p[2][0];
00739 K t14 = p[0][2] * p[2][0];
00740
00741 return (t4*p[2][2]-t6*p[2][1]-t8*p[2][2]+
00742 t10*p[2][1]+t12*p[1][2]-t14*p[1][1]);
00743
00744 }
00745
00746 DUNE_THROW(FMatrixError, "No implementation of determinantMatrix "
00747 << "for FieldMatrix<" << n << "," << m << "> !");
00748
00749 }
00750
00751
00754 template<class K>
00755 class FieldMatrix<K,1,1>
00756 {
00757 public:
00758
00759
00760
00761
00763 typedef K field_type;
00764
00766 typedef K block_type;
00767
00769 typedef std::size_t size_type;
00770
00772 enum {
00775 blocklevel = 1
00776 };
00777
00779 typedef FieldVector<K,1> row_type;
00780
00782 enum {
00785 rows = 1,
00786 n = 1,
00789 cols = 1,
00790 m = 1
00791 };
00792
00793
00796 FieldMatrix () {}
00797
00800 FieldMatrix (const K& k)
00801 {
00802 a = k;
00803 }
00804
00805
00806
00808 row_type& operator[] (size_type i)
00809 {
00810 #ifdef DUNE_FMatrix_WITH_CHECKING
00811 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00812 #endif
00813 return a;
00814 }
00815
00817 const row_type& operator[] (size_type i) const
00818 {
00819 #ifdef DUNE_FMatrix_WITH_CHECKING
00820 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"index out of range");
00821 #endif
00822 return a;
00823 }
00824
00825
00827 typedef FieldIterator<FieldMatrix<K,n,m>,row_type> Iterator;
00829 typedef Iterator iterator;
00831 typedef Iterator RowIterator;
00833 typedef typename row_type::Iterator ColIterator;
00834
00836 Iterator begin ()
00837 {
00838 return Iterator(*this,0);
00839 }
00840
00842 Iterator end ()
00843 {
00844 return Iterator(*this,n);
00845 }
00846
00848 Iterator rbegin ()
00849 {
00850 return Iterator(*this,n-1);
00851 }
00852
00854 Iterator rend ()
00855 {
00856 return Iterator(*this,-1);
00857 }
00858
00860 typedef FieldIterator<const FieldMatrix<K,n,m>,const row_type> ConstIterator;
00862 typedef ConstIterator const_iterator;
00864 typedef ConstIterator ConstRowIterator;
00866 typedef typename row_type::ConstIterator ConstColIterator;
00867
00869 ConstIterator begin () const
00870 {
00871 return ConstIterator(*this,0);
00872 }
00873
00875 ConstIterator end () const
00876 {
00877 return ConstIterator(*this,n);
00878 }
00879
00881 ConstIterator rbegin () const
00882 {
00883 return ConstIterator(*this,n-1);
00884 }
00885
00887 ConstIterator rend () const
00888 {
00889 return ConstIterator(*this,-1);
00890 }
00891
00892
00893
00894 FieldMatrix& operator= (const K& k)
00895 {
00896 a[0] = k;
00897 return *this;
00898 }
00899
00900
00901
00903 FieldMatrix& operator+= (const K& y)
00904 {
00905 a[0] += y;
00906 return *this;
00907 }
00908
00910 FieldMatrix& operator-= (const K& y)
00911 {
00912 a[0] -= y;
00913 return *this;
00914 }
00915
00917 FieldMatrix& operator*= (const K& k)
00918 {
00919 a[0] *= k;
00920 return *this;
00921 }
00922
00924 FieldMatrix& operator/= (const K& k)
00925 {
00926 a[0] /= k;
00927 return *this;
00928 }
00929
00930
00931
00933 void umv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00934 {
00935 y.p += a[0] * x.p;
00936 }
00937
00939 void umtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00940 {
00941 y.p += a[0] * x.p;
00942 }
00943
00945 void umhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00946 {
00947 y.p += fm_ck(a[0]) * x.p;
00948 }
00949
00951 void mmv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00952 {
00953 y.p -= a[0] * x.p;
00954 }
00955
00957 void mmtv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00958 {
00959 y.p -= a[0] * x.p;
00960 }
00961
00963 void mmhv (const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00964 {
00965 y.p -= fm_ck(a[0]) * x.p;
00966 }
00967
00969 void usmv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00970 {
00971 y.p += alpha * a[0] * x.p;
00972 }
00973
00975 void usmtv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00976 {
00977 y.p += alpha * a[0] * x.p;
00978 }
00979
00981 void usmhv (const K& alpha, const FieldVector<K,1>& x, FieldVector<K,1>& y) const
00982 {
00983 y.p += alpha * fm_ck(a[0]) * x.p;
00984 }
00985
00986
00987
00989 double frobenius_norm () const
00990 {
00991 return sqrt(fvmeta_abs2(a[0]));
00992 }
00993
00995 double frobenius_norm2 () const
00996 {
00997 return fvmeta_abs2(a[0]);
00998 }
00999
01001 double infinity_norm () const
01002 {
01003 return std::abs(a[0]);
01004 }
01005
01007 double infinity_norm_real () const
01008 {
01009 return fvmeta_abs_real(a[0]);
01010 }
01011
01012
01013
01015 void solve (FieldVector<K,1>& x, const FieldVector<K,1>& b) const
01016 {
01017 #ifdef DUNE_FMatrix_WITH_CHECKING
01018 if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01019 DUNE_THROW(FMatrixError,"matrix is singular");
01020 #endif
01021 x.p = b.p/a[0];
01022 }
01023
01025 void invert ()
01026 {
01027 #ifdef DUNE_FMatrix_WITH_CHECKING
01028 if (fvmeta_absreal(a[0][0])<FMatrixPrecision<>::absolute_limit())
01029 DUNE_THROW(FMatrixError,"matrix is singular");
01030 #endif
01031 a[0] = 1/a[0];
01032 }
01033
01035 K determinant () const
01036 {
01037 return std::abs(a[0]);
01038 }
01039
01041 FieldMatrix& leftmultiply (const FieldMatrix& M)
01042 {
01043 a[0] *= M.a[0];
01044 return *this;
01045 }
01046
01048 FieldMatrix& rightmultiply (const FieldMatrix& M)
01049 {
01050 a[0] *= M.a[0];
01051 return *this;
01052 }
01053
01054
01055
01056
01058 size_type N () const
01059 {
01060 return 1;
01061 }
01062
01064 size_type M () const
01065 {
01066 return 1;
01067 }
01068
01070 size_type rowdim (size_type r) const
01071 {
01072 return 1;
01073 }
01074
01076 size_type coldim (size_type c) const
01077 {
01078 return 1;
01079 }
01080
01082 size_type rowdim () const
01083 {
01084 return 1;
01085 }
01086
01088 size_type coldim () const
01089 {
01090 return 1;
01091 }
01092
01093
01094
01096 bool exists (size_type i, size_type j) const
01097 {
01098 return i==0 && j==0;
01099 }
01100
01101
01102
01103 operator K () const {return a[0];}
01104
01105 private:
01106
01107 row_type a;
01108 };
01109
01110 namespace FMatrixHelp {
01111
01112
01114 template <typename K>
01115 static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01116 {
01117 inverse[0][0] = 1.0/matrix[0][0];
01118 return matrix[0][0];
01119 }
01120
01122 template <typename K>
01123 static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
01124 {
01125 return invertMatrix(matrix,inverse);
01126 }
01127
01128
01130 template <typename K>
01131 static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01132 {
01133
01134 K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01135 K det_1 = 1.0/det;
01136 inverse[0][0] = matrix[1][1] * det_1;
01137 inverse[0][1] = - matrix[0][1] * det_1;
01138 inverse[1][0] = - matrix[1][0] * det_1;
01139 inverse[1][1] = matrix[0][0] * det_1;
01140 return det;
01141 }
01142
01145 template <typename K>
01146 static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
01147 {
01148
01149 K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
01150 K det_1 = 1.0/det;
01151 inverse[0][0] = matrix[1][1] * det_1;
01152 inverse[1][0] = - matrix[0][1] * det_1;
01153 inverse[0][1] = - matrix[1][0] * det_1;
01154 inverse[1][1] = matrix[0][0] * det_1;
01155 return det;
01156 }
01157
01159 template <typename K>
01160 static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01161 {
01162
01163 K t4 = matrix[0][0] * matrix[1][1];
01164 K t6 = matrix[0][0] * matrix[1][2];
01165 K t8 = matrix[0][1] * matrix[1][0];
01166 K t10 = matrix[0][2] * matrix[1][0];
01167 K t12 = matrix[0][1] * matrix[2][0];
01168 K t14 = matrix[0][2] * matrix[2][0];
01169
01170 K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01171 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01172 K t17 = 1.0/det;
01173
01174 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01175 inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01176 inverse[0][2] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01177 inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01178 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
01179 inverse[1][2] = -(t6-t10) * t17;
01180 inverse[2][0] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01181 inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01182 inverse[2][2] = (t4-t8) * t17;
01183
01184 return det;
01185 }
01186
01188 template <typename K>
01189 static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
01190 {
01191
01192 K t4 = matrix[0][0] * matrix[1][1];
01193 K t6 = matrix[0][0] * matrix[1][2];
01194 K t8 = matrix[0][1] * matrix[1][0];
01195 K t10 = matrix[0][2] * matrix[1][0];
01196 K t12 = matrix[0][1] * matrix[2][0];
01197 K t14 = matrix[0][2] * matrix[2][0];
01198
01199 K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
01200 t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
01201 K t17 = 1.0/det;
01202
01203 inverse[0][0] = (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
01204 inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
01205 inverse[2][0] = (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
01206 inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
01207 inverse[1][1] = (matrix[0][0] * matrix[2][2] - t14) * t17;
01208 inverse[2][1] = -(t6-t10) * t17;
01209 inverse[0][2] = (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
01210 inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
01211 inverse[2][2] = (t4-t8) * t17;
01212
01213 return det;
01214 }
01215
01217 template <typename K, int rows,int cols>
01218 static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
01219 {
01220 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01221
01222 for(size_type i=0; i<cols; i++)
01223 for(size_type j=0; j<cols; j++)
01224 { ret[i][j]=0.0;
01225 for(size_type k=0; k<rows; k++)
01226 ret[i][j]+=matrix[k][i]*matrix[k][j];
01227 }
01228 }
01229
01231 template <typename K, int dim>
01232 static inline void multAssign(const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x, FieldVector<K,dim> & ret)
01233 {
01234 typedef typename FieldMatrix<K,dim,dim>::size_type size_type;
01235
01236 for(size_type i=0; i<dim; i++)
01237 {
01238 ret[i] = 0.0;
01239 for(size_type j=0; j<dim; j++)
01240 {
01241 ret[i] += matrix[i][j]*x[j];
01242 }
01243 }
01244 }
01245
01247 template <typename K, int rows,int cols>
01248 static inline void multAssign(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x, FieldVector<K,rows> & ret)
01249 {
01250 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01251
01252 for(size_type i=0; i<rows; i++)
01253 {
01254 ret[i] = 0.0;
01255 for(size_type j=0; j<cols; j++)
01256 {
01257 ret[i] += matrix[i][j]*x[j];
01258 }
01259 }
01260 }
01261
01263 template <typename K, int dim>
01264 static inline void multAssignTransposed( const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x, FieldVector<K,dim> & ret)
01265 {
01266 typedef typename FieldMatrix<K,dim,dim>::size_type size_type;
01267
01268 for(size_type i=0; i<dim; i++)
01269 {
01270 ret[i] = 0.0;
01271 for(size_type j=0; j<dim; j++)
01272 {
01273 ret[i] += matrix[j][i]*x[j];
01274 }
01275 }
01276 }
01277
01279 template <typename K, int dim>
01280 static inline FieldVector<K,dim> mult(const FieldMatrix<K,dim,dim> &matrix, const FieldVector<K,dim> & x)
01281 {
01282 FieldVector<K,dim> ret;
01283 multAssign(matrix,x,ret);
01284 return ret;
01285 }
01286
01287
01288
01290 template <typename K, int rows, int cols>
01291 static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
01292 {
01293 FieldVector<K,cols> ret;
01294 typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
01295 for(size_type i=0; i<cols; i++)
01296 {
01297 ret[i] = 0.0;
01298 for(size_type j=0; j<rows; j++)
01299 {
01300 ret[i] += matrix[j][i]*x[j];
01301 }
01302 }
01303 return ret;
01304 }
01305
01306 }
01307
01310 }
01311
01312 #endif