computation/solver/iterative/BiCgStab.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 // Copyright (C) 2001-2009 Vivien Mallet
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_FILE_ITERATIVE_BICGSTAB_CXX
00022 
00023 namespace Seldon
00024 {
00025 
00027 
00043   template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00044   int BiCgStab(Matrix1& A, Vector1& x, const Vector1& b,
00045                Preconditioner& M, Iteration<Titer> & iter)
00046   {
00047     const int N = A.GetM();
00048     if (N <= 0)
00049       return 0;
00050 
00051     typedef typename Vector1::value_type Complexe;
00052     Complexe rho_1, rho_2(0), alpha(0), beta, omega(0), sigma;
00053     Vector1 p(b), phat(b), s(b), shat(b), t(b), v(b), r(b), rtilde(b);
00054 
00055     // we initialize iter
00056     int success_init = iter.Init(b);
00057     if (success_init != 0)
00058       return iter.ErrorCode();
00059 
00060     // we compute the residual r = b - Ax
00061     Copy(b, r);
00062     if (!iter.IsInitGuess_Null())
00063       MltAdd(Complexe(-1), A, x, Complexe(1), r);
00064     else
00065       x.Zero();
00066 
00067     Copy(r, rtilde);
00068 
00069     iter.SetNumberIteration(0);
00070     // Loop until the stopping criteria are satisfied
00071     while (! iter.Finished(r))
00072       {
00073 
00074         rho_1 = DotProdConj(rtilde, r);
00075         if (rho_1 == Complexe(0))
00076           {
00077             iter.Fail(1, "Bicgstab breakdown #1");
00078             break;
00079           }
00080 
00081         if (iter.First())
00082           Copy(r, p);
00083         else
00084           {
00085             if (omega == Complexe(0))
00086               {
00087                 iter.Fail(2, "Bicgstab breakdown #2");
00088                 break;
00089               }
00090             // p= r + beta*(p-omega*v)
00091             // beta = rho_i/rho_{i-1} * alpha/omega
00092             beta = (rho_1 / rho_2) * (alpha / omega);
00093             Add(-omega, v, p);
00094             Mlt(beta, p);
00095             Add(Complexe(1), r, p);
00096           }
00097         // preconditioning phat = M^{-1} p
00098         M.Solve(A, p, phat);
00099 
00100         // product matrix vector  v = A*phat
00101         Mlt(A, phat, v);
00102 
00103         // s=r-alpha*v  where alpha = rho_i / (v,rtilde)
00104         sigma = DotProdConj(rtilde, v);
00105         if (sigma == Complexe(0))
00106           {
00107             iter.Fail(3, "Bicgstab breakdown #3");
00108             break;
00109           }
00110         alpha = rho_1 / sigma;
00111         Copy(r, s);
00112         Add(-alpha, v, s);
00113 
00114         // we increment iter, bicgstab has two products matrix vector
00115         ++iter;
00116         if (iter.Finished(s))
00117           {
00118             // x=x+alpha*phat
00119             Add(alpha, phat, x);
00120             break;
00121           }
00122 
00123         // preconditioning shat = M^{-1} s
00124         M.Solve(A, s, shat);
00125 
00126         // product matrix vector t = A*shat
00127         Mlt(A, shat, t);
00128 
00129         omega = DotProdConj(t, s) / DotProdConj(t, t);
00130 
00131         // new iterate x=x+alpha*phat+omega*shat
00132         Add(alpha, phat, x);
00133         Add(omega, shat, x);
00134 
00135         // new residual r=s-omega*t
00136         Copy(s, r);
00137         Add(-omega, t, r);
00138 
00139         rho_2 = rho_1;
00140 
00141         ++iter;
00142       }
00143 
00144     return iter.ErrorCode();
00145   }
00146 
00147 } // end namespace
00148 
00149 #define SELDON_FILE_ITERATIVE_BICGSTAB_CXX
00150 #endif