MFEM v2.0
bicgstab.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 #include <iostream>
00013 #include <iomanip>
00014 #include "vector.hpp"
00015 #include "matrix.hpp"
00016 
00017 //*****************************************************************
00018 // Iterative template routine -- BiCGSTAB
00019 //
00020 // BiCGSTAB solves the unsymmetric linear system Ax = b
00021 // using the Preconditioned BiConjugate Gradient Stabilized method
00022 //
00023 // BiCGSTAB follows the algorithm described on p. 27 of the
00024 // SIAM Templates book.
00025 //
00026 // The return value indicates convergence within max_iter (input)
00027 // iterations (0), or no convergence within max_iter iterations (1).
00028 //
00029 // Upon successful return, output arguments have the following values:
00030 //
00031 //        x  --  approximate solution to Ax = b
00032 // max_iter  --  the number of iterations performed before the
00033 //               tolerance was reached
00034 //      tol  --  the residual after the final iteration
00035 //
00036 //*****************************************************************
00037 
00038 int
00039 BiCGSTAB(const Operator &A, Vector &x, const Vector &b,
00040          const Operator &M, int &max_iter, double &tol,
00041          double atol, int printit)
00042 {
00043    int i, n = A.Size();
00044    double resid;
00045    double rho_1, rho_2=1.0, alpha=1.0, beta, omega=1.0;
00046    Vector p(n), phat(n), s(n), shat(n), t(n), v(n), r(n), rtilde(n);
00047 
00048    A.Mult (x, r);  //  r = A * x
00049    subtract (b, r, r);  //  r = b - r
00050    rtilde = r;
00051 
00052    resid = (r * r);
00053    if (printit)
00054       cout << "   iter " << 0 << ",   (r, r) = " << resid << endl;
00055    tol *= resid;
00056    tol = (atol > tol) ? atol : tol;
00057 
00058    if (resid <= tol)
00059    {
00060       tol = resid;
00061       max_iter = 0;
00062       return 0;
00063    }
00064 
00065    for (i = 1; i <= max_iter; i++)
00066    {
00067       rho_1 = rtilde * r;
00068       if (rho_1 == 0)
00069       {
00070          tol = resid;
00071          if (printit)
00072             cout << "   iter " << i << ",   (r, r) = " << resid << endl;
00073          return 2;
00074       }
00075       if (i == 1)
00076          p = r;
00077       else
00078       {
00079          beta = (rho_1/rho_2) * (alpha/omega);
00080          add (p, -omega, v, p);  //  p = p - omega * v
00081          add (r, beta, p, p);    //  p = r + beta * p
00082       }
00083       M.Mult (p, phat);  //  phat = M^{-1} * p
00084       A.Mult (phat, v);  //  v = A * phat
00085       alpha = rho_1 / (rtilde * v);
00086       add (r, -alpha, v, s);  //  s = r - alpha * v
00087       resid = (s * s);
00088       if (resid < tol)
00089       {
00090          x.Add (alpha, phat);  //  x = x + alpha * phat
00091          tol = resid;
00092          if (printit)
00093             cout << "   iter " << i << ",   (s, s) = " << resid << endl;
00094          return 0;
00095       }
00096       if (printit)
00097          cout << "   iter " << i << ",   (s, s) = " << resid << ";   ";
00098       M.Mult (s, shat);  //  shat = M^{-1} * s
00099       A.Mult (shat, t);  //  t = A * shat
00100       omega = (t * s) / (t * t);
00101       x.Add (alpha, phat);  //  x += alpha * phat
00102       x.Add (omega, shat);  //  x += omega * shat
00103       add (s, -omega, t, r);  //  r = s - omega * t
00104 
00105       rho_2 = rho_1;
00106       resid = (r * r);
00107       if (printit)
00108          cout << "(r, r) = " << resid << endl;
00109       if (resid < tol)
00110       {
00111          tol = resid;
00112          max_iter = i;
00113          return 0;
00114       }
00115       if (omega == 0)
00116       {
00117          tol = resid;
00118          return 3;
00119       }
00120    }
00121 
00122    tol = resid;
00123    return 1;
00124 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines