ViennaCL - The Vienna Computing Library  1.6.0
Free open-source GPU-accelerated linear algebra and solver library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cg.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_CG_HPP_
2 #define VIENNACL_LINALG_CG_HPP_
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, 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 PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
25 #include <vector>
26 #include <map>
27 #include <cmath>
28 #include <numeric>
29 
30 #include "viennacl/forwards.h"
31 #include "viennacl/tools/tools.hpp"
32 #include "viennacl/linalg/ilu.hpp"
33 #include "viennacl/linalg/prod.hpp"
37 #include "viennacl/traits/size.hpp"
40 
41 namespace viennacl
42 {
43 namespace linalg
44 {
45 
48 class cg_tag
49 {
50 public:
56  cg_tag(double tol = 1e-8, unsigned int max_iterations = 300) : tol_(tol), iterations_(max_iterations) {}
57 
59  double tolerance() const { return tol_; }
61  unsigned int max_iterations() const { return iterations_; }
62 
64  unsigned int iters() const { return iters_taken_; }
65  void iters(unsigned int i) const { iters_taken_ = i; }
66 
68  double error() const { return last_error_; }
70  void error(double e) const { last_error_ = e; }
71 
72 
73 private:
74  double tol_;
75  unsigned int iterations_;
76 
77  //return values from solver
78  mutable unsigned int iters_taken_;
79  mutable double last_error_;
80 };
81 
82 namespace detail
83 {
84 
86  template<typename VectorT, typename PreconditionerT>
87  class z_handler{
88  public:
89  z_handler(VectorT & residual) : z_(residual){ }
90  VectorT & get() { return z_; }
91  private:
92  VectorT z_;
93  };
94 
95  template<typename VectorT>
96  class z_handler<VectorT, viennacl::linalg::no_precond>{
97  public:
98  z_handler(VectorT & residual) : presidual_(&residual){ }
99  VectorT & get() { return *presidual_; }
100  private:
101  VectorT * presidual_;
102  };
103 
104 }
105 
115 //template<typename MatrixType, typename ScalarType>
116 template<typename MatrixT, typename NumericT>
117 viennacl::vector<NumericT> solve(MatrixT const & A, //MatrixType const & A,
118  viennacl::vector<NumericT> const & rhs,
119  cg_tag const & tag,
121 {
122  typedef typename viennacl::vector<NumericT>::difference_type difference_type;
123 
124  viennacl::vector<NumericT> result(rhs);
125  viennacl::traits::clear(result);
126 
127  viennacl::vector<NumericT> residual(rhs);
130  viennacl::vector<NumericT> inner_prod_buffer = viennacl::zero_vector<NumericT>(3*256, viennacl::traits::context(rhs)); // temporary buffer
131  std::vector<NumericT> host_inner_prod_buffer(inner_prod_buffer.size());
132  vcl_size_t buffer_size_per_vector = inner_prod_buffer.size() / 3;
133  difference_type buffer_offset_per_vector = static_cast<difference_type>(buffer_size_per_vector);
134 
135  NumericT norm_rhs_squared = viennacl::linalg::norm_2(residual); norm_rhs_squared *= norm_rhs_squared;
136 
137  if (!norm_rhs_squared) //check for early convergence of A*x = 0
138  return result;
139 
140  NumericT inner_prod_rr = norm_rhs_squared;
141  NumericT alpha = inner_prod_rr / viennacl::linalg::inner_prod(p, Ap);
142  NumericT beta = viennacl::linalg::norm_2(Ap); beta = (alpha * alpha * beta * beta - inner_prod_rr) / inner_prod_rr;
143  NumericT inner_prod_ApAp = 0;
144  NumericT inner_prod_pAp = 0;
145 
146  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
147  {
148  tag.iters(i+1);
149 
150  viennacl::linalg::pipelined_cg_vector_update(result, alpha, p, residual, Ap, beta, inner_prod_buffer);
151  viennacl::linalg::pipelined_cg_prod(A, p, Ap, inner_prod_buffer);
152 
153  // bring back the partial results to the host:
154  viennacl::fast_copy(inner_prod_buffer.begin(), inner_prod_buffer.end(), host_inner_prod_buffer.begin());
155 
156  inner_prod_rr = std::accumulate(host_inner_prod_buffer.begin(), host_inner_prod_buffer.begin() + buffer_offset_per_vector, NumericT(0));
157  inner_prod_ApAp = std::accumulate(host_inner_prod_buffer.begin() + buffer_offset_per_vector, host_inner_prod_buffer.begin() + 2 * buffer_offset_per_vector, NumericT(0));
158  inner_prod_pAp = std::accumulate(host_inner_prod_buffer.begin() + 2 * buffer_offset_per_vector, host_inner_prod_buffer.begin() + 3 * buffer_offset_per_vector, NumericT(0));
159 
160  if (std::fabs(inner_prod_rr / norm_rhs_squared) < tag.tolerance() * tag.tolerance()) //squared norms involved here
161  break;
162 
163  alpha = inner_prod_rr / inner_prod_pAp;
164  beta = (alpha*alpha*inner_prod_ApAp - inner_prod_rr) / inner_prod_rr;
165  }
166 
167  //store last error estimate:
168  tag.error(std::sqrt(std::fabs(inner_prod_rr) / norm_rhs_squared));
169 
170  return result;
171 }
172 
183 template<typename MatrixT, typename VectorT, typename PreconditionerT>
184 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag, PreconditionerT const & precond)
185 {
186  typedef typename viennacl::result_of::value_type<VectorT>::type NumericType;
187  typedef typename viennacl::result_of::cpu_value_type<NumericType>::type CPU_NumericType;
188 
189  VectorT result = rhs;
190  viennacl::traits::clear(result);
191 
192  VectorT residual = rhs;
193  VectorT tmp = rhs;
195  VectorT & z = zhandler.get();
196 
197  precond.apply(z);
198  VectorT p = z;
199 
200  CPU_NumericType ip_rr = viennacl::linalg::inner_prod(residual, z);
201  CPU_NumericType alpha;
202  CPU_NumericType new_ip_rr = 0;
203  CPU_NumericType beta;
204  CPU_NumericType norm_rhs_squared = ip_rr;
205  CPU_NumericType new_ipp_rr_over_norm_rhs;
206 
207  if (norm_rhs_squared <= 0) //solution is zero if RHS norm is zero
208  return result;
209 
210  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
211  {
212  tag.iters(i+1);
213  tmp = viennacl::linalg::prod(matrix, p);
214 
215  alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p);
216 
217  result += alpha * p;
218  residual -= alpha * tmp;
219  z = residual;
220  precond.apply(z);
221 
222  if (&residual==&z)
223  new_ip_rr = std::pow(viennacl::linalg::norm_2(residual),2);
224  else
225  new_ip_rr = viennacl::linalg::inner_prod(residual, z);
226 
227  new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared;
228  if (std::fabs(new_ipp_rr_over_norm_rhs) < tag.tolerance() * tag.tolerance()) //squared norms involved here
229  break;
230 
231  beta = new_ip_rr / ip_rr;
232  ip_rr = new_ip_rr;
233 
234  p = z + beta*p;
235  }
236 
237  //store last error estimate:
238  tag.error(std::sqrt(std::fabs(new_ip_rr / norm_rhs_squared)));
239 
240  return result;
241 }
242 
243 template<typename MatrixT, typename VectorT>
244 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag)
245 {
246  return solve(matrix, rhs, tag, viennacl::linalg::no_precond());
247 }
248 
249 }
250 }
251 
252 #endif
T norm_2(std::vector< T, A > const &v1)
Definition: norm_2.hpp:86
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
cg_tag(double tol=1e-8, unsigned int max_iterations=300)
The constructor.
Definition: cg.hpp:56
Generic size and resize functionality for different vector and matrix types.
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Various little tools used here and there in ViennaCL.
double tolerance() const
Returns the relative tolerance.
Definition: cg.hpp:59
handles the no_precond case at minimal overhead
Definition: cg.hpp:87
void clear(VectorType &vec)
Generic routine for setting all entries of a vector to zero. This is the version for non-ViennaCL obj...
Definition: clear.hpp:57
This file provides the forward declarations for the main types used within ViennaCL.
A dense matrix class.
Definition: forwards.h:374
viennacl::enable_if< viennacl::is_stl< typename viennacl::traits::tag_of< VectorT1 >::type >::value, typename VectorT1::value_type >::type inner_prod(VectorT1 const &v1, VectorT2 const &v2)
Definition: inner_prod.hpp:89
void pipelined_cg_vector_update(vector_base< NumericT > &result, NumericT alpha, vector_base< NumericT > &p, vector_base< NumericT > &r, vector_base< NumericT > const &Ap, NumericT beta, vector_base< NumericT > &inner_prod_buffer)
Performs a joint vector update operation needed for an efficient pipelined CG algorithm.
unsigned int iters() const
Return the number of solver iterations:
Definition: cg.hpp:64
Generic interface for the computation of inner products. See viennacl/linalg/vector_operations.hpp for implementations.
void pipelined_cg_prod(MatrixT const &A, vector_base< NumericT > const &p, vector_base< NumericT > &Ap, vector_base< NumericT > &inner_prod_buffer)
Performs a joint vector update operation needed for an efficient pipelined CG algorithm.
unsigned int max_iterations() const
Returns the maximum number of iterations.
Definition: cg.hpp:61
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:91
iterator begin()
Returns an iterator pointing to the beginning of the vector (STL like)
Definition: vector.hpp:827
A tag class representing the use of no preconditioner.
Definition: forwards.h:833
Implementations of incomplete factorization preconditioners. Convenience header file.
base_type::difference_type difference_type
Definition: vector.hpp:943
std::size_t vcl_size_t
Definition: forwards.h:74
Generic clear functionality for different vector and matrix types.
T::ERROR_CANNOT_DEDUCE_CPU_SCALAR_TYPE_FOR_T type
Definition: result_of.hpp:238
double error() const
Returns the estimated relative error at the end of the solver run.
Definition: cg.hpp:68
z_handler(VectorT &residual)
Definition: cg.hpp:89
Implementations of specialized routines for the iterative solvers.
viennacl::context context(T const &t)
Returns an ID for the currently active memory domain of an object.
Definition: context.hpp:40
void iters(unsigned int i) const
Definition: cg.hpp:65
void error(double e) const
Sets the estimated relative error at the end of the solver run.
Definition: cg.hpp:70
size_type size() const
Returns the length of the vector (cf. std::vector)
Definition: vector_def.hpp:118
A tag for the conjugate gradient Used for supplying solver parameters and for dispatching the solve()...
Definition: cg.hpp:48
iterator end()
Returns an iterator pointing to the end of the vector (STL like)
Definition: vector.hpp:834
A collection of compile time type deductions.
viennacl::vector< NumericT > solve(MatrixT const &A, viennacl::vector_base< NumericT > const &rhs, bicgstab_tag const &tag, viennacl::linalg::no_precond)
Implementation of a pipelined stabilized Bi-conjugate gradient solver.
Definition: bicgstab.hpp:88
void fast_copy(const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_begin, const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_end, CPU_ITERATOR cpu_begin)