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

/data/development/ViennaCL/ViennaCL-1.1.2/viennacl/linalg/ilu.hpp

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

Generated on Sat May 21 2011 20:36:50 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1