BiCgStabl.cxx
1 // Copyright (C) 2003-2009 Marc DuruflĂ©
2 // Copyright (C) 2001-2009 Vivien Mallet
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_ITERATIVE_BICGSTABL_CXX
22 
23 namespace Seldon
24 {
25 
27 
43 #ifdef SELDON_WITH_VIRTUAL
44  template<class T, class Vector1>
45  int BiCgStabl(const VirtualMatrix<T>& A, Vector1& x, const Vector1& b,
46  Preconditioner_Base<T>& M,
47  Iteration<typename ClassComplexType<T>::Treal>& iter)
48 #else
49  template <class Titer, class Matrix1, class Vector1, class Preconditioner>
50  int BiCgStabl(const Matrix1& A, Vector1& x, const Vector1& b,
51  Preconditioner& M, Iteration<Titer> & iter)
52 #endif
53  {
54  const int N = A.GetM();
55  if (N <= 0)
56  return 0;
57 
58  typedef typename Vector1::value_type Complexe;
59  int m = iter.GetRestart();
60  int l = m;
61  Complexe rho_0, rho_1, alpha, beta, omega, sigma, zero, one;
62  SetComplexZero(zero);
63  SetComplexOne(one);
64 
65  // q temporary vector before preconditioning, r0 initial residual
66  Vector1 q(b), r0(b);
67  Vector<Complexe> gamma(l+1), gamma_prime(l+1), gamma_twice(l+1);
69  // history of u and residual r
70  std::vector<Vector1> r(l+1, b), u(l+1, b);
71  for (int i = 0; i <= l; i++)
72  {
73  r[i].Fill(zero);
74  u[i].Fill(zero);
75  }
76 
77  tau.Fill(zero); gamma.Fill(zero);
78  gamma_prime.Fill(zero); gamma_twice.Fill(zero);
79 
80  // we compute the residual r = (b - Ax)
81  Copy(b, r[0]);
82  if (!iter.IsInitGuess_Null())
83  iter.MltAdd(-one, A, x, one, r[0]);
84  else
85  x.Fill(zero);
86 
87  // we initialize iter
88  int success_init = iter.Init(b);
89  if (success_init !=0 )
90  return iter.ErrorCode();
91 
92  Copy(r[0], r0); // we keep the first residual
93 
94  // we initialize constants
95  rho_0 = one; alpha = zero; omega = one;
96  tau.Fill(zero);
97 
98  iter.SetNumberIteration(0);
99  // Loop until the stopping criteria are satisfied
100  while (! iter.Finished(r[0]))
101  {
102  rho_0 *= -omega;
103 
104  // Bi-CG Part
105  for (int j = 0; j < l; j++)
106  {
107  rho_1 = DotProd(r[j], r0);
108  if (rho_0 == zero)
109  {
110  iter.Fail(1, "Bicgstabl breakdown #1");
111  break;
112  }
113  beta = alpha*(rho_1/rho_0);
114  rho_0 = rho_1;
115  for (int i = 0; i <= j; i++)
116  {
117  Mlt(-beta, u[i]);
118  Add(one, r[i], u[i]);
119  }
120 
121  M.Solve(A, u[j], q); // preconditioning
122  iter.Mlt(A, q, u[j+1]); // product Matrix Vector
123 
124  ++iter;
125  sigma = DotProd(u[j+1], r0);
126  if (sigma == zero)
127  {
128  iter.Fail(2, "Bicgstabl Breakdown #2");
129  break;
130  }
131  alpha = rho_1/sigma;
132  Add(alpha, u[0], x);
133  for (int i = 0; i <= j; i++)
134  Add(-alpha, u[i+1], r[i]);
135 
136  M.Solve(A, r[j], q); // preconditioning
137  iter.Mlt(A, q, r[j+1]); // product matrix vector
138 
139  ++iter;
140  }
141 
142  // MR Part modified Gram-Schmidt
143  for (int j = 1; j <= l; j++)
144  {
145  for (int i = 1; i < j; i++)
146  {
147  if (gamma(i) != zero)
148  {
149  tau(i,j) = DotProd(r[j], r[i])/gamma(i);
150  Add(-tau(i,j), r[i], r[j]);
151  }
152  }
153  gamma(j) = DotProd(r[j], r[j]);
154  if (gamma(j) != zero)
155  gamma_prime(j) = DotProd(r[0], r[j])/gamma(j);
156  }
157 
158  // gamma = tau-1 * gamma_prime
159  gamma(l) = gamma_prime(l); omega = gamma(l);
160  for (int j = l-1; j >= 1; j--)
161  {
162  sigma = zero;
163  for (int i = j+1; i <= l; i++)
164  sigma += tau(j,i)*gamma(i);
165 
166  gamma(j) = gamma_prime(j)-sigma;
167  }
168 
169  // gamma_twice=T*S*gamma
170  for (int j = 1; j <= l-1; j++)
171  {
172  sigma = zero;
173  for (int i = j+1; i <= l-1; i++)
174  sigma += tau(j,i)*gamma(i+1);
175 
176  gamma_twice(j) = gamma(j+1)+sigma;
177  }
178 
179  // update
180  Add(gamma(1), r[0], x);
181  Add(-gamma_prime(l), r[l], r[0]);
182  Add(-gamma(l), u[l], u[0]);
183  for (int j = 1;j <= l-1; j++)
184  {
185  Add(-gamma(j), u[j], u[0]);
186  Add(gamma_twice(j), r[j], x);
187  Add(-gamma_prime(j), r[j], r[0]);
188  }
189  }
190  // change of coordinates (right preconditioning)
191  Copy(x,q); M.Solve(A, q, x);
192  return iter.ErrorCode();
193  }
194 
195 }
196 
197 #define SELDON_FILE_ITERATIVE_BICGSTABL_CXX
198 #endif
Seldon::Iteration::GetRestart
int GetRestart() const
Returns the restart parameter.
Definition: Iterative.cxx:110
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::Iteration::Init
int Init(const Vector1 &r)
Initialization with the right hand side.
Definition: Iterative.cxx:218
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Iteration::Mlt
void Mlt(const Matrix1 &A, const Vector1 &x, Vector1 &y)
Computes y = A x.
Definition: IterativeInline.cxx:123
Seldon::Iteration::ErrorCode
int ErrorCode()
Returns the error code (if an error occured)
Definition: Iterative.cxx:351
Seldon::Iteration::Fail
void Fail(int i, const string &s)
Informs of a failure in the iterative solver.
Definition: Iterative.cxx:330
Seldon::Iteration::MltAdd
void MltAdd(const T1 &alpha, const Matrix1 &A, const Vector1 &x, const T1 &beta, Vector1 &y)
Computes y = beta y + alpha A x.
Definition: IterativeInline.cxx:109
Seldon::Iteration::SetNumberIteration
void SetNumberIteration(int nb)
Changes the number of iterations.
Definition: Iterative.cxx:177
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::Iteration
Class containing parameters for an iterative resolution.
Definition: Iterative.hxx:59
Seldon::BiCgStabl
int BiCgStabl(const Matrix1 &A, Vector1 &x, const Vector1 &b, Preconditioner &M, Iteration< Titer > &iter)
Implements BiConjugate Gradient Stabilized (BICG-STAB(l))
Definition: BiCgStabl.cxx:50
Seldon::Iteration::IsInitGuess_Null
bool IsInitGuess_Null() const
Returns true if the initial guess is null.
Definition: Iterative.cxx:247
Seldon::Iteration::Finished
bool Finished(const Vector1 &r) const
Returns true if the iterative solver has reached its end.
Definition: Iterative.cxx:264