ViennaCL - The Vienna Computing Library: viennacl/linalg/detail/ilu/ilu0.hpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ilu0.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_DETAIL_ILU0_HPP_
2 #define VIENNACL_LINALG_DETAIL_ILU0_HPP_
3
4 /* =========================================================================
5 Copyright (c) 2010-2016, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8 Portions of this software are copyright by UChicago Argonne, LLC.
9
10 -----------------
11 ViennaCL - The Vienna Computing Library
12 -----------------
13
14 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15
16 (A list of authors and contributors can be found in the manual)
17
18 License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20
38 #include <vector>
39 #include <cmath>
40 #include <iostream>
41 #include "viennacl/forwards.h"
42 #include "viennacl/tools/tools.hpp"
43 #include "viennacl/linalg/detail/ilu/common.hpp"
44 #include "viennacl/compressed_matrix.hpp"
45 #include "viennacl/backend/memory.hpp"
46
47 #include "viennacl/linalg/host_based/common.hpp"
48
49 #include <map>
50
51 namespace viennacl
52 {
53 namespace linalg
54 {
55
58 class ilu0_tag
59 {
60 public:
61 ilu0_tag(bool with_level_scheduling = false) : use_level_scheduling_(with_level_scheduling) {}
62
63 bool use_level_scheduling() const { return use_level_scheduling_; }
64 void use_level_scheduling(bool b) { use_level_scheduling_ = b; }
65
66 private:
67 bool use_level_scheduling_;
68 };
69
70
77 template<typename NumericT>
78 void precondition(viennacl::compressed_matrix<NumericT> & A, ilu0_tag const & /* tag */)
79 {
80 assert( (A.handle1().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
81 assert( (A.handle2().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
82 assert( (A.handle().get_active_handle_id() == viennacl::MAIN_MEMORY) && bool("System matrix must reside in main memory for ILU0") );
83
84 NumericT * elements = viennacl::linalg::host_based::detail::extract_raw_pointer<NumericT>(A.handle());
85 unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle1());
86 unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(A.handle2());
87
88 // Note: Line numbers in the following refer to the algorithm in Saad's book
89
90 for (vcl_size_t i=1; i<A.size1(); ++i) // Line 1
91 {
92 unsigned int row_i_begin = row_buffer[i];
93 unsigned int row_i_end = row_buffer[i+1];
94 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
95 {
96 unsigned int k = col_buffer[buf_index_k];
97 if (k >= i)
98 continue; //Note: We do not assume that the column indices within a row are sorted
99
100 unsigned int row_k_begin = row_buffer[k];
101 unsigned int row_k_end = row_buffer[k+1];
102
103 // get a_kk:
104 NumericT a_kk = 0;
105 for (unsigned int buf_index_akk = row_k_begin; buf_index_akk < row_k_end; ++buf_index_akk)
106 {
107 if (col_buffer[buf_index_akk] == k)
108 {
109 a_kk = elements[buf_index_akk];
110 break;
111 }
112 }
113
114 NumericT & a_ik = elements[buf_index_k];
115 a_ik /= a_kk; //Line 3
116
117 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
118 {
119 unsigned int j = col_buffer[buf_index_j];
120 if (j <= k)
121 continue;
122
123 // determine a_kj:
124 NumericT a_kj = 0;
125 for (unsigned int buf_index_akj = row_k_begin; buf_index_akj < row_k_end; ++buf_index_akj)
126 {
127 if (col_buffer[buf_index_akj] == j)
128 {
129 a_kj = elements[buf_index_akj];
130 break;
131 }
132 }
133
134 //a_ij -= a_ik * a_kj
135 elements[buf_index_j] -= a_ik * a_kj; //Line 5
136 }
137 }
138 }
139
140 }
141
142
145 template<typename MatrixT>
146 class ilu0_precond
147 {
148 typedef typename MatrixT::value_type NumericType;
149
150 public:
151 ilu0_precond(MatrixT const & mat, ilu0_tag const & tag) : tag_(tag), LU_()
152 {
153 //initialize preconditioner:
154 //std::cout << "Start CPU precond" << std::endl;
155 init(mat);
156 //std::cout << "End CPU precond" << std::endl;
157 }
158
159 template<typename VectorT>
160 void apply(VectorT & vec) const
161 {
162 unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU_.handle1());
163 unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU_.handle2());
164 NumericType const * elements = viennacl::linalg::host_based::detail::extract_raw_pointer<NumericType>(LU_.handle());
165
166 viennacl::linalg::host_based::detail::csr_inplace_solve<NumericType>(row_buffer, col_buffer, elements, vec, LU_.size2(), unit_lower_tag());
167 viennacl::linalg::host_based::detail::csr_inplace_solve<NumericType>(row_buffer, col_buffer, elements, vec, LU_.size2(), upper_tag());
168 }
169
170 private:
171 void init(MatrixT const & mat)
172 {
173 viennacl::context host_context(viennacl::MAIN_MEMORY);
174 viennacl::switch_memory_context(LU_, host_context);
175
176 viennacl::copy(mat, LU_);
177 viennacl::linalg::precondition(LU_, tag_);
178 }
179
180 ilu0_tag tag_;
181 viennacl::compressed_matrix<NumericType> LU_;
182 };
183
184
189 template<typename NumericT, unsigned int AlignmentV>
190 class ilu0_precond< viennacl::compressed_matrix<NumericT, AlignmentV> >
191 {
192 typedef viennacl::compressed_matrix<NumericT, AlignmentV> MatrixType;
193
194 public:
195 ilu0_precond(MatrixType const & mat, ilu0_tag const & tag)
196 : tag_(tag),
197 LU_(mat.size1(), mat.size2(), viennacl::traits::context(mat))
198 {
199 //initialize preconditioner:
200 //std::cout << "Start GPU precond" << std::endl;
201 init(mat);
202 //std::cout << "End GPU precond" << std::endl;
203 }
204
205 void apply(viennacl::vector<NumericT> & vec) const
206 {
207 viennacl::context host_context(viennacl::MAIN_MEMORY);
208 if (vec.handle().get_active_handle_id() != viennacl::MAIN_MEMORY)
209 {
210 if (tag_.use_level_scheduling())
211 {
212 //std::cout << "Using multifrontal on GPU..." << std::endl;
213 detail::level_scheduling_substitute(vec,
214 multifrontal_L_row_index_arrays_,
215 multifrontal_L_row_buffers_,
216 multifrontal_L_col_buffers_,
217 multifrontal_L_element_buffers_,
218 multifrontal_L_row_elimination_num_list_);
219
220 vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_);
221
222 detail::level_scheduling_substitute(vec,
223 multifrontal_U_row_index_arrays_,
224 multifrontal_U_row_buffers_,
225 multifrontal_U_col_buffers_,
226 multifrontal_U_element_buffers_,
227 multifrontal_U_row_elimination_num_list_);
228 }
229 else
230 {
231 viennacl::context old_context = viennacl::traits::context(vec);
232 viennacl::switch_memory_context(vec, host_context);
233 viennacl::linalg::inplace_solve(LU_, vec, unit_lower_tag());
234 viennacl::linalg::inplace_solve(LU_, vec, upper_tag());
235 viennacl::switch_memory_context(vec, old_context);
236 }
237 }
238 else //apply ILU0 directly on CPU
239 {
240 if (tag_.use_level_scheduling())
241 {
242 //std::cout << "Using multifrontal..." << std::endl;
243 detail::level_scheduling_substitute(vec,
244 multifrontal_L_row_index_arrays_,
245 multifrontal_L_row_buffers_,
246 multifrontal_L_col_buffers_,
247 multifrontal_L_element_buffers_,
248 multifrontal_L_row_elimination_num_list_);
249
250 vec = viennacl::linalg::element_div(vec, multifrontal_U_diagonal_);
251
252 detail::level_scheduling_substitute(vec,
253 multifrontal_U_row_index_arrays_,
254 multifrontal_U_row_buffers_,
255 multifrontal_U_col_buffers_,
256 multifrontal_U_element_buffers_,
257 multifrontal_U_row_elimination_num_list_);
258 }
259 else
260 {
261 viennacl::linalg::inplace_solve(LU_, vec, unit_lower_tag());
262 viennacl::linalg::inplace_solve(LU_, vec, upper_tag());
263 }
264 }
265 }
266
267 vcl_size_t levels() const { return multifrontal_L_row_index_arrays_.size(); }
268
269 private:
270 void init(MatrixType const & mat)
271 {
272 viennacl::context host_context(viennacl::MAIN_MEMORY);
273 viennacl::switch_memory_context(LU_, host_context);
274 LU_ = mat;
275 viennacl::linalg::precondition(LU_, tag_);
276
277 if (!tag_.use_level_scheduling())
278 return;
279
280 // multifrontal part:
281 viennacl::switch_memory_context(multifrontal_U_diagonal_, host_context);
282 multifrontal_U_diagonal_.resize(LU_.size1(), false);
283 host_based::detail::row_info(LU_, multifrontal_U_diagonal_, viennacl::linalg::detail::SPARSE_ROW_DIAGONAL);
284
285 detail::level_scheduling_setup_L(LU_,
286 multifrontal_U_diagonal_, //dummy
287 multifrontal_L_row_index_arrays_,
288 multifrontal_L_row_buffers_,
289 multifrontal_L_col_buffers_,
290 multifrontal_L_element_buffers_,
291 multifrontal_L_row_elimination_num_list_);
292
293
294 detail::level_scheduling_setup_U(LU_,
295 multifrontal_U_diagonal_,
296 multifrontal_U_row_index_arrays_,
297 multifrontal_U_row_buffers_,
298 multifrontal_U_col_buffers_,
299 multifrontal_U_element_buffers_,
300 multifrontal_U_row_elimination_num_list_);
301
302 //
303 // Bring to device if necessary:
304 //
305
306 // L:
307 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_row_index_arrays_.begin();
308 it != multifrontal_L_row_index_arrays_.end();
309 ++it)
310 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
311
312 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_row_buffers_.begin();
313 it != multifrontal_L_row_buffers_.end();
314 ++it)
315 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
316
317 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_col_buffers_.begin();
318 it != multifrontal_L_col_buffers_.end();
319 ++it)
320 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
321
322 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_L_element_buffers_.begin();
323 it != multifrontal_L_element_buffers_.end();
324 ++it)
325 viennacl::backend::switch_memory_context<NumericT>(*it, viennacl::traits::context(mat));
326
327
328 // U:
329
330 viennacl::switch_memory_context(multifrontal_U_diagonal_, viennacl::traits::context(mat));
331
332 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_row_index_arrays_.begin();
333 it != multifrontal_U_row_index_arrays_.end();
334 ++it)
335 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
336
337 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_row_buffers_.begin();
338 it != multifrontal_U_row_buffers_.end();
339 ++it)
340 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
341
342 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_col_buffers_.begin();
343 it != multifrontal_U_col_buffers_.end();
344 ++it)
345 viennacl::backend::switch_memory_context<unsigned int>(*it, viennacl::traits::context(mat));
346
347 for (typename std::list< viennacl::backend::mem_handle >::iterator it = multifrontal_U_element_buffers_.begin();
348 it != multifrontal_U_element_buffers_.end();
349 ++it)
350 viennacl::backend::switch_memory_context<NumericT>(*it, viennacl::traits::context(mat));
351
352 }
353
354 ilu0_tag tag_;
355 viennacl::compressed_matrix<NumericT> LU_;
356
357 std::list<viennacl::backend::mem_handle> multifrontal_L_row_index_arrays_;
358 std::list<viennacl::backend::mem_handle> multifrontal_L_row_buffers_;
359 std::list<viennacl::backend::mem_handle> multifrontal_L_col_buffers_;
360 std::list<viennacl::backend::mem_handle> multifrontal_L_element_buffers_;
361 std::list<vcl_size_t> multifrontal_L_row_elimination_num_list_;
362
363 viennacl::vector<NumericT> multifrontal_U_diagonal_;
364 std::list<viennacl::backend::mem_handle> multifrontal_U_row_index_arrays_;
365 std::list<viennacl::backend::mem_handle> multifrontal_U_row_buffers_;
366 std::list<viennacl::backend::mem_handle> multifrontal_U_col_buffers_;
367 std::list<viennacl::backend::mem_handle> multifrontal_U_element_buffers_;
368 std::list<vcl_size_t> multifrontal_U_row_elimination_num_list_;
369
370 };
371
372 } // namespace linalg
373 } // namespace viennacl
374
375
376 #endif
377
378
379
viennacl::compressed_matrix::size2
const vcl_size_t & size2() const
Returns the number of columns.
Definition: compressed_matrix.hpp:929
viennacl::linalg::ilu0_precond< viennacl::compressed_matrix< NumericT, AlignmentV > >::ilu0_precond
ilu0_precond(MatrixType const &mat, ilu0_tag const &tag)
Definition: ilu0.hpp:195
viennacl::linalg::element_div
viennacl::vector_expression< const vector_base< T >, const vector_base< T >, op_element_binary< op_div > > element_div(vector_base< T > const &v1, vector_base< T > const &v2)
viennacl::linalg::inplace_solve
void inplace_solve(const matrix_base< NumericT > &A, matrix_base< NumericT > &B, SolverTagT)
Direct inplace solver for triangular systems with multiple right hand sides, i.e. A \ B (MATLAB notat...
Definition: direct_solve.hpp:217
viennacl::linalg::ilu0_precond::ilu0_precond
ilu0_precond(MatrixT const &mat, ilu0_tag const &tag)
Definition: ilu0.hpp:151
viennacl::linalg::ilu0_precond
ILU0 preconditioner class, can be supplied to solve()-routines.
Definition: ilu0.hpp:146
viennacl::compressed_matrix::size1
const vcl_size_t & size1() const
Returns the number of rows.
Definition: compressed_matrix.hpp:927
tools.hpp
Various little tools used here and there in ViennaCL.
viennacl::traits::size1
vcl_size_t size1(MatrixType const &mat)
Generic routine for obtaining the number of rows of a matrix (ViennaCL, uBLAS, etc.)
Definition: size.hpp:163
viennacl::linalg::ilu0_tag
A tag for incomplete LU factorization with static pattern (ILU0)
Definition: ilu0.hpp:58
viennacl::linalg::precondition
void precondition(viennacl::compressed_matrix< NumericT > &A, ilu0_tag const &)
Implementation of a ILU-preconditioner with static pattern. Optimized version for CSR matrices...
Definition: ilu0.hpp:78
forwards.h
This file provides the forward declarations for the main types used within ViennaCL.
viennacl::linalg::detail::level_scheduling_setup_U
void level_scheduling_setup_U(viennacl::compressed_matrix< NumericT, AlignmentV > const &LU, viennacl::vector< NumericT > const &diagonal_LU, std::list< viennacl::backend::mem_handle > &row_index_arrays, std::list< viennacl::backend::mem_handle > &row_buffers, std::list< viennacl::backend::mem_handle > &col_buffers, std::list< viennacl::backend::mem_handle > &element_buffers, std::list< vcl_size_t > &row_elimination_num_list)
Definition: common.hpp:208
viennacl::traits::size2
result_of::size_type< MatrixType >::type size2(MatrixType const &mat)
Generic routine for obtaining the number of columns of a matrix (ViennaCL, uBLAS, etc...
Definition: size.hpp:201
viennacl::linalg::detail::level_scheduling_substitute
void level_scheduling_substitute(viennacl::vector< NumericT > &vec, std::list< viennacl::backend::mem_handle > const &row_index_arrays, std::list< viennacl::backend::mem_handle > const &row_buffers, std::list< viennacl::backend::mem_handle > const &col_buffers, std::list< viennacl::backend::mem_handle > const &element_buffers, std::list< vcl_size_t > const &row_elimination_num_list)
Definition: common.hpp:224
viennacl::compressed_matrix::handle
const handle_type & handle() const
Returns the OpenCL handle to the matrix entry array.
Definition: compressed_matrix.hpp:942
viennacl::compressed_matrix::handle1
const handle_type & handle1() const
Returns the OpenCL handle to the row index array.
Definition: compressed_matrix.hpp:936
NumericT
float NumericT
Definition: bisect.cpp:40
viennacl::context
Represents a generic 'context' similar to an OpenCL context, but is backend-agnostic and thus also su...
Definition: context.hpp:39
viennacl::linalg::upper_tag
A tag class representing an upper triangular matrix.
Definition: forwards.h:854
compressed_matrix.hpp
Implementation of the compressed_matrix class.
viennacl::compressed_matrix::handle2
const handle_type & handle2() const
Returns the OpenCL handle to the column index array.
Definition: compressed_matrix.hpp:938
viennacl::linalg::ilu0_precond< viennacl::compressed_matrix< NumericT, AlignmentV > >::levels
vcl_size_t levels() const
Definition: ilu0.hpp:267
viennacl::vcl_size_t
std::size_t vcl_size_t
Definition: forwards.h:75
common.hpp
Common routines for single-threaded or OpenMP-enabled execution on CPU.
viennacl::linalg::ilu0_precond::apply
void apply(VectorT &vec) const
Definition: ilu0.hpp:160
viennacl::vector< NumericT >
viennacl::linalg::ilu0_tag::use_level_scheduling
void use_level_scheduling(bool b)
Definition: ilu0.hpp:64
viennacl::MAIN_MEMORY
Definition: forwards.h:348
viennacl::traits::context
viennacl::context context(T const &t)
Returns an ID for the currently active memory domain of an object.
Definition: context.hpp:40
viennacl::linalg::ilu0_tag::use_level_scheduling
bool use_level_scheduling() const
Definition: ilu0.hpp:63
viennacl::linalg::detail::SPARSE_ROW_DIAGONAL
Definition: forwards.h:842
viennacl::copy
void copy(std::vector< NumericT > &cpu_vec, circulant_matrix< NumericT, AlignmentV > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
Definition: circulant_matrix.hpp:150
viennacl::linalg::unit_lower_tag
A tag class representing a lower triangular matrix with unit diagonal.
Definition: forwards.h:859
viennacl::linalg::host_based::detail::row_info
void row_info(compressed_matrix< NumericT, AlignmentV > const &mat, vector_base< NumericT > &vec, viennacl::linalg::detail::row_info_types info_selector)
Definition: sparse_matrix_operations.hpp:53
viennacl::linalg::detail::level_scheduling_setup_L
void level_scheduling_setup_L(viennacl::compressed_matrix< NumericT, AlignmentV > const &LU, viennacl::vector< NumericT > const &diagonal_LU, std::list< viennacl::backend::mem_handle > &row_index_arrays, std::list< viennacl::backend::mem_handle > &row_buffers, std::list< viennacl::backend::mem_handle > &col_buffers, std::list< viennacl::backend::mem_handle > &element_buffers, std::list< vcl_size_t > &row_elimination_num_list)
Definition: common.hpp:191
viennacl::compressed_matrix< NumericT >
common.hpp
Common routines used within ILU-type preconditioners.
viennacl::linalg::ilu0_precond< viennacl::compressed_matrix< NumericT, AlignmentV > >::apply
void apply(viennacl::vector< NumericT > &vec) const
Definition: ilu0.hpp:205
viennacl::vector_base::handle
const handle_type & handle() const
Returns the memory handle.
Definition: vector_def.hpp:128
memory.hpp
Main interface routines for memory management.
viennacl::linalg::ilu0_tag::ilu0_tag
ilu0_tag(bool with_level_scheduling=false)
Definition: ilu0.hpp:61
viennacl::backend::mem_handle::get_active_handle_id
memory_types get_active_handle_id() const
Returns an ID for the currently active memory buffer. Other memory buffers might contain old or no da...
Definition: mem_handle.hpp:118
viennacl::switch_memory_context
void switch_memory_context(T &obj, viennacl::context new_ctx)
Generic convenience routine for migrating data of an object to a new memory domain.
Definition: memory.hpp:622