00001
00002
00003 #ifndef DUNE_SCALED_IDENTITY_MATRIX_HH
00004 #define DUNE_SCALED_IDENTITY_MATRIX_HH
00005
00012 #include<cmath>
00013 #include<cstddef>
00014 #include<complex>
00015 #include<iostream>
00016 #include <dune/common/exceptions.hh>
00017 #include <dune/common/fmatrix.hh>
00018 #include <dune/istl/diagonalmatrix.hh>
00019
00020 namespace Dune {
00021
00025 template<class K, int n>
00026 class ScaledIdentityMatrix
00027 {
00028 typedef DiagonalMatrixWrapper< ScaledIdentityMatrix<K,n> > WrapperType;
00029
00030 public:
00031
00032
00034 typedef K field_type;
00035
00037 typedef K block_type;
00038
00040 typedef std::size_t size_type;
00041
00043 enum {
00045 blocklevel = 1
00046 };
00047
00049 typedef DiagonalRowVector<K,n> row_type;
00050 typedef row_type reference;
00051 typedef DiagonalRowVectorConst<K,n> const_row_type;
00052 typedef const_row_type const_reference;
00053
00055 enum {
00057 rows = n,
00059 cols = n
00060 };
00061
00062
00065 ScaledIdentityMatrix () {}
00066
00069 ScaledIdentityMatrix (const K& k)
00070 : p_(k)
00071 {}
00072
00073
00074 ScaledIdentityMatrix& operator= (const K& k)
00075 {
00076 p_ = k;
00077 return *this;
00078 }
00079
00080
00081 bool identical(const ScaledIdentityMatrix<K,n>& other) const
00082 {
00083 return (this==&other);
00084 }
00085
00086
00088 typedef ContainerWrapperIterator<const WrapperType, reference, reference> Iterator;
00090 typedef Iterator iterator;
00092 typedef Iterator RowIterator;
00094 typedef typename row_type::Iterator ColIterator;
00095
00097 Iterator begin ()
00098 {
00099 return Iterator(WrapperType(this),0);
00100 }
00101
00103 Iterator end ()
00104 {
00105 return Iterator(WrapperType(this),n);
00106 }
00107
00109 Iterator rbegin ()
00110 {
00111 return Iterator(WrapperType(this),n-1);
00112 }
00113
00115 Iterator rend ()
00116 {
00117 return Iterator(WrapperType(this),-1);
00118 }
00119
00120
00122 typedef ContainerWrapperIterator<const WrapperType, const_reference, const_reference> ConstIterator;
00124 typedef ConstIterator const_iterator;
00126 typedef ConstIterator ConstRowIterator;
00128 typedef typename const_row_type::ConstIterator ConstColIterator;
00129
00131 ConstIterator begin () const
00132 {
00133 return ConstIterator(WrapperType(this),0);
00134 }
00135
00137 ConstIterator end () const
00138 {
00139 return ConstIterator(WrapperType(this),n);
00140 }
00141
00143 ConstIterator rbegin () const
00144 {
00145 return ConstIterator(WrapperType(this),n-1);
00146 }
00147
00149 ConstIterator rend () const
00150 {
00151 return ConstIterator(WrapperType(this),-1);
00152 }
00153
00154
00155
00157 ScaledIdentityMatrix& operator+= (const ScaledIdentityMatrix& y)
00158 {
00159 p_ += y.p_;
00160 return *this;
00161 }
00162
00164 ScaledIdentityMatrix& operator-= (const ScaledIdentityMatrix& y)
00165 {
00166 p_ -= y.p_;
00167 return *this;
00168 }
00169
00171 ScaledIdentityMatrix& operator+= (const K& k)
00172 {
00173 p_ += k;
00174 return *this;
00175 }
00176
00178 ScaledIdentityMatrix& operator-= (const K& k)
00179 {
00180 p_ -= k;
00181 return *this;
00182 }
00184 ScaledIdentityMatrix& operator*= (const K& k)
00185 {
00186 p_ *= k;
00187 return *this;
00188 }
00189
00191 ScaledIdentityMatrix& operator/= (const K& k)
00192 {
00193 p_ /= k;
00194 return *this;
00195 }
00196
00197
00198
00200 template<class X, class Y>
00201 void mv (const X& x, Y& y) const
00202 {
00203 #ifdef DUNE_FMatrix_WITH_CHECKING
00204 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00205 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00206 #endif
00207 for (size_type i=0; i<n; ++i)
00208 y[i] = p_ * x[i];
00209 }
00210
00212 template<class X, class Y>
00213 void mtv (const X& x, Y& y) const
00214 {
00215 mv(x, y);
00216 }
00217
00219 template<class X, class Y>
00220 void umv (const X& x, Y& y) const
00221 {
00222 #ifdef DUNE_FMatrix_WITH_CHECKING
00223 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00224 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00225 #endif
00226 for (size_type i=0; i<n; ++i)
00227 y[i] += p_ * x[i];
00228 }
00229
00231 template<class X, class Y>
00232 void umtv (const X& x, Y& y) const
00233 {
00234 #ifdef DUNE_FMatrix_WITH_CHECKING
00235 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00236 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00237 #endif
00238 for (size_type i=0; i<n; ++i)
00239 y[i] += p_ * x[i];
00240 }
00241
00243 template<class X, class Y>
00244 void umhv (const X& x, Y& y) const
00245 {
00246 #ifdef DUNE_FMatrix_WITH_CHECKING
00247 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00248 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00249 #endif
00250 for (size_type i=0; i<n; i++)
00251 y[i] += conjugateComplex(p_)*x[i];
00252 }
00253
00255 template<class X, class Y>
00256 void mmv (const X& x, Y& y) const
00257 {
00258 #ifdef DUNE_FMatrix_WITH_CHECKING
00259 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00260 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00261 #endif
00262 for (size_type i=0; i<n; ++i)
00263 y[i] -= p_ * x[i];
00264 }
00265
00267 template<class X, class Y>
00268 void mmtv (const X& x, Y& y) const
00269 {
00270 #ifdef DUNE_FMatrix_WITH_CHECKING
00271 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00272 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00273 #endif
00274 for (size_type i=0; i<n; ++i)
00275 y[i] -= p_ * x[i];
00276 }
00277
00279 template<class X, class Y>
00280 void mmhv (const X& x, Y& y) const
00281 {
00282 #ifdef DUNE_FMatrix_WITH_CHECKING
00283 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00284 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00285 #endif
00286 for (size_type i=0; i<n; i++)
00287 y[i] -= conjugateComplex(p_)*x[i];
00288 }
00289
00291 template<class X, class Y>
00292 void usmv (const K& alpha, const X& x, Y& y) const
00293 {
00294 #ifdef DUNE_FMatrix_WITH_CHECKING
00295 if (x.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00296 if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00297 #endif
00298 for (size_type i=0; i<n; i++)
00299 y[i] += alpha * p_ * x[i];
00300 }
00301
00303 template<class X, class Y>
00304 void usmtv (const K& alpha, const X& x, Y& y) const
00305 {
00306 #ifdef DUNE_FMatrix_WITH_CHECKING
00307 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00308 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00309 #endif
00310 for (size_type i=0; i<n; i++)
00311 y[i] += alpha * p_ * x[i];
00312 }
00313
00315 template<class X, class Y>
00316 void usmhv (const K& alpha, const X& x, Y& y) const
00317 {
00318 #ifdef DUNE_FMatrix_WITH_CHECKING
00319 if (x.N()!=N()) DUNE_THROW(FMatrixError,"index out of range");
00320 if (y.N()!=M()) DUNE_THROW(FMatrixError,"index out of range");
00321 #endif
00322 for (size_type i=0; i<n; i++)
00323 y[i] += alpha * conjugateComplex(p_) * x[i];
00324 }
00325
00326
00327
00329 double frobenius_norm () const
00330 {
00331 return fvmeta::sqrt(n*p_*p_);
00332 }
00333
00335 double frobenius_norm2 () const
00336 {
00337 return n*p_*p_;
00338 }
00339
00341 double infinity_norm () const
00342 {
00343 return std::abs(p_);
00344 }
00345
00347 double infinity_norm_real () const
00348 {
00349 return fvmeta::absreal(p_);
00350 }
00351
00352
00353
00356 template<class V>
00357 void solve (V& x, const V& b) const
00358 {
00359 for (int i=0; i<n; i++)
00360 x[i] = b[i]/p_;
00361 }
00362
00365 void invert()
00366 {
00367 p_ = 1/p_;
00368 }
00369
00371 K determinant () const {
00372 return std::pow(p_,n);
00373 }
00374
00375
00376
00378 size_type N () const
00379 {
00380 return n;
00381 }
00382
00384 size_type M () const
00385 {
00386 return n;
00387 }
00388
00389
00390
00392 bool exists (size_type i, size_type j) const
00393 {
00394 #ifdef DUNE_FMatrix_WITH_CHECKING
00395 if (i<0 || i>=n) DUNE_THROW(FMatrixError,"row index out of range");
00396 if (j<0 || j>=m) DUNE_THROW(FMatrixError,"column index out of range");
00397 #endif
00398 return i==j;
00399 }
00400
00401
00402
00404 friend std::ostream& operator<< (std::ostream& s, const ScaledIdentityMatrix<K,n>& a)
00405 {
00406 for (size_type i=0; i<n; i++) {
00407 for (size_type j=0; j<n; j++)
00408 s << ((i==j) ? a.p_ : 0) << " ";
00409 s << std::endl;
00410 }
00411 return s;
00412 }
00413
00415 reference operator[](size_type i)
00416 {
00417 return reference(const_cast<K*>(&p_), i);
00418 }
00419
00421 const_reference operator[](size_type i) const
00422 {
00423 return const_reference(const_cast<K*>(&p_), i);
00424 }
00425
00427 const K& diagonal(size_type i) const
00428 {
00429 return p_;
00430 }
00431
00433 K& diagonal(size_type i)
00434 {
00435 return p_;
00436 }
00437
00440 const K& scalar() const
00441 {
00442 return p_;
00443 }
00444
00447 K& scalar()
00448 {
00449 return p_;
00450 }
00451
00452 private:
00453
00454 K p_;
00455
00456 };
00457
00458 template<class K, int n>
00459 void istl_assign_to_fmatrix(FieldMatrix<K,n,n>& fm, const ScaledIdentityMatrix<K,n>& s)
00460 {
00461 fm = K();
00462 for(int i=0; i<n; ++i)
00463 fm[i][i] = s.scalar();
00464 }
00465
00466 }
00467
00468 #endif