computation/solver/iterative/BiCg.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_BICG_CXX
00022 
00023 namespace Seldon
00024 {
00025 
00027 
00046   template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00047   int BiCg(Matrix1& A, Vector1& x, const Vector1& b,
00048            Preconditioner& M, Iteration<Titer> & iter)
00049   {
00050     int N = A.GetM();
00051     if (N <= 0)
00052       return 0;
00053 
00054     typedef typename Vector1::value_type Complexe;
00055     Complexe rho_1, rho_2(0), alpha, beta, delta;
00056 
00057     Vector1 r(b), z(b), p(b), q(b);
00058     Vector1 r_tilde(b), z_tilde(b), p_tilde(b), q_tilde(b);
00059 
00060     // we initialize iter
00061     int success_init = iter.Init(b);
00062     if (success_init != 0)
00063       return iter.ErrorCode();
00064 
00065     // we compute the residual r = b - Ax
00066     Copy(b, r);
00067     if (!iter.IsInitGuess_Null())
00068       MltAdd(Complexe(-1), A, x, Complexe(1), r);
00069     else
00070       x.Zero();
00071 
00072     Copy(r, r_tilde);
00073 
00074     iter.SetNumberIteration(0);
00075     // Loop until the stopping criteria are reached
00076     while (! iter.Finished(r))
00077       {
00078         // preconditioning z = M^{-1} r and z_tilde = M^{-t} r_tilde
00079         M.Solve(A, r, z);
00080         M.TransSolve(A, r_tilde, z_tilde);
00081         // rho_1 = (z,r_tilde)
00082         rho_1 = DotProd(z, r_tilde);
00083 
00084         if (rho_1 == Complexe(0))
00085           {
00086             iter.Fail(1, "Bicg breakdown #1");
00087             break;
00088           }
00089 
00090         if (iter.First())
00091           {
00092             Copy(z, p);
00093             Copy(z_tilde, p_tilde);
00094           }
00095         else
00096           {
00097             // p=beta*p+z  where beta = rho_i/rho_{i-1}
00098             // p_tilde=beta*p_tilde+z_tilde
00099             beta = rho_1 / rho_2;
00100             Mlt(beta, p);
00101             Add(Complexe(1), z, p);
00102             Mlt(beta, p_tilde);
00103             Add(Complexe(1), z_tilde, p_tilde);
00104           }
00105 
00106         // we do the product matrix vector and transpose matrix vector
00107         // q = A*p    q_tilde = A^t p_tilde
00108         Mlt(A, p, q);
00109         ++iter;
00110         Mlt(SeldonTrans, A, p_tilde, q_tilde);
00111 
00112         delta = DotProd(p_tilde, q);
00113         if (delta == Complexe(0))
00114           {
00115             iter.Fail(2, "Bicg breakdown #2");
00116             break;
00117           }
00118 
00119         alpha = rho_1 / delta;
00120 
00121         // the new iterate x=x+alpha*p and residual r=r-alpha*q
00122         // where alpha = rho_i/delta
00123         Add(alpha, p, x);
00124         Add(-alpha, q, r);
00125         Add(-alpha, q_tilde, r_tilde);
00126 
00127         rho_2 = rho_1;
00128 
00129         ++iter;
00130       }
00131 
00132     return iter.ErrorCode();
00133   }
00134 
00135 }
00136 
00137 #define SELDON_FILE_ITERATIVE_BICG_CXX
00138 #endif