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