KASKADE 7 development version
bicgstab.hh
Go to the documentation of this file.
1#ifndef BICGSTAB_HH
2#define BICGSTAB_HH
3
4#include<cmath>
5#include<complex>
6#include<iostream>
7#include<iomanip>
8#include<string>
9
10#include "dune/istl/istlexception.hh"
11#include "dune/istl/operators.hh"
12#include "dune/istl/preconditioners.hh"
13#include "dune/istl/scalarproducts.hh"
14#include <dune/common/timer.hh>
15#include <dune/common/static_assert.hh>
16
44 // Ronald Kriemanns BiCG-STAB implementation from Sumo
46 template<class X>
47 class KBiCGSTABSolver : public InverseOperator<X,X> {
48 public:
50 typedef X domain_type;
52 typedef X range_type;
54 typedef typename X::field_type field_type;
55
61 template<class L, class P>
62 KBiCGSTABSolver (L& op, P& prec,
63 double reduction, int maxit, int verbose) :
64 ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose)
65 {
66 dune_static_assert(static_cast<int>(L::category) == static_cast<int>(P::category), "L and P must be of the same category!");
67 dune_static_assert(static_cast<int>(L::category) == static_cast<int>(SolverCategory::sequential), "L must be sequential!");
68 }
74 template<class L, class S, class P>
75 KBiCGSTABSolver (L& op, S& sp, P& prec,
76 double reduction, int maxit, int verbose) :
77 _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose)
78 {
79 dune_static_assert( static_cast<int>(L::category) == static_cast<int>(P::category),
80 "L and P must have the same category!");
81 dune_static_assert( static_cast<int>(L::category) == static_cast<int>(S::category),
82 "L and S must have the same category!");
83 }
84
90 virtual void apply (X& x, X& b, InverseOperatorResult& res)
91 {
92 const double EPSILON=1e-80;
93
94 double it;
95 field_type rho, rho_new(0), alpha, beta, h, omega;
96 field_type norm, norm_old, norm_0;
97
98 //
99 // get vectors and matrix
100 //
101 X& r=b;
102 X p(r);
103 X v(r);
104 X t(r);
105 X y(r);
106 X rt(r);
107
108 //
109 // begin iteration
110 //
111
112 // r = r - Ax; rt = r
113 res.clear(); // clear solver statistics
114 Timer watch; // start a timer
115 _prec.pre(x,r); // prepare preconditioner
116 if(x.size()!=0)
117 _op.applyscaleadd(-1,x,r); // overwrite b with defect
118 else
119 {
120 x.resize(r.size());
121 x=0.0;
122 }
123
124 rt=r;
125
126 norm = norm_old = norm_0 = _sp.norm(r);
127
128 p=0;
129 v=0;
130
131 rho = 1;
132 alpha = 1;
133 omega = 1;
134
135 if (_verbose>0) // printing
136 {
137 std::cout << "=== KBiCGSTABSolver" << std::endl;
138 if (_verbose>1)
139 {
140 this->printHeader(std::cout);
141 this->printOutput(std::cout,0,norm_0);
142 //std::cout << " Iter Defect Rate" << std::endl;
143 //std::cout << " 0" << std::setw(14) << norm_0 << std::endl;
144 }
145 }
146
147 if ( norm < (_reduction * norm_0) || norm<1E-30)
148 {
149 res.converged = 1;
150 _prec.post(x); // postprocess preconditioner
151 res.iterations = 0; // fill statistics
152 res.reduction = 0;
153 res.conv_rate = 0;
154 res.elapsed = watch.elapsed();
155 return;
156 }
157
158 //
159 // iteration
160 //
161
162 for (it = 0.5; it < _maxit; it+=.5)
163 {
164 //
165 // preprocess, set vecsizes etc.
166 //
167
168 // rho_new = < rt , r >
169 if(!(it < 1)) rho_new = _sp.dot(rt,r);
170
171 // look if breakdown occured
172 if (std::abs(rho) <= EPSILON)
173 DUNE_THROW(ISTLError,"breakdown in KBiCGSTAB - rho "
174 << rho << " <= EPSILON " << EPSILON
175 << " after " << it << " iterations");
176 if (std::abs(omega) <= EPSILON)
177 DUNE_THROW(ISTLError,"breakdown in KBiCGSTAB - omega "
178 << omega << " <= EPSILON " << EPSILON
179 << " after " << it << " iterations");
180
181
182 if (it<1)
183 p = r;
184 else
185 {
186 beta = ( rho_new / rho ) * ( alpha / omega );
187 p.axpy(-omega,v); // p = r + beta (p - omega*v)
188 p *= beta;
189 p += r;
190 }
191
192 // y = W^-1 * p
193 y = 0;
194 _prec.apply(y,p); // apply preconditioner
195
196 if(it < 1)
197 {
198 rt=r;
199 rho_new = _sp.dot(rt,r);
200 }
201
202 // v = A * y
203 _op.apply(y,v);
204
205 // alpha = rho_new / < rt, v >
206 h = _sp.dot(rt,v);
207
208 if ( std::abs(h) < EPSILON )
209 DUNE_THROW(ISTLError,"h=0 in KBiCGSTAB");
210
211 alpha = rho_new / h;
212
213 // apply first correction to x
214 // x <- x + alpha y
215 x.axpy(alpha,y);
216
217 // r = r - alpha*v
218 r.axpy(-alpha,v);
219
220 //
221 // test stop criteria
222 //
223
224 norm = _sp.norm(r);
225
226 if (_verbose>1) // print
227 {
228 this->printOutput(std::cout,it,norm,norm_old);
229 }
230
231 if ( norm < (_reduction * norm_0) )
232 {
233 res.converged = 1;
234 break;
235 }
236 it+=.5;
237
238 norm_old = norm;
239
240 // y = W^-1 * r
241 y = 0;
242 _prec.apply(y,r);
243
244 // t = A * y
245 _op.apply(y,t);
246
247 // omega = < t, r > / < t, t >
248 omega = _sp.dot(t,r)/_sp.dot(t,t);
249// omega = _sp.dot(t,r)/_sp.dot(y,t);
250
251 // apply second correction to x
252 // x <- x + omega y
253 x.axpy(omega,y);
254
255 // r = s - omega*t (remember : r = s)
256 r.axpy(-omega,t);
257
258 rho = rho_new;
259
260 //
261 // test stop criteria
262 //
263
264 norm = _sp.norm(r);
265
266 if (_verbose > 1) // print
267 {
268 this->printOutput(std::cout,it,norm,norm_old);
269 }
270
271 if ( norm < (_reduction * norm_0) || norm<1E-30)
272 {
273 res.converged = 1;
274 break;
275 }
276
277 norm_old = norm;
278 } // end for
279
280 if (_verbose>0) // printing for non verbose
281 this->printOutput(std::cout,it,norm);
282
283 _prec.post(x); // postprocess preconditioner
284 res.iterations = static_cast<int>(std::ceil(it)); // fill statistics
285 res.reduction = norm/norm_0;
286 res.conv_rate = pow(res.reduction,1.0/it);
287 res.elapsed = watch.elapsed();
288 if (_verbose>0) // final print
289 std::cout << "=== rate=" << res.conv_rate
290 << ", T=" << res.elapsed
291 << ", TIT=" << res.elapsed/it
292 << ", IT=" << it << std::endl;
293 }
294
300 virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res)
301 {
302 _reduction = reduction;
303 (*this).apply(x,b,res);
304 }
305
306 private:
307 SeqScalarProduct<X> ssp;
308 LinearOperator<X,X>& _op;
309 Preconditioner<X,X>& _prec;
310 ScalarProduct<X>& _sp;
311 double _reduction;
312 int _maxit;
313 int _verbose;
314 };
315
316
317#endif
Statistics about the application of an inverse operator.
Definition: bicgstab.hh:47
KBiCGSTABSolver(L &op, S &sp, P &prec, double reduction, int maxit, int verbose)
Set up solver.
Definition: bicgstab.hh:75
X domain_type
The domain type of the operator to be inverted.
Definition: bicgstab.hh:50
KBiCGSTABSolver(L &op, P &prec, double reduction, int maxit, int verbose)
Set up solver.
Definition: bicgstab.hh:62
X range_type
The range type of the operator to be inverted.
Definition: bicgstab.hh:52
virtual void apply(X &x, X &b, double reduction, InverseOperatorResult &res)
Apply inverse operator with given reduction factor.
Definition: bicgstab.hh:300
virtual void apply(X &x, X &b, InverseOperatorResult &res)
Apply inverse operator.
Definition: bicgstab.hh:90
X::field_type field_type
The field type of the operator to be inverted.
Definition: bicgstab.hh:54