• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/viennacl/linalg/cg.hpp

Go to the documentation of this file.
00001 #ifndef VIENNACL_CG_HPP_
00002 #define VIENNACL_CG_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
00018 ============================================================================= */
00019 
00024 #include <vector>
00025 #include <map>
00026 #include <cmath>
00027 #include "viennacl/forwards.h"
00028 #include "viennacl/tools/tools.hpp"
00029 #include "viennacl/linalg/ilu.hpp"
00030 #include "viennacl/linalg/prod.hpp"
00031 #include "viennacl/linalg/inner_prod.hpp"
00032 #include "viennacl/traits/clear.hpp"
00033 #include "viennacl/traits/size.hpp"
00034 #include "viennacl/meta/result_of.hpp"
00035 
00036 namespace viennacl
00037 {
00038   namespace linalg
00039   {
00040     
00043     class cg_tag
00044     {
00045       public:
00051         cg_tag(double tol = 1e-8, unsigned int max_iterations = 300) : _tol(tol), _iterations(max_iterations) {};
00052       
00054         double tolerance() const { return _tol; }
00056         unsigned int max_iterations() const { return _iterations; }
00057         
00059         unsigned int iters() const { return iters_taken_; }
00060         void iters(unsigned int i) const { iters_taken_ = i; }
00061         
00063         double error() const { return last_error_; }
00065         void error(double e) const { last_error_ = e; }
00066         
00067         
00068       private:
00069         double _tol;
00070         unsigned int _iterations;
00071         
00072         //return values from solver
00073         mutable unsigned int iters_taken_;
00074         mutable double last_error_;
00075     };
00076     
00077 
00087     template <typename MatrixType, typename VectorType>
00088     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag)
00089     {
00090       //typedef typename VectorType::value_type      ScalarType;
00091       typedef typename viennacl::result_of::value_type<VectorType>::type        ScalarType;
00092       typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type    CPU_ScalarType;
00093       //std::cout << "Starting CG" << std::endl;
00094       std::size_t problem_size = viennacl::traits::size(rhs);
00095       VectorType result(problem_size);
00096       viennacl::traits::clear(result);
00097 
00098       VectorType residual = rhs;
00099       VectorType p = rhs;
00100       VectorType tmp(problem_size);
00101 
00102       ScalarType tmp_in_p;
00103       ScalarType residual_norm_squared;
00104       CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(rhs,rhs);
00105       CPU_ScalarType alpha;
00106       CPU_ScalarType new_ip_rr = 0;
00107       CPU_ScalarType beta;
00108       CPU_ScalarType norm_rhs_squared = ip_rr;
00109       
00110       //std::cout << "Starting CG solver iterations... " << std::endl;
00111       
00112       for (unsigned int i = 0; i < tag.max_iterations(); ++i)
00113       {
00114         tag.iters(i+1);
00115         tmp = viennacl::linalg::prod(matrix, p);
00116 
00117         //alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p);
00118         tmp_in_p = viennacl::linalg::inner_prod(tmp, p);
00119         alpha = ip_rr / static_cast<CPU_ScalarType>(tmp_in_p);
00120         
00121         result += alpha * p;
00122         residual -= alpha * tmp;
00123         
00124         residual_norm_squared = viennacl::linalg::inner_prod(residual,residual);
00125         new_ip_rr = static_cast<CPU_ScalarType>(residual_norm_squared);
00126         if (new_ip_rr / norm_rhs_squared < tag.tolerance() *  tag.tolerance())//squared norms involved here
00127           break;
00128         
00129         beta = new_ip_rr / ip_rr;
00130         ip_rr = new_ip_rr;
00131 
00132         //p = residual + beta*p;
00133         p *= beta;
00134         p += residual;
00135       } 
00136       
00137       //store last error estimate:
00138       tag.error(sqrt(new_ip_rr / norm_rhs_squared));
00139       
00140       return result;
00141     }
00142 
00143     template <typename MatrixType, typename VectorType>
00144     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, viennacl::linalg::no_precond)
00145     {
00146       return solve(matrix, rhs, tag);
00147     }
00148 
00159     template <typename MatrixType, typename VectorType, typename PreconditionerType>
00160     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, PreconditionerType const & precond)
00161     {
00162       typedef typename viennacl::result_of::value_type<VectorType>::type        ScalarType;
00163       typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type    CPU_ScalarType;
00164       unsigned int problem_size = viennacl::traits::size(rhs);
00165       
00166       VectorType result(problem_size);
00167       result.clear();
00168       
00169       VectorType residual = rhs;
00170       VectorType tmp(problem_size);
00171       VectorType z = rhs;
00172 
00173       precond.apply(z);
00174       VectorType p = z;
00175 
00176       ScalarType tmp_in_p;
00177       ScalarType residual_in_z;
00178       CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(residual, z);
00179       CPU_ScalarType alpha;
00180       CPU_ScalarType new_ip_rr = 0;
00181       CPU_ScalarType beta;
00182       CPU_ScalarType norm_rhs_squared = ip_rr;
00183       CPU_ScalarType new_ipp_rr_over_norm_rhs;
00184       
00185       for (unsigned int i = 0; i < tag.max_iterations(); ++i)
00186       {
00187         tag.iters(i+1);
00188         tmp = viennacl::linalg::prod(matrix, p);
00189         
00190         tmp_in_p = viennacl::linalg::inner_prod(tmp, p);
00191         alpha = ip_rr / static_cast<CPU_ScalarType>(tmp_in_p);
00192         
00193         result += alpha * p;
00194         residual -= alpha * tmp;
00195         z = residual;
00196         precond.apply(z);
00197         
00198         residual_in_z = viennacl::linalg::inner_prod(residual, z);
00199         new_ip_rr = static_cast<CPU_ScalarType>(residual_in_z);
00200         new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared;
00201         if (std::fabs(new_ipp_rr_over_norm_rhs) < tag.tolerance() *  tag.tolerance())    //squared norms involved here
00202           break;
00203         
00204         beta = new_ip_rr / ip_rr;
00205         ip_rr = new_ip_rr;
00206         
00207         //p = z + beta*p;
00208         p *= beta;
00209         p += z;
00210       } 
00211 
00212       //store last error estimate:
00213       tag.error(sqrt(std::fabs(new_ip_rr / norm_rhs_squared)));
00214 
00215       return result;
00216     }
00217 
00218   }
00219 }
00220 
00221 #endif

Generated on Fri Dec 30 2011 23:20:42 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1