10#include "dune/istl/solvers.hh"
11#include "dune/istl/istlexception.hh"
12#include "dune/istl/operators.hh"
13#include "dune/istl/preconditioners.hh"
14#include "dune/istl/scalarproducts.hh"
15#include <dune/common/timer.hh>
16#include <dune/common/static_assert.hh>
53 template<
class L,
class P>
54 RestartedFGMResSolver (L& op, P& prec,
double reduction,
int restart,
int maxit,
int verbose,
bool recalc_defect =
false) :
56 ssp(), _sp(ssp), _restart(restart),
57 _reduction(reduction), _maxit(maxit), _verbose(verbose),
58 _recalc_defect(recalc_defect)
60 dune_static_assert(
static_cast<int>(P::category) ==
static_cast<int>(SolverCategory::sequential),
61 "P must be sequential!");
62 dune_static_assert(
static_cast<int>(L::category) ==
static_cast<int>(SolverCategory::sequential),
63 "L must be sequential!");
73 template<
class L,
class S,
class P>
74 RestartedFGMResSolver (L& op, S& sp, P& prec,
double reduction,
int restart,
int maxit,
int verbose,
bool recalc_defect =
false) :
76 _sp(sp), _restart(restart),
77 _reduction(reduction), _maxit(maxit), _verbose(verbose),
78 _recalc_defect(recalc_defect)
80 dune_static_assert(
static_cast<int>(P::category) ==
static_cast<int>(SolverCategory::sequential),
81 "P must be sequential!");
82 dune_static_assert(
static_cast<int>(L::category) ==
static_cast<int>(SolverCategory::sequential),
83 "L must be sequential!");
87 virtual void apply (
X& x,
X& b, Dune::InverseOperatorResult& res)
89 apply(x,b,_reduction,res);
97 virtual void apply (
X& x,
Y& b,
double reduction, Dune::InverseOperatorResult& res)
105 std::vector<field_type> s(m+1), cs(m), sn(m);
106 std::vector<field_type> sw(m+1), csw(m), snw(m);
109 std::vector< std::vector<field_type> > H(m+1,s), Hw(m+1,s);
110 std::vector<F> v(1,b);
111 std::vector<X> w(1,b);
121 norm_0 = _sp.norm(b);
123 _A_.applyscaleadd(-1,x,b);
130 beta = _sp.norm(v[0]);
137 norm = norm_old = _sp.norm(v[0]);
142 std::cout <<
"=== RestartedGMResSolver" << std::endl;
145 this->printHeader(std::cout);
146 this->printOutput(std::cout,0,norm);
151 if (norm <= reduction * norm_0) {
153 res.converged =
true;
159 while (j <= _maxit && res.converged !=
true) {
160 v[0] *= (1.0 / beta);
161 for (i=1; i<=m; i++) s[i] = 0.0;
164 for (i = 0; i < m && j <= _maxit && res.converged !=
true; i++, j++) {
165 if(w.size()<i+1) w.push_back(b);
167 if(v.size()<i+2) v.push_back(b);
169 _M.apply(w[i], v[i]);
170 _A_.apply(w[i], v[i+1]);
171 for (k = 0; k <= i; k++) {
172 H[k][i] = _sp.dot(v[i+1], v[k]);
174 v[i+1].axpy(-H[k][i], v[k]);
176 H[i+1][i] = _sp.norm(v[i+1]);
177 if (H[i+1][i] == 0.0)
178 DUNE_THROW(ISTLError,
"breakdown in GMRes - |w| "
179 << w[i] <<
" == 0.0 after " << j <<
" iterations");
181 v[i+1] *= (1.0 / H[i+1][i]);
183 for (k = 0; k < i; k++)
184 applyPlaneRotation(H[k][i], H[k+1][i], cs[k], sn[k]);
186 generatePlaneRotation(H[i][i], H[i+1][i], cs[i], sn[i]);
187 applyPlaneRotation(H[i][i], H[i+1][i], cs[i], sn[i]);
188 applyPlaneRotation(s[i], s[i+1], cs[i], sn[i]);
190 norm = std::abs(s[i+1]);
194 this->printOutput(std::cout,j,norm,norm_old);
199 if (norm < reduction * norm_0) {
200 res.converged =
true;
206 update(tmp, i - 1, H, s, w);
209 std::cout <<
"|dx|:" << _sp.norm(tmp) <<
" " << std::flush;
214 _A_.applyscaleadd(-1,tmp, b);
222 res.converged =
false;
226 if (norm < reduction * norm_0) {
228 res.converged =
true;
231 if (res.converged !=
true && _verbose > 0)
232 std::cout <<
"=== GMRes::restart\n";
238 res.reduction = norm / norm_0;
239 res.conv_rate = pow(res.reduction,1.0/j);
240 res.elapsed = watch.elapsed();
248 print_result (
const Dune::InverseOperatorResult & res)
const
250 int j = res.iterations>0?res.iterations:1;
251 std::cout <<
"=== rate=" << res.conv_rate
252 <<
", T=" << res.elapsed
253 <<
", TIT=" << res.elapsed/j
254 <<
", IT=" << res.iterations
260 std::vector< std::vector<field_type> > & h,
261 std::vector<field_type> & s, std::vector<F> v)
263 std::vector<field_type> y(s);
266 for (
int i = k; i >= 0; i--) {
268 for (
int j = i - 1; j >= 0; j--)
269 y[j] -= h[j][i] * y[i];
272 for (
int j = 0; j <= k; j++)
283 }
else if (std::abs(dy) > std::abs(dx)) {
285 sn = 1.0 / std::sqrt( 1.0 + temp*temp );
289 cs = 1.0 / std::sqrt( 1.0 + temp*temp );
299 dy = -sn * dx + cs * dy;
303 Dune::LinearOperator<X,X>& _A_;
304 Dune::Preconditioner<X,X>& _M;
305 Dune::SeqScalarProduct<X> ssp;
306 Dune::ScalarProduct<X>& _sp;
implements the Generalized Minimal Residual (GMRes) method
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
X::field_type field_type
The field type of the operator to be inverted.
Y range_type
The range type of the operator to be inverted.
F basis_type
The field type of the basis vectors.
virtual void apply(X &x, Y &b, double reduction, Dune::InverseOperatorResult &res)
Apply inverse operator.
X domain_type
The domain type of the operator to be inverted.
RestartedFGMResSolver(L &op, S &sp, P &prec, double reduction, int restart, int maxit, int verbose, bool recalc_defect=false)
Set up solver.
RestartedFGMResSolver(L &op, P &prec, double reduction, int restart, int maxit, int verbose, bool recalc_defect=false)
Set up solver.