ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/detail/ilu/ilu0.hpp
Go to the documentation of this file.
00001 
00002 #ifndef VIENNACL_LINALG_DETAIL_ILU0_HPP_
00003 #define VIENNACL_LINALG_DETAIL_ILU0_HPP_
00004 
00005 /* =========================================================================
00006    Copyright (c) 2010-2014, Institute for Microelectronics,
00007                             Institute for Analysis and Scientific Computing,
00008                             TU Wien.
00009    Portions of this software are copyright by UChicago Argonne, LLC.
00010 
00011                             -----------------
00012                   ViennaCL - The Vienna Computing Library
00013                             -----------------
00014 
00015    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00016 
00017    (A list of authors and contributors can be found in the PDF manual)
00018 
00019    License:         MIT (X11), see file LICENSE in the base directory
00020 ============================================================================= */
00021 
00039 #include <vector>
00040 #include <cmath>
00041 #include <iostream>
00042 #include "viennacl/forwards.h"
00043 #include "viennacl/tools/tools.hpp"
00044 #include "viennacl/linalg/detail/ilu/common.hpp"
00045 #include "viennacl/compressed_matrix.hpp"
00046 #include "viennacl/backend/memory.hpp"
00047 
00048 #include "viennacl/linalg/host_based/common.hpp"
00049 
00050 #include <map>
00051 
00052 namespace viennacl
00053 {
00054   namespace linalg
00055   {
00056 
00059     class ilu0_tag
00060     {
00061       public:
00062         ilu0_tag(bool with_level_scheduling = false) : use_level_scheduling_(with_level_scheduling) {}
00063 
00064         bool use_level_scheduling() const { return use_level_scheduling_; }
00065         void use_level_scheduling(bool b) { use_level_scheduling_ = b; }
00066 
00067       private:
00068         bool use_level_scheduling_;
00069     };
00070 
00071 
00078     template<typename ScalarType>
00079     void precondition(viennacl::compressed_matrix<ScalarType> & A, ilu0_tag const & /* tag */)
00080     {
00081       assert( (A.handle1().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
00082       assert( (A.handle2().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
00083       assert( (A.handle().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
00084 
00085       ScalarType         * elements   = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(A.handle());
00086       unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle1());
00087       unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle2());
00088 
00089       // Note: Line numbers in the following refer to the algorithm in Saad's book
00090 
00091       for (vcl_size_t i=1; i<A.size1(); ++i)  // Line 1
00092       {
00093         unsigned int row_i_begin = row_buffer[i];
00094         unsigned int row_i_end   = row_buffer[i+1];
00095         for (unsigned int buf_index_k = row_i_begin; buf_index_k < row_i_end; ++buf_index_k) //Note: We do not assume that the column indices within a row are sorted
00096         {
00097           unsigned int k = col_buffer[buf_index_k];
00098           if (k >= i)
00099             continue; //Note: We do not assume that the column indices within a row are sorted
00100 
00101           unsigned int row_k_begin = row_buffer[k];
00102           unsigned int row_k_end   = row_buffer[k+1];
00103 
00104           // get a_kk:
00105           ScalarType a_kk = 0;
00106           for (unsigned int buf_index_akk = row_k_begin; buf_index_akk < row_k_end; ++buf_index_akk)
00107           {
00108             if (col_buffer[buf_index_akk] == k)
00109             {
00110               a_kk = elements[buf_index_akk];
00111               break;
00112             }
00113           }
00114 
00115           ScalarType & a_ik = elements[buf_index_k];
00116           a_ik /= a_kk;                                 //Line 3
00117 
00118           for (unsigned int buf_index_j = row_i_begin; buf_index_j < row_i_end; ++buf_index_j) //Note: We do not assume that the column indices within a row are sorted
00119           {
00120             unsigned int j = col_buffer[buf_index_j];
00121             if (j <= k)
00122               continue;
00123 
00124             // determine a_kj:
00125             ScalarType a_kj = 0;
00126             for (unsigned int buf_index_akj = row_k_begin; buf_index_akj < row_k_end; ++buf_index_akj)
00127             {
00128               if (col_buffer[buf_index_akj] == j)
00129               {
00130                 a_kk = elements[buf_index_akj];
00131                 break;
00132               }
00133             }
00134 
00135             //a_ij -= a_ik * a_kj
00136             elements[buf_index_j] -= a_ik * a_kj;  //Line 5
00137           }
00138         }
00139       }
00140 
00141     }
00142 
00143 
00146     template <typename MatrixType>
00147     class ilu0_precond
00148     {
00149         typedef typename MatrixType::value_type      ScalarType;
00150 
00151       public:
00152         ilu0_precond(MatrixType const & mat, ilu0_tag const & tag) : tag_(tag), LU()
00153         {
00154             //initialize preconditioner:
00155             //std::cout << "Start CPU precond" << std::endl;
00156             init(mat);
00157             //std::cout << "End CPU precond" << std::endl;
00158         }
00159 
00160         template <typename VectorType>
00161         void apply(VectorType & vec) const
00162         {
00163           unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle1());
00164           unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle2());
00165           ScalarType   const * elements   = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(LU.handle());
00166 
00167           viennacl::linalg::host_based::detail::csr_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LU.size2(), unit_lower_tag());
00168           viennacl::linalg::host_based::detail::csr_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LU.size2(), upper_tag());
00169         }
00170 
00171       private:
00172         void init(MatrixType const & mat)
00173         {
00174           viennacl::context host_context(viennacl::MAIN_MEMORY);
00175           viennacl::switch_memory_context(LU, host_context);
00176 
00177           viennacl::copy(mat, LU);
00178           viennacl::linalg::precondition(LU, tag_);
00179         }
00180 
00181         ilu0_tag const & tag_;
00182 
00183         viennacl::compressed_matrix<ScalarType> LU;
00184     };
00185 
00186 
00191     template <typename ScalarType, unsigned int MAT_ALIGNMENT>
00192     class ilu0_precond< compressed_matrix<ScalarType, MAT_ALIGNMENT> >
00193     {
00194         typedef compressed_matrix<ScalarType, MAT_ALIGNMENT>   MatrixType;
00195 
00196       public:
00197         ilu0_precond(MatrixType const & mat, ilu0_tag const & tag) : tag_(tag), LU(mat.size1(), mat.size2())
00198         {
00199           //initialize preconditioner:
00200           //std::cout << "Start GPU precond" << std::endl;
00201           init(mat);
00202           //std::cout << "End GPU precond" << std::endl;
00203         }
00204 
00205         void apply(vector<ScalarType> & vec) const
00206         {
00207           viennacl::context host_context(viennacl::MAIN_MEMORY);
00208           if (vec.handle().get_active_handle_id() != viennacl::MAIN_MEMORY)
00209           {
00210             if (tag_.use_level_scheduling())
00211             {
00212               //std::cout << "Using multifrontal on GPU..." << std::endl;
00213               detail::level_scheduling_substitute(vec,
00214                                                   multifrontal_L_row_index_arrays_,
00215                                                   multifrontal_L_row_buffers_,
00216                                                   multifrontal_L_col_buffers_,
00217                                                   multifrontal_L_element_buffers_,
00218                                                   multifrontal_L_row_elimination_num_list_);
00219 
00220               vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_);
00221 
00222               detail::level_scheduling_substitute(vec,
00223                                                   multifrontal_U_row_index_arrays_,
00224                                                   multifrontal_U_row_buffers_,
00225                                                   multifrontal_U_col_buffers_,
00226                                                   multifrontal_U_element_buffers_,
00227                                                   multifrontal_U_row_elimination_num_list_);
00228             }
00229             else
00230             {
00231               viennacl::context old_context = viennacl::traits::context(vec);
00232               viennacl::switch_memory_context(vec, host_context);
00233               viennacl::linalg::inplace_solve(LU, vec, unit_lower_tag());
00234               viennacl::linalg::inplace_solve(LU, vec, upper_tag());
00235               viennacl::switch_memory_context(vec, old_context);
00236             }
00237           }
00238           else //apply ILU0 directly on CPU
00239           {
00240             if (tag_.use_level_scheduling())
00241             {
00242               //std::cout << "Using multifrontal..." << std::endl;
00243               detail::level_scheduling_substitute(vec,
00244                                                   multifrontal_L_row_index_arrays_,
00245                                                   multifrontal_L_row_buffers_,
00246                                                   multifrontal_L_col_buffers_,
00247                                                   multifrontal_L_element_buffers_,
00248                                                   multifrontal_L_row_elimination_num_list_);
00249 
00250               vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_);
00251 
00252               detail::level_scheduling_substitute(vec,
00253                                                   multifrontal_U_row_index_arrays_,
00254                                                   multifrontal_U_row_buffers_,
00255                                                   multifrontal_U_col_buffers_,
00256                                                   multifrontal_U_element_buffers_,
00257                                                   multifrontal_U_row_elimination_num_list_);
00258             }
00259             else
00260             {
00261               viennacl::linalg::inplace_solve(LU, vec, unit_lower_tag());
00262               viennacl::linalg::inplace_solve(LU, vec, upper_tag());
00263             }
00264           }
00265         }
00266 
00267         vcl_size_t levels() const { return multifrontal_L_row_index_arrays_.size(); }
00268 
00269       private:
00270         void init(MatrixType const & mat)
00271         {
00272           viennacl::context host_context(viennacl::MAIN_MEMORY);
00273           viennacl::switch_memory_context(LU, host_context);
00274           LU = mat;
00275           viennacl::linalg::precondition(LU, tag_);
00276 
00277           if (!tag_.use_level_scheduling())
00278             return;
00279 
00280           // multifrontal part:
00281           viennacl::switch_memory_context(multifrontal_U_diagonal_, host_context);
00282           multifrontal_U_diagonal_.resize(LU.size1(), false);
00283           host_based::detail::row_info(LU, multifrontal_U_diagonal_, viennacl::linalg::detail::SPARSE_ROW_DIAGONAL);
00284 
00285           detail::level_scheduling_setup_L(LU,
00286                                            multifrontal_U_diagonal_, //dummy
00287                                            multifrontal_L_row_index_arrays_,
00288                                            multifrontal_L_row_buffers_,
00289                                            multifrontal_L_col_buffers_,
00290                                            multifrontal_L_element_buffers_,
00291                                            multifrontal_L_row_elimination_num_list_);
00292 
00293 
00294           detail::level_scheduling_setup_U(LU,
00295                                            multifrontal_U_diagonal_,
00296                                            multifrontal_U_row_index_arrays_,
00297                                            multifrontal_U_row_buffers_,
00298                                            multifrontal_U_col_buffers_,
00299                                            multifrontal_U_element_buffers_,
00300                                            multifrontal_U_row_elimination_num_list_);
00301 
00302           //
00303           // Bring to device if necessary:
00304           //
00305 
00306           // L:
00307           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_L_row_index_arrays_.begin();
00308                                                                              it != multifrontal_L_row_index_arrays_.end();
00309                                                                            ++it)
00310             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00311 
00312           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_L_row_buffers_.begin();
00313                                                                              it != multifrontal_L_row_buffers_.end();
00314                                                                            ++it)
00315             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00316 
00317           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_L_col_buffers_.begin();
00318                                                                              it != multifrontal_L_col_buffers_.end();
00319                                                                            ++it)
00320             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00321 
00322           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_L_element_buffers_.begin();
00323                                                                              it != multifrontal_L_element_buffers_.end();
00324                                                                            ++it)
00325             viennacl::backend::switch_memory_context<ScalarType>(*it, viennacl::traits::context(mat));
00326 
00327 
00328           // U:
00329 
00330           viennacl::switch_memory_context(multifrontal_U_diagonal_, viennacl::traits::context(mat));
00331 
00332           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_U_row_index_arrays_.begin();
00333                                                                              it != multifrontal_U_row_index_arrays_.end();
00334                                                                            ++it)
00335             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00336 
00337           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_U_row_buffers_.begin();
00338                                                                              it != multifrontal_U_row_buffers_.end();
00339                                                                            ++it)
00340             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00341 
00342           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_U_col_buffers_.begin();
00343                                                                              it != multifrontal_U_col_buffers_.end();
00344                                                                            ++it)
00345             viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
00346 
00347           for (typename std::list< viennacl::backend::mem_handle >::iterator it  = multifrontal_U_element_buffers_.begin();
00348                                                                              it != multifrontal_U_element_buffers_.end();
00349                                                                            ++it)
00350             viennacl::backend::switch_memory_context<ScalarType>(*it, viennacl::traits::context(mat));
00351 
00352         }
00353 
00354         ilu0_tag const & tag_;
00355         viennacl::compressed_matrix<ScalarType> LU;
00356 
00357         std::list< viennacl::backend::mem_handle > multifrontal_L_row_index_arrays_;
00358         std::list< viennacl::backend::mem_handle > multifrontal_L_row_buffers_;
00359         std::list< viennacl::backend::mem_handle > multifrontal_L_col_buffers_;
00360         std::list< viennacl::backend::mem_handle > multifrontal_L_element_buffers_;
00361         std::list< vcl_size_t > multifrontal_L_row_elimination_num_list_;
00362 
00363         viennacl::vector<ScalarType> multifrontal_U_diagonal_;
00364         std::list< viennacl::backend::mem_handle > multifrontal_U_row_index_arrays_;
00365         std::list< viennacl::backend::mem_handle > multifrontal_U_row_buffers_;
00366         std::list< viennacl::backend::mem_handle > multifrontal_U_col_buffers_;
00367         std::list< viennacl::backend::mem_handle > multifrontal_U_element_buffers_;
00368         std::list< vcl_size_t > multifrontal_U_row_elimination_num_list_;
00369 
00370     };
00371 
00372   }
00373 }
00374 
00375 
00376 
00377 
00378 #endif
00379 
00380 
00381