ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/ichol.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_ICHOL_HPP_
00002 #define VIENNACL_LINALG_ICHOL_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include <vector>
00026 #include <cmath>
00027 #include <iostream>
00028 #include "viennacl/forwards.h"
00029 #include "viennacl/tools/tools.hpp"
00030 #include "viennacl/compressed_matrix.hpp"
00031 
00032 #include "viennacl/linalg/host_based/common.hpp"
00033 
00034 #include <map>
00035 
00036 namespace viennacl
00037 {
00038   namespace linalg
00039   {
00040 
00043     class ichol0_tag {};
00044 
00045 
00054     template<typename ScalarType>
00055     void precondition(viennacl::compressed_matrix<ScalarType> & A, ichol0_tag const & /* tag */)
00056     {
00057       assert( (viennacl::traits::context(A).memory_type() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ICHOL0") );
00058 
00059       ScalarType         * elements   = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(A.handle());
00060       unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle1());
00061       unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle2());
00062 
00063       //std::cout << A.size1() << std::endl;
00064       for (vcl_size_t i=0; i<A.size1(); ++i)
00065       {
00066         unsigned int row_i_begin = row_buffer[i];
00067         unsigned int row_i_end   = row_buffer[i+1];
00068 
00069         // get a_ii:
00070         ScalarType a_ii = 0;
00071         for (unsigned int buf_index_aii = row_i_begin; buf_index_aii < row_i_end; ++buf_index_aii)
00072         {
00073           if (col_buffer[buf_index_aii] == i)
00074           {
00075             a_ii = std::sqrt(elements[buf_index_aii]);
00076             elements[buf_index_aii] = a_ii;
00077             break;
00078           }
00079         }
00080 
00081         // Now scale column/row i, i.e. A(k, i) /= A(i, i)
00082         for (unsigned int buf_index_aii = row_i_begin; buf_index_aii < row_i_end; ++buf_index_aii)
00083         {
00084           if (col_buffer[buf_index_aii] > i)
00085             elements[buf_index_aii] /= a_ii;
00086         }
00087 
00088         // Now compute A(k, j) -= A(k, i) * A(j, i) for all nonzero k, j in column i:
00089         for (unsigned int buf_index_j = row_i_begin; buf_index_j < row_i_end; ++buf_index_j)
00090         {
00091           unsigned int j = col_buffer[buf_index_j];
00092           if (j <= i)
00093             continue;
00094 
00095           ScalarType a_ji = elements[buf_index_j];
00096 
00097           for (unsigned int buf_index_k = row_i_begin; buf_index_k < row_i_end; ++buf_index_k)
00098           {
00099             unsigned int k = col_buffer[buf_index_k];
00100             if (k < j)
00101               continue;
00102 
00103             ScalarType a_ki = elements[buf_index_k];
00104 
00105             //Now check whether A(k, j) is in nonzero pattern:
00106             unsigned int row_j_begin = row_buffer[j];
00107             unsigned int row_j_end   = row_buffer[j+1];
00108             for (unsigned int buf_index_kj = row_j_begin; buf_index_kj < row_j_end; ++buf_index_kj)
00109             {
00110               if (col_buffer[buf_index_kj] == k)
00111               {
00112                 elements[buf_index_kj] -= a_ki * a_ji;
00113                 break;
00114               }
00115             }
00116           }
00117         }
00118 
00119       }
00120 
00121     }
00122 
00123 
00126     template <typename MatrixType>
00127     class ichol0_precond
00128     {
00129         typedef typename MatrixType::value_type      ScalarType;
00130 
00131       public:
00132         ichol0_precond(MatrixType const & mat, ichol0_tag const & tag) : tag_(tag), LLT(mat.size1(), mat.size2(), viennacl::context(viennacl::MAIN_MEMORY))
00133         {
00134             //initialize preconditioner:
00135             //std::cout << "Start CPU precond" << std::endl;
00136             init(mat);
00137             //std::cout << "End CPU precond" << std::endl;
00138         }
00139 
00140         template <typename VectorType>
00141         void apply(VectorType & vec) const
00142         {
00143           unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LLT.handle1());
00144           unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LLT.handle2());
00145           ScalarType   const * elements   = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(LLT.handle());
00146 
00147           // Note: L is stored in a column-oriented fashion, i.e. transposed w.r.t. the row-oriented layout. Thus, the factorization A = L L^T holds L in the upper triangular part of A.
00148           viennacl::linalg::host_based::detail::csr_trans_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LLT.size2(), lower_tag());
00149           viennacl::linalg::host_based::detail::csr_inplace_solve<ScalarType>(row_buffer, col_buffer, elements, vec, LLT.size2(), upper_tag());
00150         }
00151 
00152       private:
00153         void init(MatrixType const & mat)
00154         {
00155           viennacl::context host_ctx(viennacl::MAIN_MEMORY);
00156           viennacl::switch_memory_context(LLT, host_ctx);
00157 
00158           viennacl::copy(mat, LLT);
00159           viennacl::linalg::precondition(LLT, tag_);
00160         }
00161 
00162         ichol0_tag const & tag_;
00163         viennacl::compressed_matrix<ScalarType> LLT;
00164     };
00165 
00166 
00171     template <typename ScalarType, unsigned int MAT_ALIGNMENT>
00172     class ichol0_precond< compressed_matrix<ScalarType, MAT_ALIGNMENT> >
00173     {
00174         typedef compressed_matrix<ScalarType, MAT_ALIGNMENT>   MatrixType;
00175 
00176       public:
00177         ichol0_precond(MatrixType const & mat, ichol0_tag const & tag) : tag_(tag), LLT(mat.size1(), mat.size2(), viennacl::traits::context(mat))
00178         {
00179           //initialize preconditioner:
00180           //std::cout << "Start GPU precond" << std::endl;
00181           init(mat);
00182           //std::cout << "End GPU precond" << std::endl;
00183         }
00184 
00185         void apply(vector<ScalarType> & vec) const
00186         {
00187           if (viennacl::traits::context(vec).memory_type() != viennacl::MAIN_MEMORY)
00188           {
00189             viennacl::context host_ctx(viennacl::MAIN_MEMORY);
00190             viennacl::context old_ctx = viennacl::traits::context(vec);
00191 
00192             viennacl::switch_memory_context(vec, host_ctx);
00193             viennacl::linalg::inplace_solve(trans(LLT), vec, lower_tag());
00194             viennacl::linalg::inplace_solve(      LLT , vec, upper_tag());
00195             viennacl::switch_memory_context(vec, old_ctx);
00196           }
00197           else //apply ILU0 directly:
00198           {
00199             // Note: L is stored in a column-oriented fashion, i.e. transposed w.r.t. the row-oriented layout. Thus, the factorization A = L L^T holds L in the upper triangular part of A.
00200             viennacl::linalg::inplace_solve(trans(LLT), vec, lower_tag());
00201             viennacl::linalg::inplace_solve(      LLT , vec, upper_tag());
00202           }
00203         }
00204 
00205       private:
00206         void init(MatrixType const & mat)
00207         {
00208           viennacl::context host_ctx(viennacl::MAIN_MEMORY);
00209           viennacl::switch_memory_context(LLT, host_ctx);
00210           LLT = mat;
00211 
00212           viennacl::linalg::precondition(LLT, tag_);
00213         }
00214 
00215         ichol0_tag const & tag_;
00216         viennacl::compressed_matrix<ScalarType> LLT;
00217     };
00218 
00219   }
00220 }
00221 
00222 
00223 
00224 
00225 #endif
00226 
00227 
00228