Provided by: librheolef-dev_7.0-3_amd64 bug

NAME

       minres -- conjugate gradient algorithm.

SYNOPSIS

         template <class Matrix, class Vector, class Preconditioner, class Real>
         int minres (const Matrix &A, Vector &x, const Vector &b, const Preconditioner &M,
           const solver_option& sopt = solver_option);

EXAMPLE

       The simplest call to minres has the folling form:

         solver_option sopt;
         sopt.max_iter = 100;
         sopt.tol = 1e-7;
         int status = minres (a, x, b, eye(), sopt);

DESCRIPTION

       minres  solves  the  symmetric  positive  definite  linear system Ax=b using the Conjugate
       Gradient method.

       The return value indicates convergence within  max_iter  (input)  iterations  (0),  or  no
       convergence within max_iter iterations (1).  Upon successful return, output arguments have
       the following values:

       x      approximate solution to Ax = b

       sopt.n_iter
              the number of iterations performed before the tolerance was reached

       sopt.residue
              the residual after the final iteration

NOTE

       minres follows the algorithm described in "Solution of sparse indefinite systems of linear
       equations",  C. C. Paige and M. A. Saunders, SIAM J. Numer. Anal., 12(4), 1975.  For more,
       see http://www.stanford.edu/group/SOL/software.html and also the  PhD  "Iterative  methods
       for  singular  linear  equations  and  least-squares  problems",  S.-C.  T. Choi, Stanford
       University,     2006,      http://www.stanford.edu/group/SOL/dissertations/sou-cheng-choi-
       thesis.pdf  at  page  60.   The  present  implementation  style is inspired from IML++ 1.2
       iterative method library, http://math.nist.gov/iml++.

IMPLEMENTATION

       template <class Matrix, class Vector, class Preconditioner>
       int minres (const Matrix &A, Vector &x, const Vector &Mb, const Preconditioner &M,
         const solver_option& sopt = solver_option())
       {
         // Size &max_iter, Real &tol, odiststream *p_derr = 0
         typedef typename Vector::size_type  Size;
         typedef typename Vector::float_type Real;
         std::string label = (sopt.label != "" ? sopt.label : "minres");
         Vector b = M.solve(Mb);
         Real norm_b = sqrt(fabs(dot(Mb,b)));
         if (sopt.absolute_stopping || norm_b == Real(0.)) norm_b = 1;
         Vector Mr = Mb - A*x;
         Vector z = M.solve(Mr);
         Real beta2 = dot(Mr, z);
         Real norm_r = sqrt(fabs(beta2));
         sopt.residue = norm_r/norm_b;
         if (sopt.p_err) (*sopt.p_err) << "[" << label << "] #iteration residue" << std::endl
                                       << "[" << label << "] 0 " << sopt.residue << std::endl;
         if (beta2 < 0 || sopt.residue <= sopt.tol) {
           dis_warning_macro ("beta2 = " << beta2 << " < 0: stop");
           return 0;
         }
         Real beta = sqrt(beta2);
         Real eta = beta;
         Vector Mv = Mr/beta;
         Vector  u =  z/beta;
         Real c_old = 1.;
         Real s_old = 0.;
         Real c = 1.;
         Real s = 0.;
         Vector u_old  (x.ownership(), 0.);
         Vector Mv_old (x.ownership(), 0.);
         Vector w      (x.ownership(), 0.);
         Vector w_old  (x.ownership(), 0.);
         Vector w_old2 (x.ownership(), 0.);
         for (sopt.n_iter = 1; sopt.n_iter <= sopt.max_iter; sopt.n_iter++) {
           // Lanczos
           Mr = A*u;
           z = M.solve(Mr);
           Real alpha = dot(Mr, u);
           Mr = Mr - alpha*Mv - beta*Mv_old;
           z  =  z - alpha*u  - beta*u_old;
           beta2 = dot(Mr, z);
           if (beta2 < 0) {
               dis_warning_macro ("minres: machine precision problem");
               sopt.residue = norm_r/norm_b;
               return 2;
           }
           Real beta_old = beta;
           beta = sqrt(beta2);
           // QR factorisation
           Real c_old2 = c_old;
           Real s_old2 = s_old;
           c_old = c;
           s_old = s;
           Real rho0 = c_old*alpha - c_old2*s_old*beta_old;
           Real rho2 = s_old*alpha + c_old2*c_old*beta_old;
           Real rho1 = sqrt(sqr(rho0) + sqr(beta));
           Real rho3 = s_old2 * beta_old;
           // Givens rotation
           c = rho0 / rho1;
           s = beta / rho1;
           // update
           w_old2 = w_old;
           w_old  = w;
           w = (u - rho2*w_old - rho3*w_old2)/rho1;
           x += c*eta*w;
           eta = -s*eta;
           Mv_old = Mv;
            u_old = u;
           Mv = Mr/beta;
            u =  z/beta;
           // check residue
           norm_r *= s;
           sopt.residue = norm_r/norm_b;
           if (sopt.p_err) (*sopt.p_err) << "[" << label << "] " << sopt.n_iter << " " << sopt.residue << std::endl;
           if (sopt.residue <= sopt.tol) return 0;
         }
         return 1;
       }

COPYRIGHT

       Copyright (C) 2000-2018 Pierre Saramito <Pierre.Saramito@imag.fr> GPLv3+: GNU GPL  version
       3  or  later  <http://gnu.org/licenses/gpl.html>.   This is free software: you are free to
       change and redistribute it.  There is NO WARRANTY, to the extent permitted by law.