TBCI Numerical high perf. C++ Library  2.8.0
bicgstab.h
Go to the documentation of this file.
1 
4 /* $Id: bicgstab.h,v 1.16.2.21 2019/05/28 11:13:02 garloff Exp $ */
5 
6 #ifndef TBCI_SOLVER_BICGSTAB_H
7 #define TBCI_SOLVER_BICGSTAB_H
8 
9 #include "tbci/vector.h"
10 #include "tbci/solver/precond.h"
11 
12 #ifdef SOLVER_LOG
13 # include <fstream>
14 # include <iomanip>
15 #endif
16 
17 #ifndef NO_BICGSTAB_RESTART
18 # define BICGSTAB_RESTART
19 #endif
20 
21 /* There was some rather obscure magic to improve convergence, which is
22  * removed now. (KG, 99/06/15)
23  * Unlike the CGS solver, which does weird changes to the vector before
24  * finding a point from which to converge rapidly, the BiCGstab is unlikely
25  * to ever deteriorate the Vector. Drawback is that the approach rate is
26  * getting lower and lower, when the number of iterations increase.
27  * Now the magic comes to play. Whenever we are in such a situation, i.e.
28  * the result isn't improving any longer, we try to detect this ,,stall``
29  * and recalculate some values resulting in a kick to the solver. This
30  * often results in better results.
31  * KG, 99/05/26: I've been talking to experts. The loss in the convergence
32  * rate is likely to be caused by the loss of the orthogonality of the two
33  * base vectors. This should be detectable and solvable.
34  * The magic mentioned above should be removed and replaced by some proper
35  * mechanism.
36  */
37 
39 
40 /* NOTE: Template parameter T and T_tol should really be double (or
41  * similar: float, long double are OK), as fabs() is used, which
42  * returns double. This could be changed to abs(), but will then
43  * cause some trouble for complex numbers.
44  */
45 
46 INST3(template <typename T, Matrix<T>, double> class NN friend \
47 int BiCGSTAB (const Matrix<T> &, Vector<T> &, const Vector<T> &, \
48  const Preconditioner_Sig<T, Matrix<T> > &, unsigned int&, double&, const unsigned);)
49 INST3(template <typename T, BdMatrix<T>, double> class NN friend \
50 int BiCGSTAB (const BdMatrix<T> &, Vector<T> &, const Vector<T> &, \
51  const Preconditioner_Sig<T, BdMatrix<T> > &, unsigned int&, double&, const unsigned);)
52 INST3(template <typename T, Symm_BdMatrix<T>, double> class NN friend \
53 int BiCGSTAB (const Symm_BdMatrix<T> &, Vector<T> &, const Vector<T> &, \
54  const Preconditioner_Sig<T, Symm_BdMatrix<T> > &, unsigned int&, double&, const unsigned);)
55 
56 
90 template < typename T, typename SysMatrix, typename T_tol /*= double*/>
91 int BiCGSTAB (const SysMatrix &A, Vector<T> &x, const Vector<T> &b,
92  const Preconditioner_Sig<T, SysMatrix> &M, unsigned int& max_iter,
93  T_tol& tol, const unsigned off = 0)
94 {
95  const unsigned int dim = A.rows();
96  typename SysMatrix::value_type rho_1, rho_2((typename SysMatrix::value_type)1),
97  alpha((typename SysMatrix::value_type)0), beta,
98  omega((typename SysMatrix::value_type)0);
99  //T rho_1, rho_2, alpha, beta, omega;
100  Vector<T> p(dim), phat(dim), s(dim), shat(dim), t(dim), v(dim);
101 
102  const T_tol tolsqr = TBCI__ sqr(tol);
103  T_tol normbsqr = b.fabssqr();
104  T_tol residsqr;
105 
106  if (normbsqr <= (T_tol)1e-32)
107  normbsqr = T_tol(1e32);
108  else
109  normbsqr = T_tol(1) / normbsqr;
110 
111  Vector<T> r (b - A * x);
112  Vector<T> rtilde (r);
113  //M.update (A);
114 
115  if (LIKELY((residsqr = r.fabssqr() * normbsqr) <= tolsqr)) {
116  tol = MATH__ sqrt(residsqr);
117  max_iter = 0;
118  return 0;
119  }
120  alpha = beta = omega = rho_1 = (typename SysMatrix::value_type)0;
121 #ifdef SOLVER_LOG
122  STD__ ofstream cnvg;
123  if (off) cnvg.open ("bicgstab_cnvg.gnu", STD__ ios::app);
124  else cnvg.open ("bicgstab_cnvg.gnu");
125  cnvg << "# Iter res alpha beta omega rho_1 rho_2 rho_1 / sqr(normb)" << STD__ endl;
126 #endif
127 
128  for (unsigned int i = 1; i <= max_iter; ++i) {
129 #ifdef SOLVER_LOG
130  cnvg << i+off << "\t" << MATH__ sqrt(residsqr) << "\t" << MATH__ fabs(alpha) << "\t" << MATH__ fabs(beta) << "\t"
131  << MATH__ fabs (omega) << "\t" << MATH__ fabs(rho_1) << "\t" << MATH__ fabs(rho_2) << "\t" << MATH__ fabs(rho_1)*normbsqr << "\n";
132 #endif
133  rho_1 = dot (rtilde, r);
134  if (UNLIKELY(rho_1 == (typename SysMatrix::value_type)0)) {
135 #ifdef BICGSTAB_RESTART
136 # ifdef BICGSTAB_REPORT_RESTART
137  STD__ cerr << "BiCGstab failure 2 (iter " << i
138  << ") rho1 == " << rho_1 << ". Restart.\n";
139 # endif
140  // RESTART
141  rtilde = b - A*x; r = rtilde;
142  alpha = 0;
143  continue;
144 #else
145 
146  tol = MATH__ sqrt (residsqr);
147  return 2;
148 #endif
149  }
150  if (UNLIKELY(i == 1))
151  p = r;
152  else {
153  beta = (rho_1 * alpha) / (rho_2 * omega);
154  p = r + beta * (p - omega * v);
155  }
156  phat = M.solve(p);
157  v = A * phat;
158  alpha = rho_1 / dot (rtilde, v);
159  s = r - alpha * v;
160  if ((residsqr = s.fabssqr() * normbsqr) < tolsqr) {
161  x += alpha * phat;
162  max_iter = i; tol = MATH__ sqrt(residsqr);
163  return 0;
164  }
165  shat = M.solve(s);
166  t = A * shat;
167  omega = dot(t,s) / fabssqr(t); //dot(t,t);
168 
169  x += alpha * phat + omega * shat;
170  r = s - omega * t;
171 
172  rho_2 = rho_1;
173 
174  if ((residsqr = r.fabssqr() * normbsqr) < tolsqr) {
175  tol = MATH__ sqrt(residsqr); max_iter = i;
176 #ifdef SOLVER_LOG
177  cnvg << i+off << "\t" << MATH__ sqrt(residsqr) << "\t" << MATH__ fabs(alpha) << "\t" << MATH__ fabs(beta) << "\t"
178  << MATH__ fabs (omega) << "\t" << MATH__ fabs(rho_1) << "\t" << MATH__ fabs(rho_2) << "\t" << MATH__ fabs(rho_1)*normbsqr << STD__ endl;
179 #endif
180  return 0;
181  }
182  if (UNLIKELY(omega == (typename SysMatrix::value_type)0)) {
183  tol = MATH__ sqrt(residsqr);
184  STD__ cerr << "BiCGstab failure 3: omega == 0\n";
185  max_iter = i;
186  return 3;
187  }
188  }
189 
190  tol = MATH__ sqrt (residsqr);
191  return 1;
192 }
193 
195 
196 #endif /* TBCI_SOLVER_BICGSTAB_H */
const Vector< T > const Vector< T > & x
Definition: LM_fit.h:97
Abstract base class for all Preconditioners.
Definition: precond.h:40
const Vector< T > const Vector< T > const Vector< T > & p
Definition: LM_fit.h:97
The class BdMatrix is an implementation to store and do operations on sparse Matrices with a band str...
Definition: band_matrix.h:103
double fabs(const int a)
Definition: basics.h:1215
#define NAMESPACE_TBCI
Definition: basics.h:317
#define UNLIKELY(expr)
Definition: basics.h:101
NAMESPACE_TBCI double class NN friend int BiCGSTAB(const BdMatrix< T > &, Vector< T > &, const Vector< T > &, const Preconditioner_Sig< T, BdMatrix< T > > &, unsigned int &, double &, const unsigned)
double sqrt(const int a)
Definition: basics.h:1216
Matrix class with optimized Matrix-Vector multiplication for symmetrical Matrices.
Definition: symm_bdmatrix.h:25
cplx< T > sqr(const cplx< T > &c)
Definition: cplx.h:449
double fabssqr() const HOT
Definition: vector.h:2399
#define TBCI__
Definition: basics.h:332
F_TMatrix< T > b
Definition: f_matrix.h:736
#define INST3(x, y, z)
Definition: basics.h:240
Definition: bvector.h:49
T dot(const T &a1, const T &a2)
Definition: basics.h:1183
int i
Definition: LM_fit.h:71
#define STD__
Definition: basics.h:338
SysMatrix
Definition: bicgstab.h:90
virtual TVector< T > solve(const Vector< T > &) const =0
#define NAMESPACE_END
Definition: basics.h:323
Definition: bvector.h:54
double fabssqr(const double a)
Definition: basics.h:1157
#define T
Definition: bdmatlib.cc:20
const Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > Vector< T > long int int char v
&lt; find minimun of func on grid with resolution res
Definition: LM_fit.h:205
#define MATH__
Definition: basics.h:339
#define LIKELY(expr)
branch prediction note that we sometimes on purpose mark the unlikely possibility likely and vice ver...
Definition: basics.h:100