io.hh

Go to the documentation of this file.
00001 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=4 sw=2 sts=2:
00003 #ifndef DUNE_ISTLIO_HH
00004 #define DUNE_ISTLIO_HH
00005 
00006 #include<cmath>
00007 #include<complex>
00008 #include <limits>
00009 #include<ios>
00010 #include<iomanip>
00011 #include<fstream>
00012 #include<string>
00013 
00014 #include "istlexception.hh"
00015 #include <dune/common/fvector.hh>
00016 #include <dune/common/fmatrix.hh>
00017 #include "bcrsmatrix.hh"
00018 
00019 
00020 namespace Dune {
00021    
00032   //==== pretty printing of vectors
00033 
00034   // recursively print all the blocks
00035   template<class V>
00036   void recursive_printvector (std::ostream& s, const V& v, std::string rowtext, int& counter, 
00037                                                           int columns, int width, int precision)
00038   {
00039         for (typename V::ConstIterator i=v.begin(); i!=v.end(); ++i)
00040           recursive_printvector(s,*i,rowtext,counter,columns,width,precision);
00041   }
00042 
00043   // specialization for FieldVector
00044   template<class K, int n>
00045   void recursive_printvector (std::ostream& s, const FieldVector<K,n>& v, std::string rowtext, int& counter, 
00046                                                           int columns, int width, int precision)
00047   {
00048         // we now can print n numbers
00049         for (int i=0; i<n; i++)
00050           {
00051                 if (counter%columns==0)
00052                   { 
00053                         s << rowtext; // start a new row
00054                         s << " ";     // space in front of each entry
00055                         s.width(4);   // set width for counter
00056                         s << counter; // number of first entry in a line
00057                   }
00058                 s << " ";         // space in front of each entry
00059                 s.width(width);   // set width for each entry anew
00060                 s << v[i];        // yeah, the number !
00061                 counter++;        // increment the counter
00062                 if (counter%columns==0)
00063                   s << std::endl; // start a new line
00064           }
00065   }
00066 
00067 
00068   template<class V>
00069   void printvector (std::ostream& s, const V& v, std::string title, std::string rowtext, 
00070                                         int columns=1, int width=10, int precision=2)
00071   {
00072         // count the numbers printed to make columns
00073         int counter=0;
00074 
00075         // remember old flags
00076         std::ios_base::fmtflags oldflags = s.flags();
00077         
00078         // set the output format
00079         s.setf(std::ios_base::scientific, std::ios_base::floatfield);
00080         int oldprec = s.precision();
00081         s.precision(precision);
00082 
00083         // print title
00084         s << title << " [blocks=" << v.N() << ",dimension=" << v.dim() << "]" << std::endl;
00085 
00086         // print data from all blocks
00087         recursive_printvector(s,v,rowtext,counter,columns,width,precision);
00088 
00089         // check if new line is required
00090         if (counter%columns!=0)
00091           s << std::endl;
00092 
00093         // reset the output format
00094         s.flags(oldflags);
00095         s.precision(oldprec);
00096   }
00097 
00098 
00099   //==== pretty printing of matrices
00100 
00101 
00103   inline void fill_row (std::ostream& s, int m, int width, int precision)
00104   {
00105         for (int j=0; j<m; j++)
00106           {
00107                 s << " ";         // space in front of each entry
00108                 s.width(width);   // set width for each entry anew
00109                 s << ".";         // yeah, the number !
00110           }
00111   }
00112 
00113   template<typename B, typename A>
00114   class BCRSMatrix;
00115   
00116   template<typename K, int n, int m>
00117   class FieldMatrix;
00118   
00119   template<typename M>
00120   struct MatrixDimension
00121   {
00122   };
00123     
00124     
00125   template<typename B, typename TA>
00126   struct MatrixDimension<BCRSMatrix<B,TA> >
00127   {
00128     typedef BCRSMatrix<B,TA> Matrix;
00129     typedef typename Matrix::block_type block_type;
00130     typedef typename Matrix::size_type size_type;
00131       
00132     static size_type rowdim (const Matrix& A, size_type i)
00133     {
00134       const B* row = A.r[i].getptr();
00135       if(row)
00136         return MatrixDimension<block_type>::rowdim(*row);
00137       else
00138         return 0;
00139     }
00140       
00141     static size_type coldim (const Matrix& A, size_type c)
00142     {
00143       // find an entry in column j
00144       if (A.nnz>0)
00145         {
00146           for (size_type k=0; k<A.nnz; k++) {
00147             if (A.j[k]==c) {
00148               return MatrixDimension<block_type>::coldim(A.a[k]);
00149             }
00150           }
00151         }
00152       else
00153         {
00154           for (size_type i=0; i<A.N(); i++)
00155             {
00156               size_type* j = A.r[i].getindexptr();
00157               B*   a = A.r[i].getptr();
00158               for (size_type k=0; k<A.r[i].getsize(); k++)
00159                 if (j[k]==c) {
00160                   return MatrixDimension<block_type>::coldim(a[k]);
00161                 }
00162             }
00163         }
00164 
00165       // not found
00166       return 0;
00167     }
00168 
00169     static size_type rowdim (const Matrix& A){
00170       size_type nn=0;
00171       for (size_type i=0; i<A.N(); i++)
00172         nn += rowdim(A,i);
00173       return nn;
00174     }
00175       
00176     static size_type coldim (const Matrix& A){
00177       typedef typename Matrix::ConstRowIterator ConstRowIterator;
00178       typedef typename Matrix::ConstColIterator ConstColIterator;
00179           
00180       // The following code has a complexity of nnz, and
00181       // typically a very small constant.
00182       //
00183       std::vector<size_type> coldims(A.M(),std::numeric_limits<size_type>::max());
00184           
00185       for (ConstRowIterator row=A.begin(); row!=A.end(); ++row) 
00186         for (ConstColIterator col=row->begin(); col!=row->end(); ++col)
00187           // only compute blocksizes we don't already have
00188           if (coldims[col.index()]==std::numeric_limits<size_type>::max()) 
00189             coldims[col.index()] = MatrixDimension<block_type>::coldim(*col);
00190 
00191       size_type sum = 0;
00192       for (typename std::vector<size_type>::iterator it=coldims.begin(); it!=coldims.end(); ++it)
00193         // skip rows for which no coldim could be determined
00194         if ((*it)>=0)
00195           sum += *it;
00196 
00197       return sum;
00198     }
00199   };
00200     
00201 
00202     template<typename B, int n, int m, typename TA>
00203   struct MatrixDimension<BCRSMatrix<FieldMatrix<B,n,m> ,TA> >
00204   {
00205     typedef BCRSMatrix<FieldMatrix<B,n,m> ,TA> Matrix;
00206     typedef typename Matrix::size_type size_type;
00207       
00208     static size_type rowdim (const Matrix& A, size_type i)
00209     {
00210         return n;
00211     }
00212       
00213     static size_type coldim (const Matrix& A, size_type c)
00214     {
00215         return m;
00216     }
00217 
00218     static size_type rowdim (const Matrix& A){
00219         return A.N()*n;
00220     }
00221       
00222     static size_type coldim (const Matrix& A){
00223         return A.M()*m;
00224     }
00225   };
00226     
00227   template<typename K, int n, int m>
00228   struct MatrixDimension<FieldMatrix<K,n,m> >
00229   {
00230     typedef FieldMatrix<K,n,m> Matrix;
00231     typedef typename Matrix::size_type size_type;
00232       
00233     static size_type rowdim(const Matrix& A, size_type r)
00234     {
00235       return 1;
00236     }
00237 
00238     static size_type coldim(const Matrix& A, size_type r)
00239     {
00240       return 1;
00241     }
00242 
00243     static size_type rowdim(const Matrix& A)
00244     {
00245       return n;
00246     }
00247 
00248     static size_type coldim(const Matrix& A)
00249     {
00250       return m;
00251     }
00252   };
00253   
00255   template<class M>
00256   void print_row (std::ostream& s, const M& A, typename M::size_type I,
00257                   typename M::size_type J, typename M::size_type therow,
00258                   int width, int precision)
00259   {
00260         typename M::size_type i0=I;
00261         for (typename M::size_type i=0; i<A.N(); i++)
00262           {
00263                 if (therow>=i0 && therow<i0+MatrixDimension<M>::rowdim(A,i))
00264                   {
00265                         // the row is in this block row !
00266                         typename M::size_type j0=J;
00267                         for (typename M::size_type j=0; j<A.M(); j++)
00268                           {
00269                                 // find this block
00270                                 typename M::ConstColIterator it = A[i].find(j);
00271                                 
00272                                 // print row or filler
00273                                 if (it!=A[i].end())
00274                                   print_row(s,*it,i0,j0,therow,width,precision);
00275                                 else
00276                                   fill_row(s,MatrixDimension<M>::coldim(A,j),width,precision);
00277                                 
00278                                 // advance columns
00279                                 j0 += MatrixDimension<M>::coldim(A,j);
00280                           }
00281                   }
00282                 // advance rows
00283                 i0 += MatrixDimension<M>::rowdim(A,i);
00284           }
00285   }
00286 
00288   template<class K, int n, int m>
00289   void print_row (std::ostream& s, const FieldMatrix<K,n,m>& A, 
00290                   typename FieldMatrix<K,n,m>::size_type I, typename FieldMatrix<K,n,m>::size_type J,
00291                   typename FieldMatrix<K,n,m>::size_type therow, int width, int precision)
00292   {
00293     typedef typename FieldMatrix<K,n,m>::size_type size_type;
00294     
00295         for (size_type i=0; i<n; i++)
00296           if (I+i==therow)
00297                   for (int j=0; j<m; j++)
00298                         {
00299                           s << " ";         // space in front of each entry
00300                           s.width(width);   // set width for each entry anew
00301                           s << A[i][j];     // yeah, the number !
00302                         }
00303   }
00304 
00306   template<class K>
00307   void print_row (std::ostream& s, const FieldMatrix<K,1,1>& A, typename FieldMatrix<K,1,1>::size_type I, 
00308                   typename FieldMatrix<K,1,1>::size_type J, typename FieldMatrix<K,1,1>::size_type therow, 
00309                   int width, int precision)
00310   {
00311         if (I==therow)
00312           {
00313                 s << " ";         // space in front of each entry
00314                 s.width(width);   // set width for each entry anew
00315                 s << static_cast<K>(A);         // yeah, the number !
00316           }
00317   }
00318 
00322   template<class M>
00323   void printmatrix (std::ostream& s, const M& A, std::string title, std::string rowtext, 
00324                                         int width=10, int precision=2)
00325   {
00326     
00327         // remember old flags
00328         std::ios_base::fmtflags oldflags = s.flags();
00329 
00330         // set the output format
00331         s.setf(std::ios_base::scientific, std::ios_base::floatfield);
00332         int oldprec = s.precision();
00333         s.precision(precision);
00334 
00335         // print title
00336         s << title 
00337           << " [n=" << A.N() 
00338           << ",m=" << A.M() 
00339           << ",rowdim=" << MatrixDimension<M>::rowdim(A) 
00340           << ",coldim=" << MatrixDimension<M>::coldim(A) 
00341           << "]" << std::endl;
00342 
00343         // print all rows
00344         for (typename M::size_type i=0; i<MatrixDimension<M>::rowdim(A); i++)
00345           {
00346                 s << rowtext;  // start a new row
00347                 s << " ";      // space in front of each entry
00348                 s.width(4);    // set width for counter
00349                 s << i;        // number of first entry in a line
00350                 print_row(s,A,0,0,i,width,precision); // generic print
00351                 s << std::endl;// start a new line
00352           }
00353 
00354         // reset the output format
00355         s.flags(oldflags);
00356         s.precision(oldprec);
00357   }
00358 
00376   template<class B, int n, int m, class A>
00377   void printSparseMatrix(std::ostream& s, 
00378                          const BCRSMatrix<FieldMatrix<B,n,m>,A>& mat, 
00379                          std::string title, std::string rowtext, 
00380                          int width=3, int precision=2)
00381   {
00382     typedef BCRSMatrix<FieldMatrix<B,n,m>,A> Matrix;
00383     // remember old flags
00384     std::ios_base::fmtflags oldflags = s.flags();
00385     // set the output format
00386     s.setf(std::ios_base::scientific, std::ios_base::floatfield);
00387     int oldprec = s.precision();
00388     s.precision(precision);
00389     // print title
00390     s << title 
00391       << " [n=" << mat.N() 
00392       << ",m=" << mat.M() 
00393       << ",rowdim=" << MatrixDimension<Matrix>::rowdim(mat) 
00394       << ",coldim=" << MatrixDimension<Matrix>::coldim(mat) 
00395       << "]" << std::endl;
00396     
00397     typedef typename Matrix::ConstRowIterator Row;
00398     
00399     for(Row row=mat.begin(); row != mat.end();++row){
00400       int skipcols=0;
00401       bool reachedEnd=false;
00402       
00403       while(!reachedEnd){
00404         for(int innerrow=0; innerrow<n; ++innerrow){
00405           int count=0;
00406           typedef typename Matrix::ConstColIterator Col;
00407           Col col=row->begin();   
00408           for(; col != row->end(); ++col,++count){
00409             if(count<skipcols)
00410               continue;
00411             if(count>=skipcols+width)
00412               break;
00413             if(innerrow==0){
00414               if(count==skipcols){
00415                 s << rowtext;  // start a new row
00416                 s << " ";      // space in front of each entry
00417                 s.width(4);    // set width for counter
00418                 s << row.index()<<": ";        // number of first entry in a line
00419               }
00420               s.width(4);
00421               s<<col.index()<<": |";
00422             }else{
00423               if(count==skipcols){
00424                 for(int i=0; i < rowtext.length(); i++)
00425                   s<<" ";
00426                 s<<"       ";
00427               }
00428               s<<"      |";
00429             }
00430             for(int innercol=0; innercol < m; ++innercol){
00431               s.width(9);
00432               s<<(*col)[innerrow][innercol]<<" ";
00433             }
00434             
00435             s<<"|";
00436           }
00437           if(innerrow==n-1 && col==row->end())
00438             reachedEnd=true;
00439           else
00440             s<<std::endl;
00441         }
00442         skipcols+=width;
00443         s<<std::endl;
00444       }
00445       s<<std::endl;
00446     }
00447     
00448     // reset the output format
00449     s.flags(oldflags);
00450     s.precision(oldprec);
00451   }
00452   
00453   namespace
00454   {
00455     template<typename T>
00456     struct MatlabPODWriter
00457     {
00458       static std::ostream& write(const T& t,  std::ostream& s)
00459       {
00460         s<<t;
00461         return s;
00462       }
00463     };
00464     template<typename T>
00465     struct MatlabPODWriter<std::complex<T> >
00466     {
00467       static std::ostream& write(const std::complex<T>& t,  std::ostream& s)
00468       {
00469         s<<t.real()<<" "<<t.imag();
00470         return s;
00471       }
00472     }; 
00473   }  
00478     template <class FieldType, int rows, int cols>
00479     void writeMatrixToMatlabHelper(const FieldMatrix<FieldType,rows,cols>& matrix,
00480                                    int rowOffset, int colOffset,
00481                                    std::ostream& s)
00482     {
00483         for (int i=0; i<rows; i++)
00484             for (int j=0; j<cols; j++){
00485                 //+1 for Matlab numbering
00486                 s << rowOffset + i + 1 << " " << colOffset + j + 1 << " ";
00487                 MatlabPODWriter<FieldType>::write(matrix[i][j], s)<< std::endl;
00488             }
00489     }
00490     
00491     template <class MatrixType>
00492     void writeMatrixToMatlabHelper(const MatrixType& matrix, 
00493                                    int externalRowOffset, int externalColOffset,
00494                                    std::ostream& s)
00495 {
00496     // Precompute the accumulated sizes of the columns
00497     std::vector<typename MatrixType::size_type> colOffset(matrix.M());
00498     if (colOffset.size() > 0)
00499         colOffset[0] = 0;
00500 
00501     for (typename MatrixType::size_type i=0; i<matrix.M()-1; i++)
00502         colOffset[i+1] = colOffset[i] + MatrixDimension<MatrixType>::coldim(matrix,i);
00503     
00504     typename MatrixType::size_type rowOffset = 0;
00505 
00506     // Loop over all matrix rows
00507     for (typename MatrixType::size_type rowIdx=0; rowIdx<matrix.N(); rowIdx++) {
00508         
00509         const typename MatrixType::row_type& row = matrix[rowIdx];
00510 
00511         typename MatrixType::row_type::ConstIterator cIt   = row.begin();
00512         typename MatrixType::row_type::ConstIterator cEndIt = row.end();
00513         
00514         // Loop over all columns in this row
00515         for (; cIt!=cEndIt; ++cIt) 
00516             writeMatrixToMatlabHelper(*cIt, 
00517                                       externalRowOffset+rowOffset, 
00518                                       externalColOffset + colOffset[cIt.index()], 
00519                                       s);
00520 
00521         rowOffset += MatrixDimension<MatrixType>::rowdim(matrix, rowIdx);
00522     }
00523     
00524 }
00525 
00540 template <class MatrixType>
00541 void writeMatrixToMatlab(const MatrixType& matrix, 
00542                          const std::string& filename)
00543 {
00544     std::ofstream outStream(filename.c_str());
00545 
00546     writeMatrixToMatlabHelper(matrix, 0, 0, outStream);
00547 }
00548 
00551 } // end namespace
00552 
00553 #endif
Generated on Sat Apr 24 11:13:46 2010 for dune-istl by  doxygen 1.6.3