Dune Core Modules (2.9.0)

solver.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5
6#ifndef DUNE_ISTL_SOLVER_HH
7#define DUNE_ISTL_SOLVER_HH
8
9#include <iomanip>
10#include <ostream>
11#include <string>
12#include <functional>
13
19#include <dune/common/timer.hh>
20
21#include "solvertype.hh"
22#include "preconditioner.hh"
23#include "operators.hh"
24#include "scalarproducts.hh"
25
26namespace Dune
27{
48 {
51 {
52 clear();
53 }
54
56 void clear ()
57 {
58 iterations = 0;
59 reduction = 0;
60 converged = false;
61 conv_rate = 1;
62 elapsed = 0;
64 }
65
68
70 double reduction;
71
74
76 double conv_rate;
77
79 double condition_estimate = -1;
80
82 double elapsed;
83 };
84
85
86 //=====================================================================
98 template<class X, class Y>
100 public:
102 typedef X domain_type;
103
105 typedef Y range_type;
106
108 typedef typename X::field_type field_type;
109
111 typedef typename FieldTraits<field_type>::real_type real_type;
112
115
128 virtual void apply (X& x, Y& b, InverseOperatorResult& res) = 0;
129
143 virtual void apply (X& x, Y& b, double reduction, InverseOperatorResult& res) = 0;
144
147#ifdef DUNE_ISTL_SUPPORT_OLD_CATEGORY_INTERFACE
148 {
149 DUNE_THROW(Dune::Exception,"It is necessary to implement the category method in a derived classes, in the future this method will pure virtual.");
150 }
151#else
152 = 0;
153#endif
154
156 virtual ~InverseOperator () {}
157
158 protected:
159 // spacing values
160 enum { iterationSpacing = 5 , normSpacing = 16 };
161
163 void printHeader(std::ostream& s) const
164 {
165 s << std::setw(iterationSpacing) << " Iter";
166 s << std::setw(normSpacing) << "Defect";
167 s << std::setw(normSpacing) << "Rate" << std::endl;
168 }
169
171 template <typename CountType, typename DataType>
172 void printOutput(std::ostream& s,
173 const CountType& iter,
174 const DataType& norm,
175 const DataType& norm_old) const
176 {
177 const DataType rate = norm/norm_old;
178 s << std::setw(iterationSpacing) << iter << " ";
179 s << std::setw(normSpacing) << Simd::io(norm) << " ";
180 s << std::setw(normSpacing) << Simd::io(rate) << std::endl;
181 }
182
184 template <typename CountType, typename DataType>
185 void printOutput(std::ostream& s,
186 const CountType& iter,
187 const DataType& norm) const
188 {
189 s << std::setw(iterationSpacing) << iter << " ";
190 s << std::setw(normSpacing) << Simd::io(norm) << std::endl;
191 }
192 };
193
202 template<class X, class Y>
203 class IterativeSolver : public InverseOperator<X,Y>{
204 public:
208 using typename InverseOperator<X,Y>::real_type;
210
230 IterativeSolver (const LinearOperator<X,Y>& op, Preconditioner<X,Y>& prec, scalar_real_type reduction, int maxit, int verbose) :
232 _prec(stackobject_to_shared_ptr(prec)),
233 _sp(new SeqScalarProduct<X>),
234 _reduction(reduction), _maxit(maxit), _verbose(verbose), _category(SolverCategory::sequential)
235 {
237 DUNE_THROW(InvalidSolverCategory, "LinearOperator has to be sequential!");
239 DUNE_THROW(InvalidSolverCategory, "Preconditioner has to be sequential!");
240 }
241
263 scalar_real_type reduction, int maxit, int verbose) :
265 _prec(stackobject_to_shared_ptr(prec)),
267 _reduction(reduction), _maxit(maxit), _verbose(verbose), _category(SolverCategory::category(op))
268 {
270 DUNE_THROW(InvalidSolverCategory, "LinearOperator and Preconditioner must have the same SolverCategory!");
272 DUNE_THROW(InvalidSolverCategory, "LinearOperator and ScalarProduct must have the same SolverCategory!");
273 }
274
290 IterativeSolver (std::shared_ptr<const LinearOperator<X,Y> > op, std::shared_ptr<Preconditioner<X,X> > prec, const ParameterTree& configuration) :
291 IterativeSolver(op,std::make_shared<SeqScalarProduct<X>>(),prec,
292 configuration.get<real_type>("reduction"),
293 configuration.get<int>("maxit"),
294 configuration.get<int>("verbose"))
295 {}
296
313 IterativeSolver (std::shared_ptr<const LinearOperator<X,Y> > op, std::shared_ptr<const ScalarProduct<X> > sp, std::shared_ptr<Preconditioner<X,X> > prec, const ParameterTree& configuration) :
314 IterativeSolver(op,sp,prec,
315 configuration.get<scalar_real_type>("reduction"),
316 configuration.get<int>("maxit"),
317 configuration.get<int>("verbose"))
318 {}
319
340 IterativeSolver (std::shared_ptr<const LinearOperator<X,Y>> op,
341 std::shared_ptr<const ScalarProduct<X>> sp,
342 std::shared_ptr<Preconditioner<X,Y>> prec,
343 scalar_real_type reduction, int maxit, int verbose) :
344 _op(op),
345 _prec(prec),
346 _sp(sp),
347 _reduction(reduction), _maxit(maxit), _verbose(verbose),
348 _category(SolverCategory::category(*op))
349 {
351 DUNE_THROW(InvalidSolverCategory, "LinearOperator and Preconditioner must have the same SolverCategory!");
353 DUNE_THROW(InvalidSolverCategory, "LinearOperator and ScalarProduct must have the same SolverCategory!");
354 }
355
356 // #warning actually we want to have this as the default and just implement the second one
357 // //! \copydoc InverseOperator::apply(X&,Y&,InverseOperatorResult&)
358 // virtual void apply (X& x, Y& b, InverseOperatorResult& res)
359 // {
360 // apply(x,b,_reduction,res);
361 // }
362
363#ifndef DOXYGEN
364 // make sure the three-argument apply from the base class does not get shadowed
365 // by the redefined four-argument version below
366 using InverseOperator<X,Y>::apply;
367#endif
368
374 virtual void apply (X& x, X& b, double reduction, InverseOperatorResult& res)
375 {
376 scalar_real_type saved_reduction = _reduction;
377 _reduction = reduction;
378 this->apply(x,b,res);
379 _reduction = saved_reduction;
380 }
381
384 {
385 return _category;
386 }
387
388 std::string name() const{
389 std::string name = className(*this);
390 return name.substr(0, name.find("<"));
391 }
392
410 template<class CountType = unsigned int>
411 class Iteration {
412 public:
414 : _i(0)
415 , _res(res)
416 , _parent(parent)
417 , _valid(true)
418 {
419 res.clear();
420 if(_parent._verbose>0){
421 std::cout << "=== " << parent.name() << std::endl;
422 if(_parent._verbose > 1)
423 _parent.printHeader(std::cout);
424 }
425 }
426
427 Iteration(const Iteration&) = delete;
428 Iteration(Iteration&& other)
429 : _def0(other._def0)
430 , _def(other._def)
431 , _i(other._i)
432 , _watch(other._watch)
433 , _res(other._res)
434 , _parent(other._parent)
435 , _valid(other._valid)
436 {
437 other._valid = false;
438 }
439
440 ~Iteration(){
441 if(_valid)
442 finalize();
443 }
444
455 bool step(CountType i, real_type def){
456 if (!Simd::allTrue(isFinite(def))) // check for inf or NaN
457 {
458 if (_parent._verbose>0)
459 std::cout << "=== " << _parent.name() << ": abort due to infinite or NaN defect"
460 << std::endl;
462 _parent.name() << ": defect=" << Simd::io(def)
463 << " is infinite or NaN");
464 }
465 if(i == 0)
466 _def0 = def;
467 if(_parent._verbose > 1){
468 if(i!=0)
469 _parent.printOutput(std::cout,i,def,_def);
470 else
471 _parent.printOutput(std::cout,i,def);
472 }
473 _def = def;
474 _i = i;
475 _res.converged = (Simd::allTrue(def<_def0*_parent._reduction || def<real_type(1E-30))); // convergence check
476 return _res.converged;
477 }
478
479 protected:
480 void finalize(){
481 _res.converged = (Simd::allTrue(_def<_def0*_parent._reduction || _def<real_type(1E-30)));
482 _res.iterations = _i;
483 _res.reduction = static_cast<double>(Simd::max(_def/_def0));
484 _res.conv_rate = pow(_res.reduction,1.0/_i);
485 _res.elapsed = _watch.elapsed();
486 if (_parent._verbose>0) // final print
487 {
488 std::cout << "=== rate=" << _res.conv_rate
489 << ", T=" << _res.elapsed
490 << ", TIT=" << _res.elapsed/_res.iterations
491 << ", IT=" << _res.iterations << std::endl;
492 }
493 }
494
495 real_type _def0 = 0.0, _def = 0.0;
496 CountType _i;
497 Timer _watch;
498 InverseOperatorResult& _res;
499 const IterativeSolver& _parent;
500 bool _valid;
501 };
502
503 protected:
504 std::shared_ptr<const LinearOperator<X,Y>> _op;
505 std::shared_ptr<Preconditioner<X,Y>> _prec;
506 std::shared_ptr<const ScalarProduct<X>> _sp;
507 scalar_real_type _reduction;
508 int _maxit;
509 int _verbose;
510 SolverCategory::Category _category;
511 };
512
520 template <typename ISTLLinearSolver, typename BCRSMatrix>
522 {
523 public:
524 static void setMatrix (ISTLLinearSolver& solver,
525 const BCRSMatrix& matrix)
526 {
527 static const bool is_direct_solver
528 = Dune::IsDirectSolver<ISTLLinearSolver>::value;
531 }
532
533 protected:
538 template <bool is_direct_solver, typename Dummy = void>
540 {
541 static void setMatrix (ISTLLinearSolver&,
542 const BCRSMatrix&)
543 {}
544 };
545
550 template <typename Dummy>
551 struct Implementation<true,Dummy>
552 {
553 static void setMatrix (ISTLLinearSolver& solver,
554 const BCRSMatrix& matrix)
555 {
556 solver.setMatrix(matrix);
557 }
558 };
559 };
560
564}
565
566#endif
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:466
Base class for Dune-Exceptions.
Definition: exceptions.hh:96
Abstract base class for all solvers.
Definition: solver.hh:99
void printHeader(std::ostream &s) const
helper function for printing header of solver output
Definition: solver.hh:163
virtual ~InverseOperator()
Destructor.
Definition: solver.hh:156
void printOutput(std::ostream &s, const CountType &iter, const DataType &norm) const
helper function for printing solver output
Definition: solver.hh:185
void printOutput(std::ostream &s, const CountType &iter, const DataType &norm, const DataType &norm_old) const
helper function for printing solver output
Definition: solver.hh:172
virtual void apply(X &x, Y &b, double reduction, InverseOperatorResult &res)=0
apply inverse operator, with given convergence criteria.
Simd::Scalar< real_type > scalar_real_type
scalar type underlying the field_type
Definition: solver.hh:114
Y range_type
Type of the range of the operator to be inverted.
Definition: solver.hh:105
X domain_type
Type of the domain of the operator to be inverted.
Definition: solver.hh:102
virtual void apply(X &x, Y &b, InverseOperatorResult &res)=0
Apply inverse operator,.
X::field_type field_type
The field type of the operator.
Definition: solver.hh:108
FieldTraits< field_type >::real_type real_type
The real type of the field type (is the same if using real numbers, but differs for std::complex)
Definition: solver.hh:111
virtual SolverCategory::Category category() const =0
Category of the solver (see SolverCategory::Category)
Class for controlling iterative methods.
Definition: solver.hh:411
bool step(CountType i, real_type def)
registers the iteration step, checks for invalid defect norm and convergence.
Definition: solver.hh:455
Base class for all implementations of iterative solvers.
Definition: solver.hh:203
IterativeSolver(std::shared_ptr< const LinearOperator< X, Y > > op, std::shared_ptr< const ScalarProduct< X > > sp, std::shared_ptr< Preconditioner< X, X > > prec, const ParameterTree &configuration)
Constructor.
Definition: solver.hh:313
IterativeSolver(std::shared_ptr< const LinearOperator< X, Y > > op, std::shared_ptr< Preconditioner< X, X > > prec, const ParameterTree &configuration)
Constructor.
Definition: solver.hh:290
virtual void apply(X &x, X &b, double reduction, InverseOperatorResult &res)
Apply inverse operator with given reduction factor.
Definition: solver.hh:374
IterativeSolver(std::shared_ptr< const LinearOperator< X, Y > > op, std::shared_ptr< const ScalarProduct< X > > sp, std::shared_ptr< Preconditioner< X, Y > > prec, scalar_real_type reduction, int maxit, int verbose)
General constructor to initialize an iterative solver.
Definition: solver.hh:340
IterativeSolver(const LinearOperator< X, Y > &op, Preconditioner< X, Y > &prec, scalar_real_type reduction, int maxit, int verbose)
General constructor to initialize an iterative solver.
Definition: solver.hh:230
IterativeSolver(const LinearOperator< X, Y > &op, const ScalarProduct< X > &sp, Preconditioner< X, Y > &prec, scalar_real_type reduction, int maxit, int verbose)
General constructor to initialize an iterative solver.
Definition: solver.hh:262
virtual SolverCategory::Category category() const
Category of the solver (see SolverCategory::Category)
Definition: solver.hh:383
A linear operator.
Definition: operators.hh:67
Hierarchical structure of string parameters.
Definition: parametertree.hh:37
Base class for matrix free definition of preconditioners.
Definition: preconditioner.hh:32
Base class for scalar product and norm computation.
Definition: scalarproducts.hh:52
Default implementation for the scalar case.
Definition: scalarproducts.hh:168
Thrown when a solver aborts due to some problem.
Definition: istlexception.hh:46
Helper class for notifying a DUNE-ISTL linear solver about a change of the iteration matrix object in...
Definition: solver.hh:522
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:77
A few common exception classes.
IO interface of the SIMD abstraction.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
auto io(const V &v)
construct a stream inserter
Definition: io.hh:106
bool allTrue(const Mask &mask)
Whether all entries are true
Definition: interface.hh:439
auto max(const V &v1, const V &v2)
The binary maximum value over two simd objects.
Definition: interface.hh:409
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition: interface.hh:235
Dune namespace.
Definition: alignedallocator.hh:13
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:72
std::string className()
Provide the demangled class name of a type T as a string.
Definition: classname.hh:47
STL namespace.
Define general, extensible interface for operators. The available implementation wraps a matrix.
A hierarchical structure of string parameters.
Define base class for scalar product and norm.
This file implements several utilities related to std::shared_ptr.
Include file for users of the SIMD abstraction layer.
Templates characterizing the type of a solver.
Statistics about the application of an inverse operator.
Definition: solver.hh:48
InverseOperatorResult()
Default constructor.
Definition: solver.hh:50
double condition_estimate
Estimate of condition number.
Definition: solver.hh:79
double elapsed
Elapsed time in seconds.
Definition: solver.hh:82
int iterations
Number of iterations.
Definition: solver.hh:67
double reduction
Reduction achieved: .
Definition: solver.hh:70
void clear()
Resets all data.
Definition: solver.hh:56
double conv_rate
Convergence rate (average reduction per step)
Definition: solver.hh:76
bool converged
True if convergence criterion has been met.
Definition: solver.hh:73
Categories for the solvers.
Definition: solvercategory.hh:22
Category
Definition: solvercategory.hh:23
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:25
static Category category(const OP &op, decltype(op.category()) *=nullptr)
Helperfunction to extract the solver category either from an enum, or from the newly introduced virtu...
Definition: solvercategory.hh:34
Implementation that works together with iterative ISTL solvers, e.g. Dune::CGSolver or Dune::BiCGSTAB...
Definition: solver.hh:540
A simple timing class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)