• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/viennacl/linalg/ilu.hpp

Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_ILU_HPP_
00002 #define VIENNACL_LINALG_ILU_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
00018 ============================================================================= */
00019 
00024 #include <vector>
00025 #include <cmath>
00026 #include "viennacl/forwards.h"
00027 #include "viennacl/tools/tools.hpp"
00028 
00029 #include <map>
00030 
00031 namespace viennacl
00032 {
00033   namespace linalg
00034   {
00035     
00038     class ilut_tag
00039     {
00040       public:
00046         ilut_tag(unsigned int entries_per_row = 20,
00047                  double drop_tolerance = 1e-4) : _entries_per_row(entries_per_row), _drop_tolerance(drop_tolerance) {}; 
00048 
00049         void set_drop_tolerance(double tol)
00050         {
00051           if (tol > 0)
00052             _drop_tolerance = tol;
00053         }
00054         double get_drop_tolerance() const { return _drop_tolerance; }
00055         
00056         void set_entries_per_row(unsigned int e)
00057         {
00058           if (e > 0)
00059             _entries_per_row = e;
00060         }
00061 
00062         unsigned int get_entries_per_row() const { return _entries_per_row; }
00063 
00064       private:
00065         unsigned int _entries_per_row;
00066         double _drop_tolerance;
00067     };
00068     
00069     
00077     template <typename T>
00078     void ilut_inc_row_iterator_to_row_index(T & row_iter, unsigned int k)
00079     {
00080       while (row_iter.index1() < k)
00081         ++row_iter;
00082     }
00083     
00091     template <typename ScalarType>
00092     void ilut_inc_row_iterator_to_row_index(viennacl::tools::sparse_matrix_adapter<ScalarType> & row_iter, unsigned int k)
00093     {
00094       row_iter += k - row_iter.index1();
00095     }
00096     
00104     template <typename ScalarType>
00105     void ilut_inc_row_iterator_to_row_index(viennacl::tools::const_sparse_matrix_adapter<ScalarType> & row_iter, unsigned int k)
00106     {
00107       row_iter += k - row_iter.index1();
00108     }
00109     
00110     
00119     template<typename MatrixType, typename LUType>
00120     void precondition(MatrixType const & input, LUType & output, ilut_tag const & tag)
00121     {
00122       typedef std::map<unsigned int, double>          SparseVector;
00123       typedef typename SparseVector::iterator         SparseVectorIterator;
00124       typedef typename MatrixType::const_iterator1    InputRowIterator;  //iterate along increasing row index
00125       typedef typename MatrixType::const_iterator2    InputColIterator;  //iterate along increasing column index
00126       typedef typename LUType::iterator1              OutputRowIterator;  //iterate along increasing row index
00127       typedef typename LUType::iterator2              OutputColIterator;  //iterate along increasing column index
00128 
00129       output.clear();
00130       assert(input.size1() == output.size1());
00131       assert(input.size2() == output.size2());
00132       output.resize(static_cast<unsigned int>(input.size1()), static_cast<unsigned int>(input.size2()), false);
00133       SparseVector w;
00134       
00135       std::map<double, unsigned int> temp_map;
00136       
00137       for (InputRowIterator row_iter = input.begin1(); row_iter != input.end1(); ++row_iter)
00138       {
00139     /*    if (i%10 == 0)
00140       std::cout << i << std::endl;*/
00141         
00142         //line 2:
00143         w.clear();
00144         for (InputColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00145           w[static_cast<unsigned int>(col_iter.index2())] = *col_iter;
00146 
00147         //line 3:
00148         OutputRowIterator row_iter_out = output.begin1();
00149         for (SparseVectorIterator k = w.begin(); k != w.end();)
00150         {
00151           unsigned int index_k = k->first;
00152           if (index_k >= static_cast<unsigned int>(row_iter.index1()))
00153             break;
00154           
00155           
00156           //while (row_iter_out.index1() < index_k)
00157           //  ++row_iter_out;
00158           //if (row_iter_out.index1() < index_k)
00159           //  row_iter_out += index_k - row_iter_out.index1();
00160           ilut_inc_row_iterator_to_row_index(row_iter_out, index_k);
00161           
00162           //line 4:
00163           double temp = k->second / output(index_k, index_k);
00164           if (output(index_k, index_k) == 0.0)
00165           {
00166             std::cerr << "ViennaCL: FATAL ERROR in ILUT(): Diagonal entry is zero in row " << index_k << "!" << std::endl;
00167           }
00168           
00169           //line 5: (dropping rule to w_k)
00170           if ( fabs(temp) > tag.get_drop_tolerance())
00171           {
00172             //line 7:
00173             for (OutputColIterator j = row_iter_out.begin(); j != row_iter_out.end(); ++j)
00174             {
00175               if (j.index2() > index_k) //attention: manipulation of w(k->first) would invalidate iterator!
00176               {
00177                 w[j.index2()] -= temp * *j;
00178               }
00179             }
00180             ++k;  //attention: manipulation of w(k->first) would invalidate iterator!
00181             w[index_k] = temp;// - temp * A(index_k, index_k);
00182           }
00183           else
00184             ++k;
00185         } //for k
00186         
00187         //Line 10: Apply a dropping rule to w
00188         //Step 1: Sort all entries:
00189         temp_map.clear();
00190         for (SparseVectorIterator k = w.begin(); k != w.end(); )
00191         {
00192           if (fabs(k->second) < tag.get_drop_tolerance())
00193           { 
00194             long index = k->first;
00195             ++k;
00196             w.erase(index);
00197           }
00198           else
00199           {
00200             double temp = fabs(k->second);
00201             while (temp_map.find(temp) != temp_map.end())
00202               temp *= 1.00000001; //make entry slightly larger to maintain uniqueness of the entry
00203             temp_map[temp] = k->first;
00204             ++k;
00205           }
00206         }
00207 
00208         //Lines 10-12: write the largest p values to L and U
00209         unsigned int written_L = 0;
00210         unsigned int written_U = 0;
00211         for (typename std::map<double, unsigned int>::reverse_iterator iter = temp_map.rbegin(); iter != temp_map.rend(); ++iter)
00212         {
00213           if (iter->second > static_cast<unsigned int>(row_iter.index1())) //entry for U
00214           {
00215             if (written_U < tag.get_entries_per_row())
00216             {
00217               output(static_cast<unsigned int>(row_iter.index1()), iter->second) = static_cast<typename LUType::value_type>(w[iter->second]);
00218               ++written_U;
00219             }
00220           }
00221           else if (iter->second == static_cast<unsigned int>(row_iter.index1()))
00222           {
00223             output(iter->second, iter->second) = static_cast<typename LUType::value_type>(w[static_cast<unsigned int>(row_iter.index1())]);
00224           }
00225           else //entry for L
00226           {
00227             if (written_L < tag.get_entries_per_row())
00228             {
00229               output(static_cast<unsigned int>(row_iter.index1()), iter->second) = static_cast<typename LUType::value_type>(w[iter->second]);
00230               ++written_L;
00231             }
00232           }
00233         }
00234       } //for i
00235     }
00236 
00237 
00243     template<typename MatrixType, typename VectorType>
00244     void ilu_inplace_solve(MatrixType const & mat, VectorType & vec, viennacl::linalg::unit_lower_tag)
00245     {
00246       typedef typename MatrixType::const_iterator1    InputRowIterator;  //iterate along increasing row index
00247       typedef typename MatrixType::const_iterator2    InputColIterator;  //iterate along increasing column index
00248       
00249       for (InputRowIterator row_iter = mat.begin1(); row_iter != mat.end1(); ++row_iter)
00250       {
00251         for (InputColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00252         {
00253           if (col_iter.index2() < col_iter.index1())
00254             vec[col_iter.index1()] -= *col_iter * vec[col_iter.index2()];
00255         }
00256       }
00257     }
00258 
00264     template<typename MatrixType, typename VectorType>
00265     void ilu_inplace_solve(MatrixType const & mat, VectorType & vec, viennacl::linalg::upper_tag)
00266     {
00267       typedef typename MatrixType::const_reverse_iterator1    InputRowIterator;  //iterate along increasing row index
00268       typedef typename MatrixType::const_iterator2            InputColIterator;  //iterate along increasing column index
00269       typedef typename VectorType::value_type                 ScalarType;
00270       
00271       ScalarType diagonal_entry = 1.0;
00272       
00273       for (InputRowIterator row_iter = mat.rbegin1(); row_iter != mat.rend1(); ++row_iter)
00274       {
00275         for (InputColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00276         {
00277           if (col_iter.index2() > col_iter.index1())
00278             vec[col_iter.index1()] -= *col_iter * vec[col_iter.index2()];
00279           if (col_iter.index2() == col_iter.index1())
00280             diagonal_entry = *col_iter;
00281         }
00282         vec[row_iter.index1()] /= diagonal_entry;
00283       }
00284     }
00285 
00291     template<typename MatrixType, typename VectorType>
00292     void ilu_lu_substitute(MatrixType const & mat, VectorType & vec)
00293     {
00294       ilu_inplace_solve(mat, vec, unit_lower_tag());
00295       ilu_inplace_solve(mat, vec, upper_tag());
00296     }
00297 
00298 
00301     template <typename MatrixType>
00302     class ilut_precond
00303     {
00304       typedef typename MatrixType::value_type      ScalarType;
00305       
00306       public:
00307         ilut_precond(MatrixType const & mat, ilut_tag const & tag) : _tag(tag), LU(mat.size1())
00308         {
00309           //initialize preconditioner:
00310           //std::cout << "Start CPU precond" << std::endl;
00311           init(mat);          
00312           //std::cout << "End CPU precond" << std::endl;
00313         }
00314         
00315         template <typename VectorType>
00316         void apply(VectorType & vec) const
00317         {
00318           viennacl::tools::const_sparse_matrix_adapter<ScalarType> LU_const_adapter(LU);
00319           viennacl::linalg::ilu_lu_substitute(LU_const_adapter, vec);
00320         }
00321         
00322       private:
00323         void init(MatrixType const & mat)
00324         {
00325           viennacl::tools::sparse_matrix_adapter<ScalarType>       LU_adapter(LU);
00326           viennacl::linalg::precondition(mat, LU_adapter, _tag);
00327         }
00328         
00329         ilut_tag const & _tag;
00330         std::vector< std::map<unsigned int, ScalarType> > LU;
00331     };
00332 
00333     
00338     template <typename ScalarType, unsigned int MAT_ALIGNMENT>
00339     class ilut_precond< compressed_matrix<ScalarType, MAT_ALIGNMENT> >
00340     {
00341       typedef compressed_matrix<ScalarType, MAT_ALIGNMENT>   MatrixType;
00342       
00343       public:
00344         ilut_precond(MatrixType const & mat, ilut_tag const & tag) : _tag(tag), LU(mat.size1())
00345         {
00346           //initialize preconditioner:
00347           //std::cout << "Start GPU precond" << std::endl;
00348           init(mat);          
00349           //std::cout << "End GPU precond" << std::endl;
00350         }
00351         
00352         void apply(vector<ScalarType> & vec) const
00353         {
00354           copy(vec, temp_vec);
00355           //lu_substitute(LU, vec);
00356           viennacl::tools::const_sparse_matrix_adapter<ScalarType> LU_const_adapter(LU);
00357           viennacl::linalg::ilu_lu_substitute(LU_const_adapter, temp_vec);
00358           
00359           copy(temp_vec, vec);
00360         }
00361         
00362       private:
00363         void init(MatrixType const & mat)
00364         {
00365           std::vector< std::map<unsigned int, ScalarType> > temp(mat.size1());
00366           //std::vector< std::map<unsigned int, ScalarType> > LU_cpu(mat.size1());
00367 
00368           //copy to cpu:
00369           copy(mat, temp);
00370           
00371           viennacl::tools::const_sparse_matrix_adapter<ScalarType>       temp_adapter(temp);
00372           viennacl::tools::sparse_matrix_adapter<ScalarType>       LU_adapter(LU);
00373           viennacl::linalg::precondition(temp_adapter, LU_adapter, _tag);
00374           
00375           temp_vec.resize(mat.size1());
00376           
00377           //copy resulting preconditioner back to gpu:
00378           //copy(LU_cpu, LU);
00379         }
00380         
00381         ilut_tag const & _tag;
00382         //MatrixType LU;
00383         std::vector< std::map<unsigned int, ScalarType> > LU;
00384         mutable std::vector<ScalarType> temp_vec;
00385     };
00386 
00387   }
00388 }
00389 
00390 
00391 
00392 
00393 #endif
00394 
00395 
00396 

Generated on Fri Dec 30 2011 23:20:43 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1