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 
16 #include <dune/common/simd/io.hh>
17 #include <dune/common/simd/simd.hh>
19 #include <dune/common/timer.hh>
20 
21 #include "solvertype.hh"
22 #include "preconditioner.hh"
23 #include "operators.hh"
24 #include "scalarproducts.hh"
25 
26 namespace 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;
63  condition_estimate = -1;
64  }
65 
68 
70  double reduction;
71 
73  bool converged;
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:
205  using typename InverseOperator<X,Y>::domain_type;
206  using typename InverseOperator<X,Y>::range_type;
207  using typename InverseOperator<X,Y>::field_type;
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) :
231  _op(stackobject_to_shared_ptr(op)),
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) :
264  _op(stackobject_to_shared_ptr(op)),
265  _prec(stackobject_to_shared_ptr(prec)),
266  _sp(stackobject_to_shared_ptr(sp)),
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
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:
413  Iteration(const IterativeSolver& parent, InverseOperatorResult& res)
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(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(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, 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
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.80.0 (Apr 26, 22:29, 2024)