solvers.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2004-2012 by Christian Engwer
5  Copyright (C) 2005-2011 by Markus Blatt
6  Copyright (C) 2007 by Robert Kloefkorn
7  Copyright (C) 2004-2006 by Peter Bastian
8  Copyright (C) 2010 by Jorrit Fahlke
9  Copyright (C) 2007-2012 by Oliver Sander
10  Copyright (C) 2012 by Andreas Lauser
11 
12  This program is free software: you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation, version 2.
15 
16  As a special exception, you may use the DUNE library without
17  restriction. Specifically, if other files instantiate templates or
18  use macros or inline functions from one or more of the DUNE source
19  files, or you compile one or more of the DUNE source files and link
20  them with other files to produce an executable, this does not by
21  itself cause the resulting executable to be covered by the GNU
22  General Public License. This exception does not however invalidate
23  any other reasons why the executable file might be covered by the
24  GNU General Public License.
25 
26  This program is distributed in the hope that it will be useful,
27  but WITHOUT ANY WARRANTY; without even the implied warranty of
28  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  GNU General Public License for more details.
30 
31  You should have received a copy of the GNU General Public License
32  along with this program. If not, see <http://www.gnu.org/licenses/>.
33 */
47 #ifndef EWOMS_SOLVERS_HH
48 #define EWOMS_SOLVERS_HH
49 
50 #include <cmath>
51 #include <complex>
52 #include <iostream>
53 #include <iomanip>
54 #include <memory>
55 #include <string>
56 #include <vector>
57 
60 #include "fixpointcriterion.hh"
61 
62 #include <dune/common/version.hh>
63 #include <dune/istl/istlexception.hh>
64 #include <dune/istl/operators.hh>
65 #include <dune/istl/scalarproducts.hh>
66 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,3)
67 #include <dune/istl/preconditioner.hh>
68 #include <dune/istl/solver.hh>
69 #else
70 #include <dune/istl/preconditioners.hh>
71 #include <dune/istl/solvers.hh>
72 #endif
73 #include <dune/common/array.hh>
74 #include <dune/common/timer.hh>
75 #include <dune/common/ftraits.hh>
76 
77 #include <type_traits>
78 #include <algorithm>
79 #include <memory>
80 
81 namespace Ewoms {
82 /*
83  @ingroup Linear
84 */
89 //=====================================================================
101 template <class X, class Y>
103 {
104 public:
106  typedef X domain_type;
107 
109  typedef Y range_type;
110 
112  typedef typename X::field_type field_type;
113 
119  { return *convergenceCriterion_; }
120 
126  { return *convergenceCriterion_; }
127 
132  virtual void setConvergenceCriterion(std::shared_ptr<Ewoms::ConvergenceCriterion<X> > convCrit)
133  { convergenceCriterion_ = convCrit; }
134 
144  virtual void apply(X& x, Y& b, Dune::InverseOperatorResult& res) = 0;
145 
148  {}
149 
150 private:
151  std::shared_ptr<ConvergenceCriterion<X> > convergenceCriterion_;
152 };
153 
154 //=====================================================================
155 // Implementation of this interface
156 //=====================================================================
157 
166 template <class X>
167 class LoopSolver : public InverseOperator<X, X>
168 {
170 
171 public:
173  typedef X domain_type;
175  typedef X range_type;
177  typedef typename X::field_type field_type;
178 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
179  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
181 #else
182  typedef field_type real_type;
183 #endif
184 
204  template <class L, class P>
205  LoopSolver(L& op, P& prec,
206  real_type reduction, int maxit, int verbose) :
207  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit), _verbose(verbose)
208  {
209  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
210  "L and P have to have the same category!");
211  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
212  "L has to be sequential!");
213 
214  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
215  this->setConvergenceCriterion(crit);
216  }
217 
238  template <class L, class S, class P>
239  LoopSolver(L& op, S& sp, P& prec,
240  real_type reduction, int maxit, int verbose) :
241  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose)
242  {
243  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
244  "L and P must have the same category!");
245  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
246  "L and S must have the same category!");
247 
248  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
249  this->setConvergenceCriterion(crit);
250  }
251 
252 
254  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
255  {
256  // clear solver statistics
257  res.clear();
258 
259  // start a timer
260  Dune::Timer watch;
261 
262  // prepare preconditioner
263  _prec.pre(x, b);
264 
265  // overwrite b with defect
266  _op.applyscaleadd(-1, x, b);
267 
268  this->convergenceCriterion().setInitial(x, b);
269  if (_verbose > 0) {
270  std::cout << "=== LoopSolver" << std::endl << std::flush;
271  if (_verbose > 1) {
272  this->convergenceCriterion().printInitial();
273  }
274  }
275  if (this->convergenceCriterion().converged()) {
276  // fill statistics
277  res.converged = true;
278  res.iterations = 0;
279  res.reduction = this->convergenceCriterion().accuracy();
280  res.conv_rate = 0;
281  res.elapsed = 0;
282  return;
283  }
284 
285  // allocate correction vector
286  X v(x);
287 
288  // iteration loop
289  int i = 1;
290  for (; i <= _maxit; i++) {
291  v = 0; // clear correction
292  _prec.apply(v, b); // apply preconditioner
293  x += v; // update solution
294  _op.applyscaleadd(-1, v, b); // update defect
295 
296  this->convergenceCriterion().update(x, b);
297  if (_verbose > 1) // print
298  this->convergenceCriterion().print(i);
299  if (this->convergenceCriterion().converged()) {
300  res.converged = true;
301  break;
302  }
303  }
304 
305  //correct i which is wrong if convergence was not achieved.
306  i = std::min(_maxit, i);
307 
308  // print
309  if (_verbose == 1)
310  this->convergenceCriterion().print(i);
311 
312  // postprocess preconditioner
313  _prec.post(x);
314 
315  // fill statistics
316  res.iterations = i;
317  res.reduction = this->convergenceCriterion().accuracy();
318  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
319  res.elapsed = watch.elapsed();
320 
321  // final print
322  if (_verbose > 0)
323  {
324  std::cout << "=== rate=" << res.conv_rate
325  << ", T=" << res.elapsed
326  << ", TIT=" << res.elapsed/i
327  << ", IT=" << i << std::endl;
328  }
329  }
330 
331 private:
332  Dune::SeqScalarProduct<X> ssp;
333  Dune::LinearOperator<X, X> &_op;
334  Dune::Preconditioner<X, X> &_prec;
335  Dune::ScalarProduct<X> &_sp;
336  std::shared_ptr<ConvergenceCriterion> convergenceCriterion_;
337  int _maxit;
338  int _verbose;
339 };
340 
341 // all these solvers are taken from the SUMO library
343 template <class X>
344 class GradientSolver : public InverseOperator<X, X>
345 {
347 
348 public:
350  typedef X domain_type;
352  typedef X range_type;
354  typedef typename X::field_type field_type;
355 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
356  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
358 #else
359  typedef field_type real_type;
360 #endif
361 
362 
368  template <class L, class P>
369  GradientSolver(L& op, P& prec,
370  real_type reduction, int maxit, int verbose) :
371  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit), _verbose(verbose)
372  {
373  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
374  "L and P have to have the same category!");
375  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
376  "L has to be sequential!");
377 
378  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
379  this->setConvergenceCriterion(crit);
380  }
386  template <class L, class S, class P>
387  GradientSolver(L& op, S& sp, P& prec,
388  real_type reduction, int maxit, int verbose) :
389  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose)
390  {
391  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
392  "L and P have to have the same category!");
393  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
394  "L and S have to have the same category!");
395 
396  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
397  this->setConvergenceCriterion(crit);
398  }
399 
405  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
406  {
407  res.clear(); // clear solver statistics
408  Dune::Timer watch; // start a timer
409  _prec.pre(x, b); // prepare preconditioner
410  _op.applyscaleadd(-1, x, b); // overwrite b with defect
411 
412  X p(x); // create local vectors
413  X q(b);
414 
415  this->convergenceCriterion().setInitial(x, b);
416  if (_verbose > 0) {
417  std::cout << "=== GradientSolver" << std::endl << std::flush;
418  if (_verbose > 1)
419  this->convergenceCriterion().printInitial();
420  }
421  if (this->convergenceCriterion().converged()) {
422  // fill statistics
423  res.converged = true;
424  res.iterations = 0;
425  res.reduction = this->convergenceCriterion().accuracy();
426  res.conv_rate = 0;
427  res.elapsed = 0;
428  return;
429  }
430 
431  int i = 1; // loop variables
432  field_type lambda;
433  for (; i <=_maxit; i++)
434  {
435  p = 0; // clear correction
436  _prec.apply(p, b); // apply preconditioner
437  _op.apply(p, q); // q=Ap
438  lambda = _sp.dot(p, b)/_sp.dot(q, p); // minimization
439  x.axpy(lambda, p); // update solution
440  b.axpy(-lambda, q); // update defect
441 
442  this->convergenceCriterion().update(x, b);
443  if (_verbose > 1) // print
444  this->convergenceCriterion().print(i);
445  if (this->convergenceCriterion().converged()) {
446  res.converged = true;
447  break;
448  }
449  }
450 
451  //correct i which is wrong if convergence was not achieved.
452  i = std::min(_maxit, i);
453 
454  if (_verbose == 1) // printing for non verbose
455  this->convergenceCriterion().print(i);
456 
457  _prec.post(x); // postprocess preconditioner
458  res.iterations = i; // fill statistics
459  res.reduction = this->convergenceCriterion().accuracy();
460  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
461  res.elapsed = watch.elapsed();
462  }
463 
464 private:
465  Dune::SeqScalarProduct<X> ssp;
466  Dune::LinearOperator<X, X> &_op;
467  Dune::Preconditioner<X, X> &_prec;
468  Dune::ScalarProduct<X> &_sp;
469  std::shared_ptr<ConvergenceCriterion> convergenceCriterion_;
470  int _maxit;
471  int _verbose;
472 };
473 
474 
475 
477 template <class X>
478 class CGSolver : public InverseOperator<X, X>
479 {
481 
482 public:
484  typedef X domain_type;
486  typedef X range_type;
488  typedef typename X::field_type field_type;
490  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
491 
497  template <class L, class P>
498  CGSolver(L& op, P& prec, real_type reduction, int maxit, int verbose) :
499  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit), _verbose(verbose)
500  {
501  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
502  "L and P must have the same category!");
503  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
504  "L must be sequential!");
505 
506  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
507  this->setConvergenceCriterion(crit);
508  }
514  template <class L, class S, class P>
515  CGSolver(L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) :
516  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose)
517  {
518  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
519  "L and P must have the same category!");
520  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
521  "L and S must have the same category!");
522 
523  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
524  this->setConvergenceCriterion(crit);
525  }
526 
532  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
533  {
534  res.clear(); // clear solver statistics
535  Dune::Timer watch; // start a timer
536  _prec.pre(x, b); // prepare preconditioner
537  _op.applyscaleadd(-1, x, b); // overwrite b with defect
538 
539  X p(x); // the search direction
540  X q(x); // a temporary vector
541 
542  this->convergenceCriterion().setInitial(x, b);
543  if (_verbose > 0)
544  {
545  std::cout << "=== CGSolver" << std::endl << std::flush;
546  if (_verbose > 1)
547  this->convergenceCriterion().printInitial();
548  }
549  if (this->convergenceCriterion().converged()) {
550  // fill statistics
551  res.converged = true;
552  res.iterations = 0;
553  res.reduction = this->convergenceCriterion().accuracy();
554  res.conv_rate = 0;
555  res.elapsed = 0;
556  return;
557  }
558 
559  // some local variables
560  field_type rho, rholast, lambda, alpha, beta;
561 
562  // determine initial search direction
563  p = 0; // clear correction
564  _prec.apply(p, b); // apply preconditioner
565  rholast = _sp.dot(p, b); // orthogonalization
566 
567  // the loop
568  int i = 1;
569  for (; i <= _maxit; i++) {
570  // minimize in given search direction p
571  _op.apply(p, q); // q=Ap
572  alpha = _sp.dot(p, q); // scalar product
573  lambda = rholast/alpha; // minimization
574  x.axpy(lambda, p); // update solution
575  b.axpy(-lambda, q); // update defect
576 
577  // convergence test
578  this->convergenceCriterion().update(x, b);
579  if (_verbose > 1) // print
580  this->convergenceCriterion().print(i);
581  if (this->convergenceCriterion().converged()) {
582  res.converged = true;
583  break;
584  }
585 
586  // determine new search direction
587  q = 0; // clear correction
588  _prec.apply(q, b); // apply preconditioner
589  rho = _sp.dot(q, b); // orthogonalization
590  beta = rho/rholast; // scaling factor
591  p *= beta; // scale old search direction
592  p += q; // orthogonalization with correction
593  rholast = rho; // remember rho for recurrence
594  }
595 
596  //correct i which is wrong if convergence was not achieved.
597  i = std::min(_maxit, i);
598 
599  if (_verbose == 1) // printing for non verbose
600  this->convergenceCriterion().print(i);
601 
602  _prec.post(x); // postprocess preconditioner
603  res.iterations = i; // fill statistics
604  res.reduction = this->convergenceCriterion().accuracy();
605  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
606  res.elapsed = watch.elapsed();
607  }
608 
609 private:
610  Dune::SeqScalarProduct<X> ssp;
611  Dune::LinearOperator<X, X> &_op;
612  Dune::Preconditioner<X, X> &_prec;
613  Dune::ScalarProduct<X> &_sp;
614  std::shared_ptr<ConvergenceCriterion> convergenceCriterion_;
615  int _maxit;
616  int _verbose;
617 };
618 
619 
620 // Ronald Kriemanns BiCG-STAB implementation from Sumo
622 template <class X>
623 class BiCGSTABSolver : public InverseOperator<X, X>
624 {
626 
627 public:
629  typedef X domain_type;
631  typedef X range_type;
633  typedef typename X::field_type field_type;
634 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
635  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
637 #else
638  typedef field_type real_type;
639 #endif
640 
646  template <class L, class P>
647  BiCGSTABSolver(L& op, P& prec,
648  real_type reduction, int maxit, int verbose) :
649  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit), _verbose(verbose)
650  {
651  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
652  "L and P must be of the same category!");
653  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
654  "L must be sequential!");
655 
656  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
657  this->setConvergenceCriterion(crit);
658  }
664  template <class L, class S, class P>
665  BiCGSTABSolver(L& op, S& sp, P& prec,
666  real_type reduction, int maxit, int verbose) :
667  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose)
668  {
669  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
670  "L and P must have the same category!");
671  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
672  "L and S must have the same category!");
673 
674  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
675  this->setConvergenceCriterion(crit);
676  }
677 
683  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
684  {
685  const real_type EPSILON = 1e-80;
686  double it;
687  field_type rho, rho_new, alpha, beta, h, omega;
688 
689  //
690  // get vectors and matrix
691  //
692  X& r=b;
693  X p(x);
694  X v(x);
695  X t(x);
696  X y(x);
697  X rt(x);
698 
699  //
700  // begin iteration
701  //
702 
703  // r = r - Ax; rt = r
704  res.clear(); // clear solver statistics
705  Dune::Timer watch; // start a timer
706  _prec.pre(x, r); // prepare preconditioner
707  _op.applyscaleadd(-1, x, r); // overwrite b with defect
708 
709  rt = r;
710 
711  p = 0;
712  v = 0;
713 
714  rho = 1;
715  alpha = 1;
716  omega = 1;
717 
718  this->convergenceCriterion().setInitial(x, r);
719  if (_verbose > 0)
720  {
721  std::cout << "=== BiCGSTABSolver" << std::endl << std::flush;
722  if (_verbose > 1)
723  this->convergenceCriterion().printInitial();
724  }
725  if (this->convergenceCriterion().converged()) {
726  // fill statistics
727  res.converged = true;
728  res.iterations = 0;
729  res.reduction = this->convergenceCriterion().accuracy();
730  res.conv_rate = 0;
731  res.elapsed = 0;
732  return;
733  }
734 
735  //
736  // iteration
737  //
738  for (it = 0.5; it < _maxit; it += .5)
739  {
740  //
741  // preprocess, set vecsizes etc.
742  //
743 
744  // rho_new = < rt, r >
745  rho_new = _sp.dot(rt, r);
746 
747  // look if breakdown occured
748  if (std::abs(rho) <= EPSILON)
749  DUNE_THROW(Dune::ISTLError, "breakdown in BiCGSTAB - rho "
750  << rho << " <= EPSILON " << EPSILON
751  << " after " << it << " iterations");
752  if (std::abs(omega) <= EPSILON)
753  DUNE_THROW(Dune::ISTLError, "breakdown in BiCGSTAB - omega "
754  << omega << " <= EPSILON " << EPSILON
755  << " after " << it << " iterations");
756 
757  if (it < 1)
758  p = r;
759  else {
760  beta = (rho_new / rho) * (alpha / omega);
761  p.axpy(-omega, v); // p = r + beta (p - omega*v)
762  p *= beta;
763  p += r;
764  }
765 
766  // y = W^-1 * p
767  y = 0;
768  _prec.apply(y, p); // apply preconditioner
769 
770  // v = A * y
771  _op.apply(y, v);
772 
773  // alpha = rho_new / < rt, v >
774  h = _sp.dot(rt, v);
775 
776  if (std::abs(h) < EPSILON)
777  DUNE_THROW(Dune::ISTLError, "h=0 in BiCGSTAB");
778 
779  alpha = rho_new / h;
780 
781  // apply first correction to x
782  // x <- x + alpha y
783  x.axpy(alpha, y);
784 
785  // r = r - alpha*v
786  r.axpy(-alpha, v);
787 
788  //
789  // test stop criteria
790  //
791  this->convergenceCriterion().update(x, r);
792  if (_verbose > 1) // print
793  this->convergenceCriterion().print(it);
794  if (this->convergenceCriterion().converged()) {
795  res.converged = true;
796  break;
797  }
798  it += .5;
799 
800  // y = W^-1 * r
801  y = 0;
802  _prec.apply(y, r);
803 
804  // t = A * y
805  _op.apply(y, t);
806 
807  // omega = < t, r > / < t, t >
808  omega = _sp.dot(t, r) / _sp.dot(t, t);
809 
810  // apply second correction to x
811  // x <- x + omega y
812  x.axpy(omega, y);
813 
814  // r = s - omega*t (remember : r = s)
815  r.axpy(-omega, t);
816 
817  rho = rho_new;
818 
819  //
820  // test stop criteria
821  //
822  this->convergenceCriterion().update(x, r);
823  if (_verbose > 1) // print
824  this->convergenceCriterion().print(it);
825  if (this->convergenceCriterion().converged()) {
826  res.converged = true;
827  break;
828  }
829  } // end for
830 
831  //correct i which is wrong if convergence was not achieved.
832  it = std::min(static_cast<double>(_maxit), it);
833 
834  if (_verbose == 1) // printing for non verbose
835  this->convergenceCriterion().print(it);
836 
837  _prec.post(x); // postprocess preconditioner
838  res.iterations = static_cast<int>(std::ceil(it)); // fill statistics
839  res.reduction = this->convergenceCriterion().accuracy();
840  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
841  res.elapsed = watch.elapsed();
842  }
843 
844 private:
845  Dune::SeqScalarProduct<X> ssp;
846  Dune::LinearOperator<X, X> &_op;
847  Dune::Preconditioner<X, X> &_prec;
848  Dune::ScalarProduct<X> &_sp;
849  std::shared_ptr<ConvergenceCriterion> convergenceCriterion_;
850  int _maxit;
851  int _verbose;
852 };
853 
860 template <class X>
861 class MINRESSolver : public InverseOperator<X, X>
862 {
864 
865 public:
867  typedef X domain_type;
869  typedef X range_type;
871  typedef typename X::field_type field_type;
872 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
873  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
875 #else
876  typedef field_type real_type;
877 #endif
878 
884  template <class L, class P>
885  MINRESSolver(L& op, P& prec, real_type reduction, int maxit, int verbose) :
886  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit), _verbose(verbose)
887  {
888  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
889  "L and P must have the same category!");
890  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
891  "L must be sequential!");
892 
893  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
894  this->setConvergenceCriterion(crit);
895  }
901  template <class L, class S, class P>
902  MINRESSolver(L& op, S& sp, P& prec, real_type reduction, int maxit, int verbose) :
903  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose)
904  {
905  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
906  "L and P must have the same category!");
907  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
908  "L and S must have the same category!");
909 
910  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
911  this->setConvergenceCriterion(crit);
912  }
913 
919  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
920  {
921  // clear solver statistics
922  res.clear();
923  // start a timer
924  Dune::Timer watch;
925  watch.reset();
926  // prepare preconditioner
927  _prec.pre(x, b);
928  // overwrite rhs with defect
929  _op.applyscaleadd(-1, x, b);
930 
931  this->convergenceCriterion().setInitial(x, b);
932  if (_verbose > 0)
933  {
934  std::cout << "=== MINRESSolver" << std::endl << std::flush;
935  if (_verbose > 1) {
936  this->convergenceCriterion().printInitial();
937  }
938  }
939  // check for convergence
940  if (this->convergenceCriterion().converged()) {
941  // fill statistics
942  res.converged = true;
943  res.iterations = 0;
944  res.reduction = this->convergenceCriterion().accuracy();
945  res.conv_rate = 0;
946  res.elapsed = 0;
947  return;
948  }
949 
950  // recurrence coefficients as computed in Lanczos algorithm
951  field_type alpha, beta;
952  // diagonal entries of givens rotation
953  std::array<real_type, 2> c{{0.0, 0.0}};
954  // off-diagonal entries of givens rotation
955  std::array<field_type, 2> s{{0.0, 0.0}};
956 
957  // recurrence coefficients (column k of tridiag matrix T_k)
958  std::array<field_type, 3> T{{0.0, 0.0, 0.0}};
959 
960  // the rhs vector of the min problem
961  std::array<field_type, 2> xi{{1.0, 0.0}};
962 
963  // some temporary vectors
964  X z(b), dummy(b);
965 
966  // initialize and clear correction
967  z = 0.0;
968  _prec.apply(z, b);
969 
970  // beta is real and positive in exact arithmetic
971  // since it is the norm of the basis vectors (in unpreconditioned case)
972  beta = std::sqrt(_sp.dot(z, b));
973  field_type beta0 = beta;
974 
975  // the search directions
976  std::array<X, 3> p{{b, b, b}};
977  p[0] = 0.0;
978  p[1] = 0.0;
979  p[2] = 0.0;
980 
981  // orthonormal basis vectors (in unpreconditioned case)
982  std::array<X, 3> q{{b, b, b}};
983  q[0] = 0.0;
984  q[1] *= 1.0/beta;
985  q[2] = 0.0;
986 
987  z *= 1.0/beta;
988 
989  // the loop
990  int i = 1;
991  for (; i <= _maxit; i++) {
992 
993  dummy = z;
994  int i1 = i%3,
995  i0 = (i1+2)%3,
996  i2 = (i1+1)%3;
997 
998  // symmetrically preconditioned Lanczos algorithm (see Greenbaum p.121)
999  _op.apply(z, q[i2]); // q[i2] = Az
1000  q[i2].axpy(-beta, q[i0]);
1001  // alpha is real since it is the diagonal entry of the hermitian tridiagonal matrix
1002  // from the Lanczos Algorithm
1003  // so the order in the scalar product doesn't matter even for the complex case
1004  alpha = _sp.dot(z, q[i2]);
1005  q[i2].axpy(-alpha, q[i1]);
1006 
1007  z = 0.0;
1008  _prec.apply(z, q[i2]);
1009 
1010  // beta is real and positive in exact arithmetic
1011  // since it is the norm of the basis vectors (in unpreconditioned case)
1012  beta = std::sqrt(_sp.dot(q[i2], z));
1013 
1014  q[i2] *= 1.0/beta;
1015  z *= 1.0/beta;
1016 
1017  // QR Factorization of recurrence coefficient matrix
1018  // apply previous givens rotations to last column of T
1019  T[1] = T[2];
1020  if (i > 2) {
1021  T[0] = s[i%2]*T[1];
1022  T[1] = c[i%2]*T[1];
1023  }
1024  if (i > 1) {
1025  T[2] = c[(i+1)%2]*alpha - s[(i+1)%2]*T[1];
1026  T[1] = c[(i+1)%2]*T[1] + s[(i+1)%2]*alpha;
1027  }
1028  else
1029  T[2] = alpha;
1030 
1031  // update QR factorization
1032  generateGivensRotation(T[2], beta, c[i%2], s[i%2]);
1033  // to last column of T_k
1034  T[2] = c[i%2]*T[2] + s[i%2]*beta;
1035  // and to the rhs xi of the min problem
1036  xi[i%2] = -s[i%2]*xi[(i+1)%2];
1037  xi[(i+1)%2] *= c[i%2];
1038 
1039  // compute correction direction
1040  p[i2] = dummy;
1041  p[i2].axpy(-T[1], p[i1]);
1042  p[i2].axpy(-T[0], p[i0]);
1043  p[i2] *= 1.0/T[2];
1044 
1045  // apply correction/update solution
1046  x.axpy(beta0*xi[(i+1)%2], p[i2]);
1047 
1048  // remember beta_old
1049  T[2] = beta;
1050 
1051  // check for convergence
1052  this->convergenceCriterion().update(x, b);
1053  if (_verbose > 1)
1054  this->convergenceCriterion().print(i);
1055  if (this->convergenceCriterion().converged()) {
1056  res.converged = true;
1057  break;
1058  }
1059  } // end for
1060 
1061  if (_verbose == 1) // printing for non verbose
1062  this->convergenceCriterion().print(i);
1063 
1064  // postprocess preconditioner
1065  _prec.post(x);
1066  // fill statistics
1067  res.iterations = i;
1068  res.reduction = this->convergenceCriterion().accuracy();
1069  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
1070  res.elapsed = watch.elapsed();
1071  }
1072 
1073 private:
1074 
1075  void generateGivensRotation(field_type& dx, field_type& dy, real_type& cs, field_type& sn)
1076  {
1077  real_type norm_dx = std::abs(dx);
1078  real_type norm_dy = std::abs(dy);
1079  if (norm_dy < 1e-15) {
1080  cs = 1.0;
1081  sn = 0.0;
1082  } else if (norm_dx < 1e-15) {
1083  cs = 0.0;
1084  sn = 1.0;
1085  } else if (norm_dy > norm_dx) {
1086  real_type temp = norm_dx/norm_dy;
1087  cs = 1.0/std::sqrt(1.0 + temp*temp);
1088  sn = cs;
1089  cs *= temp;
1090  sn *= dx/norm_dx;
1091  // dy is real in exact arithmetic
1092  // so we don't need to conjugate here
1093  sn *= dy/norm_dy;
1094  } else {
1095  real_type temp = norm_dy/norm_dx;
1096  cs = 1.0/std::sqrt(1.0 + temp*temp);
1097  sn = cs;
1098  sn *= dy/dx;
1099  // dy and dx is real in exact arithmetic
1100  // so we don't have to conjugate both of them
1101  }
1102  }
1103 
1104  Dune::SeqScalarProduct<X> ssp;
1105  Dune::LinearOperator<X, X>& _op;
1106  Dune::Preconditioner<X, X>& _prec;
1107  Dune::ScalarProduct<X>& _sp;
1108  std::shared_ptr<ConvergenceCriterion> convergenceCriterion_;
1109  int _maxit;
1110  int _verbose;
1111 };
1112 
1126 template <class X, class Y=X, class F = Y>
1128 {
1129  typedef Ewoms::ConvergenceCriterion<X> ConvergenceCriterion;
1130 
1131 public:
1133  typedef X domain_type;
1135  typedef Y range_type;
1137  typedef typename X::field_type field_type;
1138 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
1139  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
1141 #else
1142  typedef field_type real_type;
1143 #endif
1144  typedef F basis_type;
1146 
1153  template <class L, class P>
1154  RestartedGMResSolver(L& op, P& prec, real_type reduction, int restart, int maxit, int verbose) :
1155  _A(op), _W(prec),
1156  ssp(), _sp(ssp), _restart(restart),
1157  _maxit(maxit), _verbose(verbose)
1158  {
1159  static_assert(static_cast<int>(P::category) == static_cast<int>(L::category),
1160  "P and L must be the same category!");
1161  static_assert(static_cast<int>(L::category) == static_cast<int>(Dune::SolverCategory::sequential),
1162  "L must be sequential!");
1163 
1164  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
1165  this->setConvergenceCriterion(crit);
1166  }
1167 
1174  template <class L, class S, class P>
1175  RestartedGMResSolver(L& op, S& sp, P& prec, real_type reduction, int restart, int maxit, int verbose) :
1176  _A(op), _W(prec),
1177  _sp(sp), _restart(restart),
1178  _maxit(maxit), _verbose(verbose)
1179  {
1180  static_assert(static_cast<int>(P::category) == static_cast<int>(L::category),
1181  "P and L must have the same category!");
1182  static_assert(static_cast<int>(P::category) == static_cast<int>(S::category),
1183  "P and S must have the same category!");
1184 
1185  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
1186  this->setConvergenceCriterion(crit);
1187  }
1188 
1194  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
1195  {
1196  const real_type EPSILON = 1e-80;
1197  const int m = _restart;
1198  real_type norm, norm_0;
1199  int j = 1;
1200  std::vector<field_type> s(m+1), sn(m);
1201  std::vector<real_type> cs(m);
1202  // need copy of rhs if GMRes has to be restarted
1203  Y b2(b);
1204  // helper vector
1205  Y w(b);
1206  std::vector< std::vector<field_type> > H(m+1, s);
1207  std::vector<F> v(m+1, b);
1208 
1209  // start timer
1210  Dune::Timer watch;
1211  watch.reset();
1212 
1213  // clear solver statistics and set res.converged to false
1214  res.clear();
1215  _W.pre(x, b);
1216 
1217  // calculate defect and overwrite rhs with it
1218  _A.applyscaleadd(-1.0, x, b); // b -= Ax
1219  // calculate preconditioned defect
1220  v[0] = 0.0; _W.apply(v[0], b); // r = W^-1 b
1221  norm_0 = _sp.norm(v[0]);
1222  norm = norm_0;
1223 
1224  this->convergenceCriterion().setInitial(x, b, norm_0);
1225  if (_verbose > 0) {
1226  std::cout << "=== RestartedGMResSolver" << std::endl << std::flush;
1227  if (_verbose > 1)
1228  this->convergenceCriterion().printInitial();
1229  }
1230  if (this->convergenceCriterion().converged())
1231  res.converged = true;
1232 
1233  while (j <= _maxit && res.converged != true) {
1234 
1235  int i = 0;
1236  v[0] *= 1.0/norm;
1237  s[0] = norm;
1238  for (i=1; i < m+1; i++)
1239  s[i] = 0.0;
1240 
1241  for (i=0; i < m && j <= _maxit && res.converged != true; i++, j++) {
1242  w = 0.0;
1243  // use v[i+1] as temporary vector
1244  v[i+1] = 0.0;
1245  // do Arnoldi algorithm
1246  _A.apply(v[i], v[i+1]);
1247  _W.apply(w, v[i+1]);
1248  for (int k=0; k < i+1; k++) {
1249  // notice that _sp.dot (v[k], w) = v[k]\adjoint w
1250  // so one has to pay attention to the order
1251  // the in scalar product for the complex case
1252  // doing the modified Gram-Schmidt algorithm
1253  H[k][i] = _sp.dot(v[k], w);
1254  // w -= H[k][i] * v[k]
1255  w.axpy(-H[k][i], v[k]);
1256  }
1257  H[i+1][i] = _sp.norm(w);
1258  if (std::abs(H[i+1][i]) < EPSILON)
1259  DUNE_THROW(Dune::ISTLError,
1260  "breakdown in GMRes - |w| == 0.0 after " << j << " iterations");
1261 
1262  // normalize new vector
1263  v[i+1] = w; v[i+1] *= 1.0/H[i+1][i];
1264 
1265  // update QR factorization
1266  for (int k=0; k < i; k++)
1267  applyPlaneRotation(H[k][i], H[k+1][i], cs[k], sn[k]);
1268 
1269  // compute new givens rotation
1270  generatePlaneRotation(H[i][i], H[i+1][i], cs[i], sn[i]);
1271  // finish updating QR factorization
1272  applyPlaneRotation(H[i][i], H[i+1][i], cs[i], sn[i]);
1273  applyPlaneRotation(s[i], s[i+1], cs[i], sn[i]);
1274 
1275  // norm of the defect is the last component the vector s
1276  norm = std::abs(s[i+1]);
1277 
1278  this->convergenceCriterion().update(x, b);
1279  if (_verbose > 1)
1280  this->convergenceCriterion().print(j);
1281  if (this->convergenceCriterion().converged()) {
1282  res.converged = true;
1283  }
1284  } // end for
1285 
1286  // calculate update vector
1287  w = 0.0;
1288  update(w, i, H, s, v);
1289  // and current iterate
1290  x += w;
1291 
1292  // restart GMRes if convergence was not achieved,
1293  // i.e. linear defect has not reached desired reduction
1294  // and if j < _maxit
1295  if (res.converged != true && j <= _maxit ) {
1296 
1297  if (_verbose > 0)
1298  std::cout << "=== GMRes::restart" << std::endl;
1299  // get saved rhs
1300  b = b2;
1301  // calculate new defect
1302  _A.applyscaleadd(-1.0, x, b); // b -= Ax;
1303  // calculate preconditioned defect
1304  v[0] = 0.0;
1305  _W.apply(v[0], b);
1306  norm = _sp.norm(v[0]);
1307  }
1308 
1309  } //end while
1310 
1311  // postprocess preconditioner
1312  _W.post(x);
1313 
1314  // save solver statistics
1315  res.iterations = j-1; // it has to be j-1!!!
1316  res.reduction = this->convergenceCriterion().accuracy();
1317  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
1318  res.elapsed = watch.elapsed();
1319 
1320  if (_verbose > 0)
1321  this->convergenceCriterion().print(j);
1322  }
1323 
1324 private :
1325  void update(X& w, int i,
1326  const std::vector<std::vector<field_type> >& H,
1327  const std::vector<field_type>& s,
1328  const std::vector<X>& v) {
1329  // solution vector of the upper triangular system
1330  std::vector<field_type> y(s);
1331 
1332  // backsolve
1333  for (int a=i-1; a >=0; a--) {
1334  field_type rhs(s[a]);
1335  for (int b=a+1; b < i; b++)
1336  rhs -= H[a][b]*y[b];
1337  y[a] = rhs/H[a][a];
1338 
1339  // compute update on the fly
1340  // w += y[a]*v[a]
1341  w.axpy(y[a], v[a]);
1342  }
1343  }
1344 
1345  template <typename T>
1346  typename std::enable_if<std::is_same<field_type, real_type>::value, T>::type conjugate(const T& t) {
1347  return t;
1348  }
1349 
1350  template <typename T>
1351  typename std::enable_if<!std::is_same<field_type, real_type>::value, T>::type conjugate(const T& t) {
1352  return conj(t);
1353  }
1354 
1355  void
1356  generatePlaneRotation(field_type& dx, field_type& dy, real_type& cs, field_type& sn)
1357  {
1358  real_type norm_dx = std::abs(dx);
1359  real_type norm_dy = std::abs(dy);
1360  if (norm_dy < 1e-15) {
1361  cs = 1.0;
1362  sn = 0.0;
1363  } else if (norm_dx < 1e-15) {
1364  cs = 0.0;
1365  sn = 1.0;
1366  } else if (norm_dy > norm_dx) {
1367  real_type temp = norm_dx/norm_dy;
1368  cs = 1.0/std::sqrt(1.0 + temp*temp);
1369  sn = cs;
1370  cs *= temp;
1371  sn *= dx/norm_dx;
1372  sn *= conjugate(dy)/norm_dy;
1373  } else {
1374  real_type temp = norm_dy/norm_dx;
1375  cs = 1.0/std::sqrt(1.0 + temp*temp);
1376  sn = cs;
1377  sn *= conjugate(dy/dx);
1378  }
1379  }
1380 
1381 
1382  void
1383  applyPlaneRotation(field_type& dx, field_type& dy, real_type& cs, field_type& sn)
1384  {
1385  field_type temp = cs * dx + sn * dy;
1386  dy = -conjugate(sn) * dx + cs * dy;
1387  dx = temp;
1388  }
1389 
1390  Dune::LinearOperator<X, X> &_A;
1391  Dune::Preconditioner<X, X> &_W;
1392  Dune::SeqScalarProduct<X> ssp;
1393  Dune::ScalarProduct<X> &_sp;
1394  int _restart;
1395  int _maxit;
1396  int _verbose;
1397 };
1398 
1399 
1413 template <class X>
1415 {
1416  typedef Ewoms::ConvergenceCriterion<X> ConvergenceCriterion;
1417 
1418 public:
1420  typedef X domain_type;
1422  typedef X range_type;
1424  typedef typename X::field_type field_type;
1425 #if DUNE_VERSION_NEWER(DUNE_COMMON, 2,4)
1426  typedef typename Dune::FieldTraits<field_type>::real_type real_type;
1428 #else
1429  typedef field_type real_type;
1430 #endif
1431 
1439  template <class L, class P>
1440  GeneralizedPCGSolver(L& op, P& prec, real_type reduction, int maxit, int verbose,
1441  int restart = 10) :
1442  ssp(), _op(op), _prec(prec), _sp(ssp), _maxit(maxit),
1443  _verbose(verbose), _restart(std::min(maxit, restart))
1444  {
1445  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
1446  "L and P have to have the same category!");
1447  static_assert(static_cast<int>(L::category) ==
1448  static_cast<int>(Dune::SolverCategory::sequential),
1449  "L has to be sequential!");
1450 
1451  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
1452  this->setConvergenceCriterion(crit);
1453  }
1454 
1462  template <class L, class P, class S>
1463  GeneralizedPCGSolver(L& op, S& sp, P& prec,
1464  real_type reduction, int maxit, int verbose, int restart=10) :
1465  _op(op), _prec(prec), _sp(sp), _maxit(maxit), _verbose(verbose),
1466  _restart(std::min(maxit, restart))
1467  {
1468  static_assert(static_cast<int>(L::category) == static_cast<int>(P::category),
1469  "L and P must have the same category!");
1470  static_assert(static_cast<int>(L::category) == static_cast<int>(S::category),
1471  "L and S must have the same category!");
1472 
1473  auto crit = std::make_shared<ResidReductionCriterion<X>>(_sp, reduction);
1474  this->setConvergenceCriterion(crit);
1475  }
1481  virtual void apply(X& x, X& b, Dune::InverseOperatorResult& res)
1482  {
1483  res.clear(); // clear solver statistics
1484  Dune::Timer watch; // start a timer
1485  _prec.pre(x, b); // prepare preconditioner
1486  _op.applyscaleadd(-1, x, b); // overwrite b with defect
1487 
1488  std::vector<std::shared_ptr<X> > p(_restart);
1489  std::vector<typename X::field_type> pp(_restart);
1490  X q(x); // a temporary vector
1491  X prec_res(x); // a temporary vector for preconditioner output
1492 
1493  p[0].reset(new X(x));
1494 
1495  this->convergenceCriterion().setInitial(x, b);
1496  if (_verbose > 0) {
1497  std::cout << "=== GeneralizedPCGSolver" << std::endl << std::flush;
1498  if (_verbose > 1)
1499  this->convergenceCriterion().printInitial();
1500  }
1501  if (this->convergenceCriterion().converged()) {
1502  res.converged = true;
1503  res.iterations = 0;
1504  res.reduction = this->convergenceCriterion().accuracy();
1505  res.conv_rate = 0;
1506  res.elapsed = 0;
1507  return;
1508  }
1509 
1510  // some local variables
1511  field_type rho, lambda;
1512 
1513  int i = 0;
1514  int ii = 0;
1515  // determine initial search direction
1516  *(p[0]) = 0; // clear correction
1517  _prec.apply(*(p[0]), b); // apply preconditioner
1518  rho = _sp.dot(*(p[0]), b); // orthogonalization
1519  _op.apply(*(p[0]), q); // q=Ap
1520  pp[0] = _sp.dot(*(p[0]), q); // scalar product
1521  lambda = rho/pp[0]; // minimization
1522  x.axpy(lambda, *(p[0])); // update solution
1523  b.axpy(-lambda, q); // update defect
1524 
1525  // convergence test
1526  this->convergenceCriterion().update(x, b);
1527  if (_verbose > 1) // print
1528  this->convergenceCriterion().print(i);
1529  if (this->convergenceCriterion().converged()) {
1530  // fill statistics
1531  res.converged = true;
1532  }
1533 
1534  while (i < _maxit) {
1535  // the loop
1536  int end = std::min(_restart, _maxit-i+1);
1537  for (ii=1; ii < end;++ii )
1538  {
1539  //std::cout<<" ii="<<ii<<" i="<<i<<std::endl;
1540  // compute next conjugate direction
1541  prec_res = 0; // clear correction
1542  _prec.apply(prec_res, b); // apply preconditioner
1543 
1544  p[ii].reset(new X(prec_res));
1545  _op.apply(prec_res, q);
1546 
1547  for (int j=0; j < ii;++j) {
1548  rho = _sp.dot(q, *(p[j]))/pp[j];
1549  p[ii]->axpy(-rho, *(p[j]));
1550  }
1551 
1552  // minimize in given search direction
1553  _op.apply(*(p[ii]), q); // q=Ap
1554  pp[ii] = _sp.dot(*(p[ii]), q); // scalar product
1555  rho = _sp.dot(*(p[ii]), b); // orthogonalization
1556  lambda = rho/pp[ii]; // minimization
1557  x.axpy(lambda, *(p[ii])); // update solution
1558  b.axpy(-lambda, q); // update defect
1559 
1560  // convergence test
1561  this->convergenceCriterion().update(x, b);
1562  if (_verbose > 1) // print
1563  this->convergenceCriterion().print(i);
1564  if (this->convergenceCriterion().converged()) {
1565  res.converged = true;
1566  break;
1567  }
1568  }
1569  if (res.converged)
1570  break;
1571  if (end == _restart) {
1572  *(p[0])=*(p[_restart-1]);
1573  pp[0]=pp[_restart-1];
1574  }
1575  }
1576 
1577  // postprocess preconditioner
1578  _prec.post(x);
1579 
1580  // fill statistics
1581  res.iterations = i;
1582  res.reduction = this->convergenceCriterion().accuracy();
1583  res.conv_rate = std::pow(res.reduction, 1.0/res.iterations);
1584  res.elapsed = watch.elapsed();
1585 
1586  if (_verbose == 1) // printing in non-verbose mode
1587  this->convergenceCriterion().print(i);
1588  }
1589 
1590 private:
1591  Dune::SeqScalarProduct<X> ssp;
1592  Dune::LinearOperator<X, X> &_op;
1593  Dune::Preconditioner<X, X> &_prec;
1594  Dune::ScalarProduct<X> &_sp;
1595  int _maxit;
1596  int _verbose;
1597  int _restart;
1598 };
1599 
1602 } // end namespace
1603 
1604 #endif
X domain_type
Type of the domain of the operator to be inverted.
Definition: solvers.hh:106
X::field_type field_type
The field type of the operator to be inverted.
Definition: solvers.hh:1424
conjugate gradient method
Definition: solvers.hh:478
virtual ~InverseOperator()
Destructor.
Definition: solvers.hh:147
field_type real_type
Definition: solvers.hh:1429
X::field_type field_type
The field type of the operator to be inverted.
Definition: solvers.hh:1137
F basis_type
The field type of the basis vectors.
Definition: solvers.hh:1145
Abstract base class for all solvers.
Definition: solvers.hh:102
RestartedGMResSolver(L &op, S &sp, P &prec, real_type reduction, int restart, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:1175
Base class for all convergence criteria which only defines an virtual API.
Definition: convergencecriterion.hh:51
LoopSolver(L &op, P &prec, real_type reduction, int maxit, int verbose)
Set up Loop solver.
Definition: solvers.hh:205
Provides a convergence criterion which looks at the reduction of the two-norm of the residual for the...
X range_type
The range type of the operator to be inverted.
Definition: solvers.hh:869
X::field_type field_type
The field type of the operator to be inverted.
Definition: solvers.hh:633
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:1194
X::field_type field_type
The field type of the operator.
Definition: solvers.hh:112
X domain_type
The domain type of the operator to be inverted.
Definition: solvers.hh:1133
X range_type
The range type of the operator that we do the inverse for.
Definition: solvers.hh:175
X domain_type
The domain type of the operator that we do the inverse for.
Definition: solvers.hh:173
Provides a convergence criterion for the linear solvers which looks at the weighted maximum of the di...
X domain_type
The domain type of the operator to be inverted.
Definition: solvers.hh:484
X::field_type field_type
The field type of the operator that we do the inverse for.
Definition: solvers.hh:177
gradient method
Definition: solvers.hh:344
LoopSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose)
Set up loop solver.
Definition: solvers.hh:239
field_type real_type
Definition: solvers.hh:359
BiCGSTABSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:665
X range_type
The range type of the operator to be inverted.
Definition: solvers.hh:631
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:405
virtual const Ewoms::ConvergenceCriterion< X > & convergenceCriterion() const
Return the criterion to be used to check for convergence of the linear solver.
Definition: solvers.hh:118
field_type real_type
Definition: solvers.hh:1142
STL namespace.
CGSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose)
Set up conjugate gradient solver.
Definition: solvers.hh:515
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:919
X domain_type
The domain type of the operator to be inverted.
Definition: solvers.hh:629
RestartedGMResSolver(L &op, P &prec, real_type reduction, int restart, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:1154
virtual void setConvergenceCriterion(std::shared_ptr< Ewoms::ConvergenceCriterion< X > > convCrit)
Set the criterion to be used to check for convergence of the linear solver.
Definition: solvers.hh:132
X range_type
The range type of the operator to be inverted.
Definition: solvers.hh:1422
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Definition: solvers.hh:254
Definition: baseauxiliarymodule.hh:35
X::field_type field_type
The field type of the operator to be inverted.
Definition: solvers.hh:871
Preconditioned loop solver.
Definition: solvers.hh:167
GeneralizedPCGSolver(L &op, P &prec, real_type reduction, int maxit, int verbose, int restart=10)
Set up nonlinear preconditioned conjugate gradient solver.
Definition: solvers.hh:1440
MINRESSolver(L &op, P &prec, real_type reduction, int maxit, int verbose)
Set up MINRES solver.
Definition: solvers.hh:885
field_type real_type
Definition: solvers.hh:638
Dune::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: solvers.hh:490
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:532
virtual Ewoms::ConvergenceCriterion< X > & convergenceCriterion()
Return the criterion to be used to check for convergence of the linear solver.
Definition: solvers.hh:125
MINRESSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose)
Set up MINRES solver.
Definition: solvers.hh:902
Bi-conjugate Gradient Stabilized (BiCG-STAB)
Definition: solvers.hh:623
GradientSolver(L &op, P &prec, real_type reduction, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:369
X range_type
The range type of the operator to be inverted.
Definition: solvers.hh:486
field_type real_type
Definition: solvers.hh:182
BiCGSTABSolver(L &op, P &prec, real_type reduction, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:647
Minimal Residual Method (MINRES)
Definition: solvers.hh:861
Convergence criterion which looks at the weighted absolute value of the residual. ...
X::field_type field_type
The field type of the operator that we do the inverse for.
Definition: solvers.hh:354
Generalized preconditioned conjugate gradient solver.
Definition: solvers.hh:1414
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:1481
X range_type
The range type of the operator that we do the inverse for.
Definition: solvers.hh:352
GeneralizedPCGSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose, int restart=10)
Set up nonlinear preconditioned conjugate gradient solver.
Definition: solvers.hh:1463
GradientSolver(L &op, S &sp, P &prec, real_type reduction, int maxit, int verbose)
Set up solver.
Definition: solvers.hh:387
implements the Generalized Minimal Residual (GMRes) method
Definition: solvers.hh:1127
Y range_type
Type of the range of the operator to be inverted.
Definition: solvers.hh:109
X domain_type
The domain type of the operator to be inverted.
Definition: solvers.hh:1420
virtual void apply(X &x, Y &b, Dune::InverseOperatorResult &res)=0
Apply inverse operator,.
Y range_type
The range type of the operator to be inverted.
Definition: solvers.hh:1135
X domain_type
The domain type of the operator to be inverted.
Definition: solvers.hh:867
X domain_type
The domain type of the operator that we do the inverse for.
Definition: solvers.hh:350
virtual void apply(X &x, X &b, Dune::InverseOperatorResult &res)
Apply inverse operator.
Definition: solvers.hh:683
CGSolver(L &op, P &prec, real_type reduction, int maxit, int verbose)
Set up conjugate gradient solver.
Definition: solvers.hh:498
field_type real_type
Definition: solvers.hh:876
X::field_type field_type
The field type of the operator to be inverted.
Definition: solvers.hh:488