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>
61 template<
class L,
class P>
63 double reduction,
int maxit,
int verbose) :
64 ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose)
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!");
74 template<
class L,
class S,
class P>
76 double reduction,
int maxit,
int verbose) :
77 _op(op), _prec(prec), _sp(sp), _reduction(reduction), _maxit(maxit), _verbose(verbose)
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!");
90 virtual void apply (
X& x,
X& b, InverseOperatorResult& res)
92 const double EPSILON=1e-80;
95 field_type rho, rho_new(0), alpha, beta, h, omega;
117 _op.applyscaleadd(-1,x,r);
126 norm = norm_old = norm_0 = _sp.norm(r);
137 std::cout <<
"=== KBiCGSTABSolver" << std::endl;
140 this->printHeader(std::cout);
141 this->printOutput(std::cout,0,norm_0);
147 if ( norm < (_reduction * norm_0) || norm<1E-30)
154 res.elapsed = watch.elapsed();
162 for (it = 0.5; it < _maxit; it+=.5)
169 if(!(it < 1)) rho_new = _sp.dot(rt,r);
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");
186 beta = ( rho_new / rho ) * ( alpha / omega );
199 rho_new = _sp.dot(rt,r);
208 if ( std::abs(h) < EPSILON )
209 DUNE_THROW(ISTLError,
"h=0 in KBiCGSTAB");
228 this->printOutput(std::cout,it,norm,norm_old);
231 if ( norm < (_reduction * norm_0) )
248 omega = _sp.dot(t,r)/_sp.dot(t,t);
268 this->printOutput(std::cout,it,norm,norm_old);
271 if ( norm < (_reduction * norm_0) || norm<1E-30)
281 this->printOutput(std::cout,it,norm);
284 res.iterations =
static_cast<int>(std::ceil(it));
285 res.reduction = norm/norm_0;
286 res.conv_rate = pow(res.reduction,1.0/it);
287 res.elapsed = watch.elapsed();
289 std::cout <<
"=== rate=" << res.conv_rate
290 <<
", T=" << res.elapsed
291 <<
", TIT=" << res.elapsed/it
292 <<
", IT=" << it << std::endl;
300 virtual void apply (
X& x,
X& b,
double reduction, InverseOperatorResult& res)
302 _reduction = reduction;
303 (*this).apply(x,b,res);
307 SeqScalarProduct<X> ssp;
308 LinearOperator<X,X>& _op;
309 Preconditioner<X,X>& _prec;
310 ScalarProduct<X>& _sp;
Statistics about the application of an inverse operator.
KBiCGSTABSolver(L &op, S &sp, P &prec, double reduction, int maxit, int verbose)
Set up solver.
X domain_type
The domain type of the operator to be inverted.
KBiCGSTABSolver(L &op, P &prec, double reduction, int maxit, int verbose)
Set up solver.
X range_type
The range type of the operator to be inverted.
virtual void apply(X &x, X &b, double reduction, InverseOperatorResult &res)
Apply inverse operator with given reduction factor.
virtual void apply(X &x, X &b, InverseOperatorResult &res)
Apply inverse operator.
X::field_type field_type
The field type of the operator to be inverted.