KASKADE 7 development version
mg/apcg.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_APCG_HH
14#define NMIII_APCG_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 NMIIIAPCGSolver : 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 NMIIIAPCGSolver (L& op, P& prec, double reduction, int maxit, int verbose, int addedIterations = 2) :
42 ssp(), _op(op), _prec(prec), _sp(ssp), _reduction(reduction), _maxit(maxit), _verbose(verbose), _addedIterations(addedIterations)
43 {
44 gammas.resize(_addedIterations);
45 allGammas.resize(_maxit);
46 allEstimates.resize(_maxit);
47 int k;
48 for (k=0; k<_addedIterations; k++) gammas[k] = 0.0;
49 for (k=0; k<_maxit; k++) allGammas[k] = allEstimates[k] = 0.0;
50 static_assert( static_cast<int>(L::category) == static_cast<int>(P::category),
51 "L and P must have the same category!");
52 static_assert( static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
53 "L must be sequential!");
54 }
55
61 virtual void apply (X& u, X& b, Dune::InverseOperatorResult& res)
62 {
63 res.clear(); // clear solver statistics
64 Dune::Timer watch; // start a timer
65
66 X r(u);
67 X rq(u);
68 X q(u);
69 X h(u);
70
71 r = b;
72 _op.applyscaleadd(-1,u,r); // r = r-Au
73 rq = 0;
74 _prec.apply(rq,r);
75 q = rq;
76
77 double def0 = _sp.norm(rq);// compute norm
78 if (def0<1E-30) // convergence check
79 {
80 res.converged = true;
81 res.iterations = 0; // fill statistics
82 res.reduction = 0;
83 res.conv_rate = 0;
84 res.elapsed=0;
85 if (_verbose>0) // final print
86 std::cout << "=== rate=" << res.conv_rate
87 << ", T=" << res.elapsed << ", TIT=" << res.elapsed
88 << ", IT=0" << std::endl;
89 return;
90 }
91
92 if (_verbose>0) // printing
93 {
94 std::cout << "=== NMIIIAPCGSolver" << std::endl;
95 if (_verbose>1) {
96 this->printHeader(std::cout);
97 this->printOutput(std::cout,(double) 0,def0);
98 }
99 }
100
101 // some local variables
102 double def=def0, defnew=def0; // loop variables
103 field_type alpha,beta,sigma,gamma;
104 sigma = _sp.dot(r,rq);
105
106 // the loop
107 int i=1;
108 double eps0 = 0.0, epsk;
109 for ( ; i<=_maxit; i++ )
110 {
111 // minimize in given search direction p
112 _op.apply(q,h); // h=Aq
113 alpha = sigma/_sp.dot(q,h);
114 u.axpy(alpha,q);
115 gamma = sigma*alpha;
116 gammas[i%_addedIterations] = gamma;
117 allGammas[i] = gamma;
118
119 // convergence test
120
121 if (_verbose>1) // print
122 this->printOutput(std::cout,(double) i,defnew,def);
123
124 if (i==_addedIterations)
125 {
126 for (i=0; i<_addedIterations; i++)
127 eps0 += gammas[i];
128 allEstimates[_addedIterations] = eps0;
129 }
130
131 if (i>_addedIterations)
132 {
133 epsk = 0.0;
134 for (int k=0; k<_addedIterations; k++)
135 epsk += gammas[k];
136 allEstimates[i] = epsk;
137 if (epsk<=_reduction)
138 {
139 break;
140 }
141 }
142
143 r.axpy(-alpha,h);
144 rq = 0;
145 _prec.apply(rq,r);
146
147 defnew=_sp.norm(rq); // comp defect norm
148
149 // determine new search direction
150 double sigmaNew = _sp.dot(r,rq);
151 beta = sigmaNew/sigma;
152 sigma = sigmaNew;
153 q *= beta; // scale old search direction
154 q += rq; // orthogonalization with correction
155 def = defnew; // update norm
156 }
157
158 if (_verbose>0) // printing for non verbose
159 this->printOutput(std::cout,(double) i,def);
160
161 res.iterations = i; // fill statistics
162 res.reduction = def/def0;
163 res.conv_rate = pow(res.reduction,1.0/i);
164 res.elapsed = watch.elapsed();
165
166 if (_verbose>0) // final print
167 {
168 std::cout << "=== rate=" << res.conv_rate
169 << ", T=" << res.elapsed
170 << ", TIT=" << res.elapsed/i
171 << ", IT=" << i << std::endl;
172 }
173// double sum = 0.0;
174// for (i=1; i<res.iterations; i++)
175// {
176// sum = 0.0;
177// for (int k = i; k<res.iterations; k++)
178// sum += allGammas[k];
179// if (i==_addedIterations)
180// printf("%4d %e %e %e eps0\n", i, allGammas[i], sum, allEstimates[i]);
181// else
182// printf("%4d %e %e %e\n", i, allGammas[i], sum, allEstimates[i]);
183// }
184 }
185
191 virtual void apply (X& x, X& b, double reduction, Dune::InverseOperatorResult& res)
192 {
193 _reduction = reduction;
194 (*this).apply(x,b,res);
195 }
196
197 private:
198 Dune::SeqScalarProduct<X> ssp;
199 Dune::LinearOperator<X,X>& _op;
200 Dune::Preconditioner<X,X>& _prec;
201 Dune::ScalarProduct<X>& _sp;
202 double _reduction;
203 int _maxit;
204 int _verbose;
205 int _addedIterations;
206 std::vector<double> gammas;
207 std::vector<double> allGammas;
208 std::vector<double> allEstimates;
209 };
210}
211#endif
conjugate gradient method
Definition: mg/apcg.hh:26
X::field_type field_type
The field type of the operator to be inverted.
Definition: mg/apcg.hh:33
virtual void apply(X &x, X &b, double reduction, Dune::InverseOperatorResult &res)
Apply inverse operator with given reduction factor.
Definition: mg/apcg.hh:191
NMIIIAPCGSolver(L &op, P &prec, double reduction, int maxit, int verbose, int addedIterations=2)
Set up conjugate gradient solver.
Definition: mg/apcg.hh:41
X domain_type
The domain type of the operator to be inverted.
Definition: mg/apcg.hh:29
virtual void apply(X &u, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: mg/apcg.hh:61
X range_type
The range type of the operator to be inverted.
Definition: mg/apcg.hh:31