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

/data/development/ViennaCL/ViennaCL-1.1.2/viennacl/linalg/cg.hpp

Go to the documentation of this file.
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_CG_HPP_
00016 #define _VIENNACL_CG_HPP_
00017 
00022 #include <vector>
00023 #include <map>
00024 #include <cmath>
00025 #include "viennacl/forwards.h"
00026 #include "viennacl/tools/tools.hpp"
00027 #include "viennacl/linalg/ilu.hpp"
00028 #include "viennacl/linalg/prod.hpp"
00029 #include "viennacl/linalg/inner_prod.hpp"
00030 
00031 namespace viennacl
00032 {
00033   namespace linalg
00034   {
00035     
00038     class cg_tag
00039     {
00040       public:
00046         cg_tag(double tol = 1e-8, unsigned int max_iterations = 300) : _tol(tol), _iterations(max_iterations) {};
00047       
00049         double tolerance() const { return _tol; }
00051         unsigned int max_iterations() const { return _iterations; }
00052         
00054         unsigned int iters() const { return iters_taken_; }
00055         void iters(unsigned int i) const { iters_taken_ = i; }
00056         
00058         double error() const { return last_error_; }
00060         void error(double e) const { last_error_ = e; }
00061         
00062         
00063       private:
00064         double _tol;
00065         unsigned int _iterations;
00066         
00067         //return values from solver
00068         mutable unsigned int iters_taken_;
00069         mutable double last_error_;
00070     };
00071     
00072 
00082     template <typename MatrixType, typename VectorType>
00083     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag)
00084     {
00085       //typedef typename VectorType::value_type      ScalarType;
00086       typedef typename viennacl::tools::result_of::value_type<VectorType>::type    ScalarType;
00087       typedef typename viennacl::tools::CPU_SCALAR_TYPE_DEDUCER<ScalarType>::ResultType    CPU_ScalarType;
00088       
00089       unsigned int problem_size = viennacl::tools::traits::size(rhs);
00090       VectorType result(problem_size);
00091       viennacl::tools::traits::clear(result);
00092 
00093       VectorType residual = rhs;
00094       VectorType p = rhs;
00095       VectorType tmp(problem_size);
00096 
00097       ScalarType tmp_in_p;
00098       ScalarType residual_norm_squared;
00099       CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(rhs,rhs);
00100       CPU_ScalarType alpha;
00101       CPU_ScalarType new_ip_rr = 0;
00102       CPU_ScalarType beta;
00103       CPU_ScalarType norm_rhs_squared = ip_rr;
00104       
00105       //std::cout << "Starting CG solver... " << std::endl;
00106       
00107       for (unsigned int i = 0; i < tag.max_iterations(); ++i)
00108       {
00109         tag.iters(i+1);
00110         tmp = viennacl::linalg::prod(matrix, p);
00111 
00112         //alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p);
00113         tmp_in_p = viennacl::linalg::inner_prod(tmp, p);
00114         alpha = ip_rr / static_cast<CPU_ScalarType>(tmp_in_p);
00115         
00116         result += alpha * p;
00117         residual -= alpha * tmp;
00118         
00119         residual_norm_squared = viennacl::linalg::inner_prod(residual,residual);
00120         new_ip_rr = static_cast<CPU_ScalarType>(residual_norm_squared);
00121         if (new_ip_rr / norm_rhs_squared < tag.tolerance() *  tag.tolerance())//squared norms involved here
00122           break;
00123         
00124         beta = new_ip_rr / ip_rr;
00125         ip_rr = new_ip_rr;
00126 
00127         //p = residual + beta*p;
00128         p *= beta;
00129         p += residual;
00130       } 
00131       
00132       //store last error estimate:
00133       tag.error(sqrt(new_ip_rr / norm_rhs_squared));
00134       
00135       return result;
00136     }
00137 
00138     template <typename MatrixType, typename VectorType>
00139     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, viennacl::linalg::no_precond)
00140     {
00141       return solve(matrix, rhs, tag);
00142     }
00143 
00154     template <typename MatrixType, typename VectorType, typename PreconditionerType>
00155     VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, PreconditionerType const & precond)
00156     {
00157       typedef typename VectorType::value_type      ScalarType;
00158       typedef typename viennacl::tools::CPU_SCALAR_TYPE_DEDUCER<ScalarType>::ResultType    CPU_ScalarType;
00159       unsigned int problem_size = viennacl::tools::traits::size(rhs);
00160       
00161       VectorType result(problem_size);
00162       result.clear();
00163       
00164       VectorType residual = rhs;
00165       VectorType tmp(problem_size);
00166       VectorType z = rhs;
00167 
00168       precond.apply(z);
00169       VectorType p = z;
00170 
00171       ScalarType tmp_in_p;
00172       ScalarType residual_in_z;
00173       CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(residual, z);
00174       CPU_ScalarType alpha;
00175       CPU_ScalarType new_ip_rr = 0;
00176       CPU_ScalarType beta;
00177       CPU_ScalarType norm_rhs_squared = ip_rr;
00178       CPU_ScalarType new_ipp_rr_over_norm_rhs;
00179       
00180       for (unsigned int i = 0; i < tag.max_iterations(); ++i)
00181       {
00182         tag.iters(i+1);
00183         tmp = viennacl::linalg::prod(matrix, p);
00184         
00185         tmp_in_p = viennacl::linalg::inner_prod(tmp, p);
00186         alpha = ip_rr / static_cast<CPU_ScalarType>(tmp_in_p);
00187         
00188         result += alpha * p;
00189         residual -= alpha * tmp;
00190         z = residual;
00191         precond.apply(z);
00192         
00193         residual_in_z = viennacl::linalg::inner_prod(residual, z);
00194         new_ip_rr = static_cast<CPU_ScalarType>(residual_in_z);
00195         new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared;
00196         if (std::fabs(new_ipp_rr_over_norm_rhs) < tag.tolerance() *  tag.tolerance())    //squared norms involved here
00197           break;
00198         
00199         beta = new_ip_rr / ip_rr;
00200         ip_rr = new_ip_rr;
00201         
00202         //p = z + beta*p;
00203         p *= beta;
00204         p += z;
00205       } 
00206 
00207       //store last error estimate:
00208       tag.error(sqrt(std::fabs(new_ip_rr / norm_rhs_squared)));
00209 
00210       return result;
00211     }
00212 
00213   }
00214 }
00215 
00216 #endif

Generated on Sat May 21 2011 20:36:50 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1