ViennaCL - The Vienna Computing Library
1.5.2
|
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