00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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;
00123 typedef typename MatrixType::const_iterator2 InputColIterator;
00124 typedef typename LUType::iterator1 OutputRowIterator;
00125 typedef typename LUType::iterator2 OutputColIterator;
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
00138
00139
00140
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
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
00155
00156
00157
00158 ilut_inc_row_iterator_to_row_index(row_iter_out, index_k);
00159
00160
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
00168 if ( fabs(temp) > tag.get_drop_tolerance())
00169 {
00170
00171 for (OutputColIterator j = row_iter_out.begin(); j != row_iter_out.end(); ++j)
00172 {
00173 if (j.index2() > index_k)
00174 {
00175 w[j.index2()] -= temp * *j;
00176 }
00177 }
00178 ++k;
00179 w[index_k] = temp;
00180 }
00181 else
00182 ++k;
00183 }
00184
00185
00186
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;
00201 temp_map[temp] = k->first;
00202 ++k;
00203 }
00204 }
00205
00206
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()))
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
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 }
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;
00245 typedef typename MatrixType::const_iterator2 InputColIterator;
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;
00266 typedef typename MatrixType::const_iterator2 InputColIterator;
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
00308
00309 init(mat);
00310
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
00345
00346 init(mat);
00347
00348 }
00349
00350 void apply(vector<ScalarType> & vec) const
00351 {
00352 copy(vec, temp_vec);
00353
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
00365
00366
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
00376
00377 }
00378
00379 ilut_tag const & _tag;
00380
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