KASKADE 7 development version
pcg.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copied from dune/istl/solvers.hh and adapted to NM III notation */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef NMIII_PCG_HH
14#define NMIII_PCG_HH
15
16#include "dune/istl/solvers.hh"
17#include "dune/istl/istlexception.hh"
18#include "dune/istl/operators.hh"
19#include "dune/istl/preconditioners.hh"
20#include "dune/istl/scalarproducts.hh"
21
22namespace Kaskade {
23
25 template<class X>
26 class NMIIIPCGSolver : public Dune::InverseOperator<X,X> {
27 public:
29 typedef X domain_type;
31 typedef X range_type;
33 typedef typename X::field_type field_type;
34
40 template<class L, class P>
41 NMIIIPCGSolver (L& op, P& prec, double reduction, int maxit, int verbose) :
42 ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose)
43 {
44 static_assert( static_cast<int>(L::category) == static_cast<int>(P::category),
45 "L and P must have the same category!");
46 static_assert( static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
47 "L must be sequential!");
48 }
49
55 virtual void apply (X& u, X& b, Dune::InverseOperatorResult& res)
56 {
57 res.clear(); // clear solver statistics
58 Dune::Timer watch; // start a timer
59
60 X r(u);
61 X rq(u);
62 X q(u);
63 X h(u);
64
65 r = b;
66 _op.applyscaleadd(-1,u,r); // r = r-Au
67 rq = 0;
68 _prec.apply(rq,r);
69 q = rq;
70
71 double def0 = _sp.norm(rq);// compute norm
72 if (def0<1E-30) // convergence check
73 {
74 res.converged = true;
75 res.iterations = 0; // fill statistics
76 res.reduction = 0;
77 res.conv_rate = 0;
78 res.elapsed=0;
79 if (_verbose>0) // final print
80 std::cout << "=== rate=" << res.conv_rate
81 << ", T=" << res.elapsed << ", TIT=" << res.elapsed
82 << ", IT=0" << std::endl;
83 return;
84 }
85
86 if (_verbose>0) // printing
87 {
88 std::cout << "=== NMIIIPCGSolver" << std::endl;
89 if (_verbose>1) {
90 this->printHeader(std::cout);
91 this->printOutput(std::cout,(double) 0,def0);
92 }
93 }
94
95 // some local variables
96 double def=def0, defnew=def0; // loop variables
97 field_type alpha,beta,sigma;
98 sigma = _sp.dot(r,rq);
99
100 // the loop
101 int i=1;
102 for ( ; i<=_maxit; i++ )
103 {
104 // minimize in given search direction p
105 _op.apply(q,h); // h=Aq
106 alpha = sigma/_sp.dot(q,h); // scalar product
107 u.axpy(alpha,q); // update solution
108
109 // convergence test
110
111 if (_verbose>1) // print
112 this->printOutput(std::cout,(double) i,defnew,def);
113
114 if (defnew<sqrt(_reduction) || def<1E-30) // convergence check
115 {
116 res.converged = true;
117 break;
118 }
119
120 r.axpy(-alpha,h);
121 rq = 0;
122 _prec.apply(rq,r);
123
124 defnew=_sp.norm(rq); // comp defect norm
125
126 // determine new search direction
127 double sigmaNew = _sp.dot(r,rq);
128 beta = sigmaNew/sigma;
129 sigma = sigmaNew;
130 q *= beta; // scale old search direction
131 q += rq; // orthogonalization with correction
132 def = defnew; // update norm
133 }
134
135 if (_verbose>0) // printing for non verbose
136 this->printOutput(std::cout,(double) i,def);
137
138 res.iterations = i; // fill statistics
139 res.reduction = def/def0;
140 res.conv_rate = pow(res.reduction,1.0/i);
141 res.elapsed = watch.elapsed();
142
143 if (_verbose>0) // final print
144 {
145 std::cout << "=== rate=" << res.conv_rate
146 << ", T=" << res.elapsed
147 << ", TIT=" << res.elapsed/i
148 << ", IT=" << i << std::endl;
149 }
150 }
151
157 virtual void apply (X& x, X& b, double reduction, Dune::InverseOperatorResult& res)
158 {
159 _reduction = reduction;
160 (*this).apply(x,b,res);
161 }
162
163 private:
164 Dune::SeqScalarProduct<X> ssp;
165 Dune::LinearOperator<X,X>& _op;
166 Dune::Preconditioner<X,X>& _prec;
167 Dune::ScalarProduct<X>& _sp;
168 double _reduction;
169 int _maxit;
170 int _verbose;
171 };
172}
173#endif
conjugate gradient method
Definition: pcg.hh:26
virtual void apply(X &u, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: pcg.hh:55
X domain_type
The domain type of the operator to be inverted.
Definition: pcg.hh:29
X::field_type field_type
The field type of the operator to be inverted.
Definition: pcg.hh:33
NMIIIPCGSolver(L &op, P &prec, double reduction, int maxit, int verbose)
Set up conjugate gradient solver.
Definition: pcg.hh:41
X range_type
The range type of the operator to be inverted.
Definition: pcg.hh:31
virtual void apply(X &x, X &b, double reduction, Dune::InverseOperatorResult &res)
Apply inverse operator with given reduction factor.
Definition: pcg.hh:157