btdmatrix.hh

Go to the documentation of this file.
00001 #ifndef DUNE_BLOCK_TRIDIAGONAL_MATRIX_HH
00002 #define DUNE_BLOCK_TRIDIAGONAL_MATRIX_HH
00003 
00004 #include <dune/istl/bcrsmatrix.hh>
00005 
00011 namespace Dune {
00021     template <class B, class A=std::allocator<B> >
00022 class BTDMatrix : public BCRSMatrix<B,A>
00023 {
00024 public:
00025 
00026     //===== type definitions and constants
00027     
00029     typedef typename B::field_type field_type;
00030     
00032     typedef B block_type;
00033     
00035     typedef A allocator_type;
00036     
00038     //typedef BCRSMatrix<B,A>::row_type row_type;
00039 
00041     typedef typename A::size_type size_type;
00042 
00044     enum {blocklevel = B::blocklevel+1};
00045 
00047     BTDMatrix() : BCRSMatrix<B,A>() {}
00048 
00049     explicit BTDMatrix(int size) 
00050         : BCRSMatrix<B,A>(size, size, BCRSMatrix<B,A>::random) 
00051     {
00052         // special handling for 1x1 matrices
00053         if (size==1) {
00054 
00055             this->BCRSMatrix<B,A>::setrowsize(0, 1);
00056             this->BCRSMatrix<B,A>::endrowsizes();
00057             
00058             this->BCRSMatrix<B,A>::addindex(0, 0);
00059             this->BCRSMatrix<B,A>::endindices();
00060             
00061             return;
00062         }
00063 
00064         // Set number of entries for each row
00065         this->BCRSMatrix<B,A>::setrowsize(0, 2);
00066 
00067         for (int i=1; i<size-1; i++)
00068             this->BCRSMatrix<B,A>::setrowsize(i, 3);
00069 
00070         this->BCRSMatrix<B,A>::setrowsize(size-1, 2);
00071 
00072         this->BCRSMatrix<B,A>::endrowsizes();
00073 
00074         // The actual entries for each row
00075         this->BCRSMatrix<B,A>::addindex(0, 0);
00076         this->BCRSMatrix<B,A>::addindex(0, 1);
00077 
00078         for (int i=1; i<size-1; i++) {
00079             this->BCRSMatrix<B,A>::addindex(i, i-1);
00080             this->BCRSMatrix<B,A>::addindex(i, i  );
00081             this->BCRSMatrix<B,A>::addindex(i, i+1);
00082         }
00083 
00084         this->BCRSMatrix<B,A>::addindex(size-1, size-2);
00085         this->BCRSMatrix<B,A>::addindex(size-1, size-1);
00086 
00087         this->BCRSMatrix<B,A>::endindices();
00088 
00089     }
00090 
00092     BTDMatrix& operator= (const BTDMatrix& other) {
00093         this->BCRSMatrix<B,A>::operator=(other);
00094         return *this;
00095     }
00096 
00098     BTDMatrix& operator= (const field_type& k) {
00099         this->BCRSMatrix<B,A>::operator=(k);
00100         return *this;
00101     }
00102 
00108     template <class V>
00109     void solve (V& x, const V& rhs) const {
00110 
00111         // special handling for 1x1 matrices.  The generic algorithm doesn't work for them
00112         if (this->N()==1) {
00113             (*this)[0][0].solve(x[0],rhs[0]);
00114             return;
00115         }
00116 
00117         // Make copies of the rhs and the right matrix band
00118         V d = rhs;
00119         std::vector<block_type> c(this->N()-1);
00120         for (size_t i=0; i<this->N()-1; i++)
00121             c[i] = (*this)[i][i+1];
00122 
00123         /* Modify the coefficients. */
00124         block_type a_00_inv;
00125         FMatrixHelp::invertMatrix((*this)[0][0], a_00_inv);
00126 
00127         //c[0] /= (*this)[0][0];        /* Division by zero risk. */
00128         block_type c_0_tmp = c[0];
00129         FMatrixHelp::multMatrix(a_00_inv, c_0_tmp, c[0]);
00130         
00131         // d = a^{-1} d        /* Division by zero would imply a singular matrix. */
00132         typename V::block_type d_0_tmp = d[0];
00133         (*this)[0][0].solve(d[0], d_0_tmp);
00134         
00135         for (unsigned int i = 1; i < this->N(); i++) {
00136 
00137             // id = ( a_ii - c_{i-1} a_{i, i-1} ) ^{-1}
00138             block_type tmp;
00139             FMatrixHelp::multMatrix(c[i-1], (*this)[i][i-1], tmp);
00140             block_type id = (*this)[i][i];
00141             id -= tmp;
00142             id.invert();     /* Division by zero risk. */
00143 
00144             if (i<c.size()) {
00145                 // c[i] *= id
00146                 tmp = c[i];
00147                 FMatrixHelp::multMatrix(tmp, id, c[i]);                /* Last value calculated is redundant. */
00148             }
00149             
00150             // d[i] = (d[i] - d[i-1] * (*this)[i][i-1]) * id;
00151             (*this)[i][i-1].mmv(d[i-1], d[i]);
00152             typename V::block_type tmpVec = d[i];
00153             id.mv(tmpVec, d[i]);
00154             //d[i] *= id;
00155 
00156         }
00157  
00158         /* Now back substitute. */
00159         x[this->N() - 1] = d[this->N() - 1];
00160         for (int i = this->N() - 2; i >= 0; i--) {
00161             //x[i] = d[i] - c[i] * x[i + 1];
00162             x[i] = d[i];
00163             c[i].mmv(x[i+1], x[i]);
00164         }
00165 
00166     }
00167 
00168 private:        
00169 
00170     // ////////////////////////////////////////////////////////////////////////////
00171     //   The following methods from the base class should now actually be called
00172     // ////////////////////////////////////////////////////////////////////////////
00173 
00174     // createbegin and createend should be in there, too, but I can't get it to compile
00175     //     BCRSMatrix<B,A>::CreateIterator createbegin () {}
00176     //     BCRSMatrix<B,A>::CreateIterator createend () {}
00177     void setrowsize (size_type i, size_type s) {}
00178     void incrementrowsize (size_type i) {}
00179     void endrowsizes () {}
00180     void addindex (size_type row, size_type col) {}
00181     void endindices () {}
00182 };
00185 }  // end namespace Dune
00186 
00187 #endif

Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].