KASKADE 7 development version
tcg.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/* Copyright (C) 2012 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef TCG_HH
14#define TCG_HH
15
16#include <numeric>
17
18#include <boost/circular_buffer.hpp>
19
20#include "dune/common/timer.hh"
21#include "dune/istl/istlexception.hh"
22#include "dune/istl/operators.hh"
23#include "dune/istl/preconditioners.hh"
24#include "dune/istl/scalarproducts.hh"
25#include "dune/istl/solvers.hh"
26
28#include "utilities/scalar.hh"
30
31#include "linalg/apcg.hh"
32
33namespace Kaskade
34{
36 {
37 template <class X, class Xstar>
38 void operator()(const X&, Xstar&){}
39 };
40
41 template <class Linearization, class VariableSet>
43 {
44 DoRegularization(Linearization const& lin_, typename VariableSet::Descriptions const& description) : lin(lin_), v(description)
45 {}
46
47 template <class X, class Xstar>
48 void operator()(const X& x, Xstar& r)
49 {
50 v = x; //
52 y *= 0;
53 lin.ddxpy(y,z,0,2,2,3);
54 y *= -1;
55 v = r; //
56
57 boost::fusion::at_c<0>(v.data) += boost::fusion::at_c<0>(y.get().data);
58 boost::fusion::at_c<1>(v.data) += boost::fusion::at_c<1>(y.get().data);
59
60 r = v; //
61 }
62
63 private:
64 Linearization const& lin;
66 };
67
78 template<class X, class Xstar, class Regularization=NoRegularization>
79 class TCG : public Dune::InverseOperator<X,Xstar> {
80 public:
81 enum class Result { Converged, Failed, EncounteredNonConvexity };
86
92 template <class Int=int, class enable = typename std::enable_if<!std::is_same<Regularization,NoRegularization>::value && std::is_same<Int,int>::value>::type>
93 TCG(Dune::LinearOperator<X,Xstar>& op_, Dune::Preconditioner<X,Xstar>& prec_, DualPairing<X,Xstar> const& dp_,
94 Regularization& regularization_, double relTol_=1e-3, size_t maxSteps_=100, Int verbose_=0) :
95 op(op_), prec(prec_), dp(dp_), regularization(regularization_), relTol(relTol_), absTol(1e-9), maxSteps(maxSteps_), verbose(verbose_)
96 {
97 // Do we need this in Kaskade7?
98 // dune_static_assert( static_cast<int>(L::category) == static_cast<int>(P::category),
99 // "L and P must have the same category!");
100 // dune_static_assert( static_cast<int>(L::category) == static_cast<int>(SolverCategory::sequential),
101 // "L must be sequential!");
102 }
103
109 template <class Int=int, class enable = typename std::enable_if<std::is_same<Regularization,NoRegularization>::value && std::is_same<Int,int>::value>::type>
110 TCG(Dune::LinearOperator<X,Xstar>& op_, Dune::Preconditioner<X,Xstar>& prec_, DualPairing<X,Xstar> const& dp_,
111 double relTol_=1e-3, size_t maxSteps_=100, Int verbose_=0) :
112 op(op_), prec(prec_), dp(dp_), relTol(relTol_), absTol(1e-9), maxSteps(maxSteps_), verbose(verbose_)
113 {
114 // Do we need this in Kaskade7?
115 // dune_static_assert( static_cast<int>(L::category) == static_cast<int>(P::category),
116 // "L and P must have the same category!");
117 // dune_static_assert( static_cast<int>(L::category) == static_cast<int>(SolverCategory::sequential),
118 // "L must be sequential!");
119 }
120
127 virtual int apply (X& u, X& q, Xstar& b, Dune::InverseOperatorResult& res)
128 {
129 result = Result::Failed;
130 int numberOfResults = 1;
131 res.clear(); // clear solver statistics
132 //terminate.clear(); // clear termination criterion
133 Dune::Timer watch; // start a timer
134
135 prec.pre(u,b);
136
137 Xstar r(b);
138 op.applyscaleadd(-1.0,u,r); // r = b-Au
139 regularization(u,r);
140
141 X rq(u), du(u); rq = 0;
142
143 prec.apply(rq,r); // rq = B^{-1} r
144
145 q = rq;
146
147 X Aq(b);
148
149
150 // some local variables
151 Real alpha,beta,sigma,gamma;
152 sigma = dp(rq,r); // preconditioned residual norm squared
153
154 //terminate.residual(sigma);
155 double const sigma0 = std::abs(sigma);
156
157 if (verbose>0) { // printing
158 std::cout << "=== Kaskade7 TCG" << std::endl;
159 if (verbose>1) {
160 this->printHeader(std::cout);
161 this->printOutput(std::cout,0,sigma0);
162 }
163 }
164
165 // the loop
166 int i=0;
167 while(true)
168 {
169 ++i;
170 // minimize in given search direction p
171 op.apply(q,Aq); // h = Aq
172 Real qAq = dp(q,Aq);
173
174 if(qAq <=0)
175 {
176 result = Result::EncounteredNonConvexity;
177 if(verbose > 0) std::cout << "Nonconvexity at iteration " << i << ", qAq=" << qAq << ", ||q||=" << sqrt(q*q) << std::endl;
178 if(i==1)
179 {
180 u.axpy(1.0,q);
181 break;
182 }
183 numberOfResults = 2;
184 break; // Abbruch wg. fehlender Konvexität
185 }
186
187 alpha = sigma/qAq;
188 u.axpy(alpha,q);
189 du = q;
190 du *= 1./alpha;
191 if(dp(du,du) < absTol)
192 {
193 result = Result::Converged;
194 break;
195 }
196
197 gamma = sigma*alpha;
198 //terminate.step(ScalarTraits<Real>::real(gamma));
199 resDebug.push_back(std::sqrt(sigma));
200
201 // convergence test
202 //if (terminate)
203 //break;
204
205 r.axpy(-alpha,Aq); // r = r - alpha*A*q
206 regularization(u,r);
207 rq = 0;
208 prec.apply(rq,r); // rq = B^{-1}r
209
210 // determine new search direction
211 double sigmaNew = dp(rq,r);
212 //terminate.residual(ScalarTraits<Real>::real(sigmaNew));
213 if (verbose>1) // print
214 this->printOutput(std::cout,i,std::abs(sigmaNew),std::abs(sigma));
215
216 // convergence check to prevent division by zero if we obtained an exact solution
217 // (which may happen for low dimensional systems)
218 if (std::abs(sigmaNew) < relTol*sigma0)
219 {
220 result = Result::Converged;
221 break;
222 }
223 beta = sigmaNew/sigma;
224 if(verbose > 0) std::cout << "step reduction: " << (sigmaNew/sigma) << ", overall reduction: " << (sigmaNew/sigma0) << std::endl;
225 sigma = sigmaNew;
226 q *= beta; // scale old search direction
227 q += rq; // orthogonalization with correction
228
229 if(i > maxSteps) break;
230 }
231
232 res.iterations = i; // fill statistics
233 res.reduction = std::sqrt(std::abs(sigma)/sigma0);
234 res.conv_rate = pow(res.reduction,1.0/i);
235 res.elapsed = watch.elapsed();
236
237 if (verbose>0) // final print
238 {
239 std::cout << "=== rate=" << res.conv_rate
240 << ", time=" << res.elapsed
241 << ", iterations=" << i << std::endl;
242 }
243
244 prec.post(u);
245
246 return numberOfResults;
247 }
248
252 virtual void apply (X& u, Xstar& b, Dune::InverseOperatorResult& res) {
253 X q(u);
254 apply(u,q,b,res);
255 }
256
257 void apply (X& u, Xstar& b)
258 {
259 Dune::InverseOperatorResult res;
260 apply(u,b,res);
261 }
262
266 virtual void apply (X& x, X& b, double relTol, Dune::InverseOperatorResult& res) {
267 //terminate.relTol(relTol);
268 (*this).apply(x,b,res);
269 }
270
271 void setRelativeAccuracy(double relTol_) { relTol = relTol_; }
272
273 void setMaxSteps(size_t maxSteps_) { maxSteps = maxSteps_; }
274
275 bool localConvergenceLikely() const { return result == Result::Converged; }
276
277 bool encounteredNonConvexity() const { return result == Result::EncounteredNonConvexity; }
278
279 private:
280 Dune::LinearOperator<X,Xstar>& op;
281 Dune::Preconditioner<X,Xstar>& prec;
282 DualPairing<X,Xstar> const& dp;
283 typename std::conditional<std::is_same<Regularization,NoRegularization>::value,NoRegularization,Regularization&>::type regularization;
284 double relTol, absTol;
285 size_t maxSteps;
286 int verbose;
287 std::vector<double> resDebug;
288 Result result;
289 };
290
291 template <class X, class Xstar, class Regularization = NoRegularization> using TPCG = TCG<X,Xstar,Regularization>;
292} // namespace Kaskade
293#endif
Mathematical Vector that supports copy-on-write, implements AbstractFunctionSpaceElement.
Abstract base class for dual pairing of and its dual space .
Helper class for working with (real or complex) scalar field types.
Definition: scalar.hh:36
preconditioned conjugate gradient method
Definition: tcg.hh:79
TCG(Dune::LinearOperator< X, Xstar > &op_, Dune::Preconditioner< X, Xstar > &prec_, DualPairing< X, Xstar > const &dp_, Regularization &regularization_, double relTol_=1e-3, size_t maxSteps_=100, Int verbose_=0)
Set up conjugate gradient solver with absolute energy error termination criterion.
Definition: tcg.hh:93
bool encounteredNonConvexity() const
Definition: tcg.hh:277
void setRelativeAccuracy(double relTol_)
Definition: tcg.hh:271
virtual void apply(X &u, Xstar &b, Dune::InverseOperatorResult &res)
Apply tcg and possibly forget second descent direction.
Definition: tcg.hh:252
TCG(Dune::LinearOperator< X, Xstar > &op_, Dune::Preconditioner< X, Xstar > &prec_, DualPairing< X, Xstar > const &dp_, double relTol_=1e-3, size_t maxSteps_=100, Int verbose_=0)
Set up conjugate gradient solver with absolute energy error termination criterion.
Definition: tcg.hh:110
virtual int apply(X &u, X &q, Xstar &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: tcg.hh:127
ScalarTraits< typenameGetScalar< X >::type >::Real Real
the real field type corresponding to X::field_type
Definition: tcg.hh:85
void setMaxSteps(size_t maxSteps_)
Definition: tcg.hh:273
bool localConvergenceLikely() const
Definition: tcg.hh:275
void apply(X &u, Xstar &b)
Definition: tcg.hh:257
virtual void apply(X &x, X &b, double relTol, Dune::InverseOperatorResult &res)
Apply inverse operator with given absolute tolerance.
Definition: tcg.hh:266
A class for storing a heterogeneous collection of FunctionSpaceElement s.
Definition: variables.hh:341
VSDescriptions Descriptions
Type of the VariableSetDescription.
Definition: variables.hh:344
DoRegularization(Linearization const &lin_, typename VariableSet::Descriptions const &description)
Definition: tcg.hh:44
void operator()(const X &x, Xstar &r)
Definition: tcg.hh:48
void operator()(const X &, Xstar &)
Definition: tcg.hh:38