1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3 #ifndef DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH
4 #define DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH
5 
6 #include <dune/common/deprecated.hh>
7 #include <dune/common/parallel/mpihelper.hh>
8 
9 #include <dune/istl/owneroverlapcopy.hh>
10 #include <dune/istl/solvercategory.hh>
11 #include <dune/istl/operators.hh>
12 #include <dune/istl/solvers.hh>
13 #include <dune/istl/preconditioners.hh>
14 #include <dune/istl/scalarproducts.hh>
15 #include <dune/istl/paamg/amg.hh>
16 #include <dune/istl/paamg/pinfo.hh>
17 #include <dune/istl/io.hh>
18 #include <dune/istl/superlu.hh>
19 #include <dune/istl/umfpack.hh>
20 
21 #include <dune/pdelab/constraints/common/constraints.hh>
22 #include <dune/pdelab/gridfunctionspace/genericdatahandle.hh>
23 #include <dune/pdelab/backend/solver.hh>
24 #include <dune/pdelab/backend/istl/vector.hh>
25 #include <dune/pdelab/backend/istl/bcrsmatrix.hh>
26 
27 namespace Dune {
28   namespace PDELab {
29 
30     //! \addtogroup Backend
31     //! \ingroup PDELab
32     //! \{
33 
34 
35     /**Create ISTL operator from a grid operator object
36      *
37      * In the nonlinear case the operator need to be linearized by setting a
38      * linearization point before it can be used.
39      *
40      * \tparam X Trial vector.
41      * \tparam Y Test vector.
42      * \tparam GO Grid operator that implements the jacobian apply
43      */
44     template<typename X, typename Y, typename GO>
45     class OnTheFlyOperator : public Dune::LinearOperator<X,Y>
46     {
47     public:
48       typedef X domain_type;
49       typedef Y range_type;
50       typedef typename X::field_type field_type;
51       static constexpr bool isLinear = GO::LocalAssembler::isLinear();
52 
53 
OnTheFlyOperator(const GO & go_)54       OnTheFlyOperator (const GO& go_)
55         : go(go_)
56         , u_(nullptr)
57       {}
58 
59       //! Set linearization point.
60       //! Must be called before apply() and applyscaleadd() for nonlinear problems.
setLinearizationPoint(const X & u)61       void setLinearizationPoint(const X& u)
62       {
63         u_ = &u;
64       }
65 
apply(const X & x,Y & y) const66       virtual void apply (const X& x, Y& y) const override
67       {
68         y = 0.0;
69         if (isLinear)
70           go.jacobian_apply(x,y);
71         else {
72           if (u_ == nullptr)
73             DUNE_THROW(Dune::InvalidStateException, "You seem to apply a nonlinear operator without setting the linearization point first!");
74           go.jacobian_apply(*u_, x, y);
75         }
76       }
77 
applyscaleadd(field_type alpha,const X & x,Y & y) const78       virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const override
79       {
80         Y temp(y);
81         temp = 0.0;
82         if (isLinear)
83           go.jacobian_apply(x,temp);
84         else {
85           if (u_ == nullptr)
86             DUNE_THROW(Dune::InvalidStateException, "You seem to apply a nonlinear operator without setting the linearization point first!");
87           go.jacobian_apply(*u_, x, temp);
88         }
89         y.axpy(alpha,temp);
90       }
91 
category() const92       SolverCategory::Category category() const override
93       {
94         return SolverCategory::sequential;
95       }
96 
97     private:
98       const GO& go;
99       const X* u_;
100     };
101 
102     //==============================================================================
103     // Here we add some standard linear solvers conforming to the linear solver
104     // interface required to solve linear and nonlinear problems.
105     //==============================================================================
106 
107     //=====================================================================
108     // First we add some base classes where the preconditioner is specified
109     //=====================================================================
110 
111     template<template<class> class Solver>
112     class ISTLBackend_SEQ_Richardson
113       : public SequentialNorm, public LinearResultStorage
114     {
115     public:
116       /*! \brief make a linear solver object
117 
118         \param[in] maxiter_ maximum number of iterations to do
119         \param[in] verbose_ print messages if true
120       */
ISTLBackend_SEQ_Richardson(unsigned maxiter_=5000,int verbose_=1)121       explicit ISTLBackend_SEQ_Richardson(unsigned maxiter_=5000, int verbose_=1)
122         : maxiter(maxiter_), verbose(verbose_)
123       {}
124 
125       /*! \brief solve the given linear system
126 
127         \param[in] A the given matrix
128         \param[out] z the solution vector to be computed
129         \param[in] r right hand side
130         \param[in] reduction to be achieved
131       */
132       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)133       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
134       {
135         using Backend::Native;
136         using Backend::native;
137 
138         Dune::MatrixAdapter<Native<M>,
139                             Native<V>,
140                             Native<W>> opa(native(A));
141         Dune::Richardson<Native<V>,Native<W> > prec(0.7);
142         Solver<Native<V> > solver(opa, prec, reduction, maxiter, verbose);
143         Dune::InverseOperatorResult stat;
144         solver.apply(native(z), native(r), stat);
145         res.converged  = stat.converged;
146         res.iterations = stat.iterations;
147         res.elapsed    = stat.elapsed;
148         res.reduction  = stat.reduction;
149         res.conv_rate  = stat.conv_rate;
150       }
151 
152     private:
153       unsigned maxiter;
154       int verbose;
155     };
156 
157     template<class GO, template<class> class Solver>
158     class ISTLBackend_SEQ_MatrixFree_Richardson
159       : public SequentialNorm, public LinearResultStorage
160     {
161       using V = typename GO::Traits::Domain;
162       using W = typename GO::Traits::Range;
163     public:
164       /*! \brief make a linear solver object
165 
166         \param[in] maxiter_ maximum number of iterations to do
167         \param[in] verbose_ print messages if true
168       */
ISTLBackend_SEQ_MatrixFree_Richardson(const GO & go,unsigned maxiter=5000,int verbose=1)169       explicit ISTLBackend_SEQ_MatrixFree_Richardson(const GO& go, unsigned maxiter=5000, int verbose=1)
170         : opa_(go)
171         , maxiter_(maxiter)
172         , verbose_(verbose)
173       {}
174 
175       /*! \brief solve the given linear system
176 
177         \param[in] A the given matrix
178         \param[out] z the solution vector to be computed
179         \param[in] r right hand side
180         \param[in] reduction to be achieved
181       */
apply(V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)182       void apply(V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
183       {
184         Dune::Richardson<V,W> prec(1.0);
185         Solver<V> solver(opa_, prec, reduction, maxiter_, verbose_);
186         Dune::InverseOperatorResult stat;
187         solver.apply(z, r, stat);
188         res.converged  = stat.converged;
189         res.iterations = stat.iterations;
190         res.elapsed    = stat.elapsed;
191         res.reduction  = stat.reduction;
192         res.conv_rate  = stat.conv_rate;
193       }
194 
195       //! Set position of jacobian, ust be called before apply() for nonlinear problems.
setLinearizationPoint(const V & u)196       void setLinearizationPoint(const V& u)
197       {
198         opa_.setLinearizationPoint(u);
199       }
200 
201     private:
202       Dune::PDELab::OnTheFlyOperator<V,W,GO> opa_;
203       unsigned maxiter_;
204       int verbose_;
205     };
206 
207     template<template<class,class,class,int> class Preconditioner,
208              template<class> class Solver>
209     class ISTLBackend_SEQ_Base
210       : public SequentialNorm, public LinearResultStorage
211     {
212     public:
213       /*! \brief make a linear solver object
214 
215         \param[in] maxiter_ maximum number of iterations to do
216         \param[in] verbose_ print messages if true
217       */
ISTLBackend_SEQ_Base(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)218       explicit ISTLBackend_SEQ_Base(unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
219         : maxiter(maxiter_), verbose(verbose_), preconditioner_steps(preconditioner_steps_)
220       {}
221 
222 
223 
224       /*! \brief solve the given linear system
225 
226         \param[in] A the given matrix
227         \param[out] z the solution vector to be computed
228         \param[in] r right hand side
229         \param[in] reduction to be achieved
230       */
231       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)232       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
233       {
234         using Backend::Native;
235         using Backend::native;
236 
237         Dune::MatrixAdapter<Native<M>,
238                             Native<V>,
239                             Native<W>> opa(native(A));
240         Preconditioner<Native<M>,
241                        Native<V>,
242                        Native<W>,
243                        1> prec(native(A), preconditioner_steps, 1.0);
244         Solver<Native<V>> solver(opa, prec, reduction, maxiter, verbose);
245         Dune::InverseOperatorResult stat;
246         solver.apply(native(z), native(r), stat);
247         res.converged  = stat.converged;
248         res.iterations = stat.iterations;
249         res.elapsed    = stat.elapsed;
250         res.reduction  = stat.reduction;
251         res.conv_rate  = stat.conv_rate;
252       }
253 
254     private:
255       unsigned maxiter;
256       int verbose;
257       unsigned preconditioner_steps;
258     };
259 
260     template<template<typename> class Solver>
261     class ISTLBackend_SEQ_ILU0
262       :  public SequentialNorm, public LinearResultStorage
263     {
264     public:
265       /*! \brief make a linear solver object
266 
267         \param[in] maxiter_ maximum number of iterations to do
268         \param[in] verbose_ print messages if true
269       */
ISTLBackend_SEQ_ILU0(unsigned maxiter_=5000,int verbose_=1)270       explicit ISTLBackend_SEQ_ILU0 (unsigned maxiter_=5000, int verbose_=1)
271         : maxiter(maxiter_), verbose(verbose_)
272        {}
273       /*! \brief solve the given linear system
274 
275         \param[in] A the given matrix
276         \param[out] z the solution vector to be computed
277         \param[in] r right hand side
278         \param[in] reduction to be achieved
279       */
280       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)281       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
282       {
283         using Backend::Native;
284         using Backend::native;
285         Dune::MatrixAdapter<Native<M>,
286                             Native<V>,
287                             Native<W>> opa(native(A));
288         Dune::SeqILU<Native<M>,
289                       Native<V>,
290                       Native<W>
291                       > ilu0(native(A), 1.0);
292         Solver<Native<V>> solver(opa, ilu0, reduction, maxiter, verbose);
293         Dune::InverseOperatorResult stat;
294         solver.apply(native(z), native(r), stat);
295         res.converged  = stat.converged;
296         res.iterations = stat.iterations;
297         res.elapsed    = stat.elapsed;
298         res.reduction  = stat.reduction;
299         res.conv_rate  = stat.conv_rate;
300        }
301     private:
302       unsigned maxiter;
303       int verbose;
304     };
305 
306     template<template<typename> class Solver>
307     class ISTLBackend_SEQ_ILUn
308       :  public SequentialNorm, public LinearResultStorage
309     {
310     public:
311       /*! \brief make a linear solver object
312         \param[in] n The number of levels to be used.
313         \param[in] w The relaxation factor.
314         \param[in] maxiter_ maximum number of iterations to do
315         \param[in] verbose_ print messages if true
316       */
ISTLBackend_SEQ_ILUn(int n,double w,unsigned maxiter_=5000,int verbose_=1)317       ISTLBackend_SEQ_ILUn (int n, double w, unsigned maxiter_=5000, int verbose_=1)
318         : n_(n), w_(w), maxiter(maxiter_), verbose(verbose_)
319        {}
320       /*! \brief solve the given linear system
321 
322         \param[in] A the given matrix
323         \param[out] z the solution vector to be computed
324         \param[in] r right hand side
325         \param[in] reduction to be achieved
326       */
327       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)328       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
329       {
330         using Backend::Native;
331         using Backend::native;
332         Dune::MatrixAdapter<Native<M>,
333                             Native<V>,
334                             Native<W>
335                             > opa(native(A));
336         Dune::SeqILU<Native<M>,
337                       Native<V>,
338                       Native<W>
339                       > ilun(native(A), n_, w_, false);
340         Solver<Native<V>> solver(opa, ilun, reduction, maxiter, verbose);
341         Dune::InverseOperatorResult stat;
342         solver.apply(native(z), native(r), stat);
343         res.converged  = stat.converged;
344         res.iterations = stat.iterations;
345         res.elapsed    = stat.elapsed;
346         res.reduction  = stat.reduction;
347         res.conv_rate  = stat.conv_rate;
348        }
349     private:
350       int n_;
351       double w_;
352 
353       unsigned maxiter;
354       int verbose;
355     };
356 
357     //========================================
358     // Start with matrix based solver backends
359     //========================================
360 
361     //! \addtogroup PDELab_seqsolvers Sequential Solvers
362     //! \{
363 
364     /**
365      * @brief Backend for sequential loop solver with Jacobi preconditioner.
366      */
367     class ISTLBackend_SEQ_LOOP_Jac
368       : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::LoopSolver>
369     {
370     public:
371       /*! \brief make a linear solver object
372         \param[in] maxiter_ maximum number of iterations to do
373         \param[in] verbose_ print messages if true
374       */
ISTLBackend_SEQ_LOOP_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)375       explicit ISTLBackend_SEQ_LOOP_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
376         : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::LoopSolver>(maxiter_, verbose_, preconditioner_steps_)
377       {}
378     };
379 
380    /**
381      * @brief Backend for sequential BiCGSTAB solver with Richardson
382      * precondition (equivalent to no preconditioner for Richards with
383      * parameter=1.0).
384      */
385     class ISTLBackend_SEQ_BCGS_Richardson
386       : public ISTLBackend_SEQ_Richardson<Dune::BiCGSTABSolver>
387     {
388     public:
389       /*! \brief make a linear solver object
390         \param[in] maxiter_ maximum number of iterations to do
391         \param[in] verbose_ print messages if true
392       */
ISTLBackend_SEQ_BCGS_Richardson(unsigned maxiter_=5000,int verbose_=1)393       explicit ISTLBackend_SEQ_BCGS_Richardson (unsigned maxiter_=5000, int verbose_=1)
394         : ISTLBackend_SEQ_Richardson<Dune::BiCGSTABSolver>(maxiter_, verbose_)
395       {}
396     };
397 
398     /**
399      * @brief Backend for sequential BiCGSTAB solver with Jacobi preconditioner.
400      */
401     class ISTLBackend_SEQ_BCGS_Jac
402       : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::BiCGSTABSolver>
403     {
404     public:
405       /*! \brief make a linear solver object
406         \param[in] maxiter_ maximum number of iterations to do
407         \param[in] verbose_ print messages if true
408       */
ISTLBackend_SEQ_BCGS_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)409       explicit ISTLBackend_SEQ_BCGS_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
410         : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::BiCGSTABSolver>(maxiter_, verbose_, preconditioner_steps_)
411       {}
412     };
413 
414     /**
415      * @brief Backend for sequential BiCGSTAB solver with SSOR preconditioner.
416      */
417     class ISTLBackend_SEQ_BCGS_SSOR
418       : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::BiCGSTABSolver>
419     {
420     public:
421       /*! \brief make a linear solver object
422 
423         \param[in] maxiter_ maximum number of iterations to do
424         \param[in] verbose_ print messages if true
425       */
ISTLBackend_SEQ_BCGS_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)426       explicit ISTLBackend_SEQ_BCGS_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
427         : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::BiCGSTABSolver>(maxiter_, verbose_, preconditioner_steps_)
428       {}
429     };
430 
431      /**
432      * @brief Backend for sequential BiCGSTAB solver with ILU0 preconditioner.
433      */
434     class ISTLBackend_SEQ_BCGS_ILU0
435       : public ISTLBackend_SEQ_ILU0<Dune::BiCGSTABSolver>
436     {
437     public:
438       /*! \brief make a linear solver object
439 
440         \param[in] maxiter_ maximum number of iterations to do
441         \param[in] verbose_ print messages if true
442       */
ISTLBackend_SEQ_BCGS_ILU0(unsigned maxiter_=5000,int verbose_=1)443       explicit ISTLBackend_SEQ_BCGS_ILU0 (unsigned maxiter_=5000, int verbose_=1)
444         : ISTLBackend_SEQ_ILU0<Dune::BiCGSTABSolver>(maxiter_, verbose_)
445       {}
446     };
447 
448     /**
449      * @brief Backend for sequential conjugate gradient solver with ILU0 preconditioner.
450      */
451     class ISTLBackend_SEQ_CG_ILU0
452       : public ISTLBackend_SEQ_ILU0<Dune::CGSolver>
453     {
454     public:
455       /*! \brief make a linear solver object
456 
457         \param[in] maxiter_ maximum number of iterations to do
458         \param[in] verbose_ print messages if true
459       */
ISTLBackend_SEQ_CG_ILU0(unsigned maxiter_=5000,int verbose_=1)460       explicit ISTLBackend_SEQ_CG_ILU0 (unsigned maxiter_=5000, int verbose_=1)
461         : ISTLBackend_SEQ_ILU0<Dune::CGSolver>(maxiter_, verbose_)
462       {}
463     };
464 
465     //! \brief Sequential BiCGStab solver with ILU0 preconditioner
466     class ISTLBackend_SEQ_BCGS_ILUn
467       : public ISTLBackend_SEQ_ILUn<Dune::BiCGSTABSolver>
468     {
469     public:
470       /*! \brief make a linear solver object
471 
472 
473         \param[in] n_ The number of levels to be used.
474         \param[in] w_ The relaxation factor.
475         \param[in] maxiter_ maximum number of iterations to do
476         \param[in] verbose_ print messages if true
477       */
ISTLBackend_SEQ_BCGS_ILUn(int n_,double w_=1.0,unsigned maxiter_=5000,int verbose_=1)478       explicit ISTLBackend_SEQ_BCGS_ILUn (int n_, double w_=1.0, unsigned maxiter_=5000, int verbose_=1)
479         : ISTLBackend_SEQ_ILUn<Dune::BiCGSTABSolver>(n_, w_, maxiter_, verbose_)
480       {}
481     };
482 
483     //! \brief Sequential congute gradient solver with ILU0 preconditioner
484     class ISTLBackend_SEQ_CG_ILUn
485       : public ISTLBackend_SEQ_ILUn<Dune::CGSolver>
486     {
487     public:
488       /*! \brief make a linear solver object
489 
490 
491         \param[in] n_ The number of levels to be used.
492         \param[in] w_ The relaxation factor.
493         \param[in] maxiter_ maximum number of iterations to do
494         \param[in] verbose_ print messages if true
495       */
ISTLBackend_SEQ_CG_ILUn(int n_,double w_=1.0,unsigned maxiter_=5000,int verbose_=1)496       explicit ISTLBackend_SEQ_CG_ILUn (int n_, double w_=1.0, unsigned maxiter_=5000, int verbose_=1)
497         : ISTLBackend_SEQ_ILUn<Dune::CGSolver>(n_, w_, maxiter_, verbose_)
498       {}
499     };
500 
501     /**
502      * @brief Backend for sequential conjugate gradient solver with SSOR preconditioner.
503      */
504     class ISTLBackend_SEQ_CG_SSOR
505       : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::CGSolver>
506     {
507     public:
508       /*! \brief make a linear solver object
509 
510         \param[in] maxiter_ maximum number of iterations to do
511         \param[in] verbose_ print messages if true
512       */
ISTLBackend_SEQ_CG_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)513       explicit ISTLBackend_SEQ_CG_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
514         : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::CGSolver>(maxiter_, verbose_, preconditioner_steps_)
515       {}
516     };
517 
518     /**
519      * @brief Backend using a MINRes solver preconditioned by SSOR.
520      */
521     class ISTLBackend_SEQ_MINRES_SSOR
522       : public ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::MINRESSolver>
523     {
524     public:
525       /*! \brief make a linear solver object
526 
527         \param[in] maxiter_ maximum number of iterations to do
528         \param[in] verbose_ print messages if true
529       */
ISTLBackend_SEQ_MINRES_SSOR(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)530       explicit ISTLBackend_SEQ_MINRES_SSOR (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
531         : ISTLBackend_SEQ_Base<Dune::SeqSSOR, Dune::MINRESSolver>(maxiter_, verbose_, preconditioner_steps_)
532       {}
533     };
534 
535     /**
536      * @brief Backend for conjugate gradient solver with Jacobi preconditioner.
537      */
538     class ISTLBackend_SEQ_CG_Jac
539       : public ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::CGSolver>
540     {
541     public:
542       /*! \brief make a linear solver object
543         \param[in] maxiter_ maximum number of iterations to do
544         \param[in] verbose_ print messages if true
545       */
ISTLBackend_SEQ_CG_Jac(unsigned maxiter_=5000,int verbose_=1,unsigned preconditioner_steps_=1)546       explicit ISTLBackend_SEQ_CG_Jac (unsigned maxiter_=5000, int verbose_=1, unsigned preconditioner_steps_=1)
547         : ISTLBackend_SEQ_Base<Dune::SeqJac, Dune::CGSolver>(maxiter_, verbose_, preconditioner_steps_)
548       {}
549     };
550 
551 #if HAVE_SUPERLU || DOXYGEN
552     /**
553      * @brief Solver backend using SuperLU as a direct solver.
554      */
555     class ISTLBackend_SEQ_SuperLU
556       : public SequentialNorm, public LinearResultStorage
557     {
558     public:
559       /*! \brief make a linear solver object
560 
561         \param[in] verbose_ print messages if true
562       */
ISTLBackend_SEQ_SuperLU(int verbose_=1)563       explicit ISTLBackend_SEQ_SuperLU (int verbose_=1)
564         : verbose(verbose_)
565       {}
566 
567 
568       /*! \brief make a linear solver object
569 
570         \param[in] maxiter Maximum number of allowed steps (ignored)
571         \param[in] verbose_ print messages if true
572       */
ISTLBackend_SEQ_SuperLU(int maxiter,int verbose_)573       ISTLBackend_SEQ_SuperLU (int maxiter, int verbose_)
574         : verbose(verbose_)
575       {}
576 
577       /*! \brief solve the given linear system
578 
579         \param[in] A the given matrix
580         \param[out] z the solution vector to be computed
581         \param[in] r right hand side
582         \param[in] reduction to be achieved
583       */
584       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)585       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
586       {
587         using Backend::Native;
588         using Backend::native;
589         using ISTLM = Native<M>;
590         Dune::SuperLU<ISTLM> solver(native(A), verbose);
591         Dune::InverseOperatorResult stat;
592         solver.apply(native(z), native(r), stat);
593         res.converged  = stat.converged;
594         res.iterations = stat.iterations;
595         res.elapsed    = stat.elapsed;
596         res.reduction  = stat.reduction;
597         res.conv_rate  = stat.conv_rate;
598       }
599 
600     private:
601       int verbose;
602     };
603 #endif // HAVE_SUPERLU || DOXYGEN
604 
605 #if HAVE_SUITESPARSE_UMFPACK || DOXYGEN
606     /**
607      * @brief Solver backend using UMFPack as a direct solver.
608      */
609     class ISTLBackend_SEQ_UMFPack
610       : public SequentialNorm, public LinearResultStorage
611     {
612     public:
613       /*! \brief make a linear solver object
614 
615         \param[in] verbose_ print messages if true
616       */
ISTLBackend_SEQ_UMFPack(int verbose_=1)617       explicit ISTLBackend_SEQ_UMFPack (int verbose_=1)
618         : verbose(verbose_)
619       {}
620 
621 
622       /*! \brief make a linear solver object
623 
624         \param[in] maxiter Maximum number of allowed steps (ignored)
625         \param[in] verbose_ print messages if true
626       */
ISTLBackend_SEQ_UMFPack(int maxiter,int verbose_)627       ISTLBackend_SEQ_UMFPack (int maxiter, int verbose_)
628         : verbose(verbose_)
629       {}
630 
631       /*! \brief solve the given linear system
632 
633         \param[in] A the given matrix
634         \param[out] z the solution vector to be computed
635         \param[in] r right hand side
636         \param[in] reduction to be achieved
637       */
638       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)639       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
640       {
641         using Backend::native;
642         using ISTLM = Backend::Native<M>;
643         Dune::UMFPack<ISTLM> solver(native(A), verbose);
644         Dune::InverseOperatorResult stat;
645         solver.apply(native(z), native(r), stat);
646         res.converged  = stat.converged;
647         res.iterations = stat.iterations;
648         res.elapsed    = stat.elapsed;
649         res.reduction  = stat.reduction;
650         res.conv_rate  = stat.conv_rate;
651       }
652 
653     private:
654       int verbose;
655     };
656 #endif // HAVE_SUITESPARSE_UMFPACK || DOXYGEN
657 
658     //! Solver to be used for explicit time-steppers with (block-)diagonal mass matrix
659     class ISTLBackend_SEQ_ExplicitDiagonal
660       : public SequentialNorm, public LinearResultStorage
661     {
662     public:
663       /*! \brief make a linear solver object
664       */
ISTLBackend_SEQ_ExplicitDiagonal()665       ISTLBackend_SEQ_ExplicitDiagonal ()
666       {}
667 
668       /*! \brief solve the given linear system
669 
670         \param[in] A the given matrix
671         \param[out] z the solution vector to be computed
672         \param[in] r right hand side
673         \param[in] reduction to be achieved
674       */
675       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)676       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
677       {
678         using Backend::Native;
679         Dune::SeqJac<Native<M>,
680                      Native<V>,
681                      Native<W>
682                      > jac(Backend::native(A),1,1.0);
683         jac.pre(z,r);
684         jac.apply(z,r);
685         jac.post(z);
686         res.converged  = true;
687         res.iterations = 1;
688         res.elapsed    = 0.0;
689         res.reduction  = reduction;
690         res.conv_rate  = reduction; // pow(reduction,1.0/1)
691       }
692     };
693 
694     //! \} Sequential Solvers
695 
696     /**
697      * @brief Class providing some statistics of the AMG solver.
698      *
699      */
700     struct ISTLAMGStatistics
701     {
702       /**
703        * @brief The needed for computing the parallel information and
704        * for adapting the linear system.
705        */
706       double tprepare;
707       /** @brief the number of levels in the AMG hierarchy. */
708       int levels;
709       /** @brief The time spent in solving the system (without building the hierarchy. */
710       double tsolve;
711       /** @brief The time needed for building the AMG hierarchy (coarsening). */
712       double tsetup;
713       /** @brief The number of iterations performed until convergence was reached. */
714       int iterations;
715       /** @brief True if a direct solver was used on the coarset level. */
716       bool directCoarseLevelSolver;
717     };
718 
719     template<class GO, template<class,class,class,int> class Preconditioner, template<class> class Solver,
720               bool skipBlocksizeCheck = false>
721     class ISTLBackend_SEQ_AMG : public LinearResultStorage
722     {
723       typedef typename GO::Traits::TrialGridFunctionSpace GFS;
724       typedef typename GO::Traits::Jacobian M;
725       typedef Backend::Native<M> MatrixType;
726       typedef typename GO::Traits::Domain V;
727       typedef Backend::Native<V> VectorType;
728       typedef Preconditioner<MatrixType,VectorType,VectorType,1> Smoother;
729       typedef Dune::MatrixAdapter<MatrixType,VectorType,VectorType> Operator;
730       typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs;
731       typedef Dune::Amg::AMG<Operator,VectorType,Smoother> AMG;
732       typedef Dune::Amg::Parameters Parameters;
733 
734     public:
ISTLBackend_SEQ_AMG(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)735       ISTLBackend_SEQ_AMG(unsigned maxiter_=5000, int verbose_=1,
736                           bool reuse_=false, bool usesuperlu_=true)
737         : maxiter(maxiter_), params(15,2000), verbose(verbose_),
738           reuse(reuse_), firstapply(true), usesuperlu(usesuperlu_)
739       {
740         params.setDefaultValuesIsotropic(GFS::Traits::GridViewType::Traits::Grid::dimension);
741         params.setDebugLevel(verbose_);
742 #if !HAVE_SUPERLU
743         if (usesuperlu == true)
744           {
745             std::cout << "WARNING: You are using AMG without SuperLU!"
746                       << " Please consider installing SuperLU,"
747                       << " or set the usesuperlu flag to false"
748                       << " to suppress this warning." << std::endl;
749           }
750 #endif
751       }
752 
753        /*! \brief set AMG parameters
754 
755         \param[in] params_ a parameter object of Type Dune::Amg::Parameters
756       */
setparams(Parameters params_)757       void setparams(Parameters params_)
758       {
759         params = params_;
760       }
761 
762       //! Set whether the AMG should be reused again during call to apply().
setReuse(bool reuse_)763       void setReuse(bool reuse_)
764       {
765         reuse = reuse_;
766       }
767 
768       //! Return whether the AMG is reused during call to apply()
getReuse() const769       bool getReuse() const
770       {
771         return reuse;
772       }
773 
774       /*! \brief compute global norm of a vector
775 
776         \param[in] v the given vector
777       */
norm(const V & v) const778       typename V::ElementType norm (const V& v) const
779       {
780         return Backend::native(v).two_norm();
781       }
782 
783       /*! \brief solve the given linear system
784 
785         \param[in] A the given matrix
786         \param[out] z the solution vector to be computed
787         \param[in] r right hand side
788         \param[in] reduction to be achieved
789       */
apply(M & A,V & z,V & r,typename Dune::template FieldTraits<typename V::ElementType>::real_type reduction)790       void apply(M& A, V& z, V& r, typename Dune::template FieldTraits<typename V::ElementType >::real_type reduction)
791       {
792         Timer watch;
793         MatrixType& mat = Backend::native(A);
794         typedef Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<MatrixType,
795           Dune::Amg::FirstDiagonal> > Criterion;
796         SmootherArgs smootherArgs;
797         smootherArgs.iterations = 1;
798         smootherArgs.relaxationFactor = 1;
799 
800         Criterion criterion(params);
801         //only construct a new AMG if the matrix changes
802         if (reuse==false || firstapply==true){
803           oop.reset(new Operator(mat));
804           amg.reset(new AMG(*oop, criterion, smootherArgs));
805           firstapply = false;
806           stats.tsetup = watch.elapsed();
807           stats.levels = amg->maxlevels();
808           stats.directCoarseLevelSolver=amg->usesDirectCoarseLevelSolver();
809         }
810         watch.reset();
811         Dune::InverseOperatorResult stat;
812 
813         Solver<VectorType> solver(*oop,*amg,reduction,maxiter,verbose);
814         solver.apply(Backend::native(z),Backend::native(r),stat);
815         stats.tsolve= watch.elapsed();
816         res.converged  = stat.converged;
817         res.iterations = stat.iterations;
818         res.elapsed    = stat.elapsed;
819         res.reduction  = stat.reduction;
820         res.conv_rate  = stat.conv_rate;
821       }
822 
823 
824       /**
825        * @brief Get statistics of the AMG solver (no of levels, timings).
826        * @return statistis of the AMG solver.
827        */
statistics() const828       const ISTLAMGStatistics& statistics() const
829       {
830         return stats;
831       }
832 
833     private:
834       unsigned maxiter;
835       Parameters params;
836       int verbose;
837       bool reuse;
838       bool firstapply;
839       bool usesuperlu;
840       std::shared_ptr<Operator> oop;
841       std::shared_ptr<AMG> amg;
842       ISTLAMGStatistics stats;
843     };
844 
845     //! \addtogroup PDELab_seqsolvers Sequential Solvers
846     //! \{
847 
848     /**
849      * @brief Sequential conjugate gradient solver preconditioned with AMG smoothed by SSOR
850      * @tparam GO The type of the grid operator
851      * (or the fakeGOTraits class for the old grid operator space).
852      */
853     template<class GO>
854     class ISTLBackend_SEQ_CG_AMG_SSOR
855       : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::CGSolver>
856     {
857 
858     public:
859       /**
860        * @brief Constructor
861        * @param maxiter_ The maximum number of iterations allowed.
862        * @param verbose_ The verbosity level to use.
863        * @param reuse_ Set true, if the Matrix to be used is always identical
864        * (AMG aggregation is then only performed once).
865        * @param usesuperlu_ Set false, to suppress the no SuperLU warning
866        */
ISTLBackend_SEQ_CG_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)867       ISTLBackend_SEQ_CG_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1,
868                                   bool reuse_=false, bool usesuperlu_=true)
869         : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::CGSolver>
870           (maxiter_, verbose_, reuse_, usesuperlu_)
871       {}
872     };
873 
874     /**
875      * @brief Sequential BiCGStab solver preconditioned with AMG smoothed by SSOR
876      * @tparam GO The type of the grid operator
877      * (or the fakeGOTraits class for the old grid operator space).
878      */
879     template<class GO>
880     class ISTLBackend_SEQ_BCGS_AMG_SSOR
881       : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::BiCGSTABSolver>
882     {
883 
884     public:
885       /**
886        * @brief Constructor
887        * @param maxiter_ The maximum number of iterations allowed.
888        * @param verbose_ The verbosity level to use.
889        * @param reuse_ Set true, if the Matrix to be used is always identical
890        * (AMG aggregation is then only performed once).
891        * @param usesuperlu_ Set false, to suppress the no SuperLU warning
892        */
ISTLBackend_SEQ_BCGS_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)893       ISTLBackend_SEQ_BCGS_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1,
894                                     bool reuse_=false, bool usesuperlu_=true)
895         : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::BiCGSTABSolver>
896           (maxiter_, verbose_, reuse_, usesuperlu_)
897       {}
898     };
899 
900     /**
901      * @brief Sequential BiCGSTAB solver preconditioned with AMG smoothed by SOR
902      * @tparam GO The type of the grid operator
903      * (or the fakeGOTraits class for the old grid operator space).
904      */
905     template<class GO>
906     class ISTLBackend_SEQ_BCGS_AMG_SOR
907       : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::BiCGSTABSolver>
908     {
909 
910     public:
911       /**
912        * @brief Constructor
913        * @param maxiter_ The maximum number of iterations allowed.
914        * @param verbose_ The verbosity level to use.
915        * @param reuse_ Set true, if the Matrix to be used is always identical
916        * (AMG aggregation is then only performed once).
917        * @param usesuperlu_ Set false, to suppress the no SuperLU warning
918        */
ISTLBackend_SEQ_BCGS_AMG_SOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)919       ISTLBackend_SEQ_BCGS_AMG_SOR(unsigned maxiter_=5000, int verbose_=1,
920                                    bool reuse_=false, bool usesuperlu_=true)
921         : ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::BiCGSTABSolver>
922           (maxiter_, verbose_, reuse_, usesuperlu_)
923       {}
924     };
925 
926     /**
927      * @brief Sequential Loop solver preconditioned with AMG smoothed by SSOR
928      * @tparam GO The type of the grid operator
929      * (or the fakeGOTraits class for the old grid operator space).
930      */
931     template<class GO>
932     class ISTLBackend_SEQ_LS_AMG_SSOR
933       : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::LoopSolver>
934     {
935 
936     public:
937       /**
938        * @brief Constructor
939        * @param maxiter_ The maximum number of iterations allowed.
940        * @param verbose_ The verbosity level to use.
941        * @param reuse_ Set true, if the Matrix to be used is always identical
942        * (AMG aggregation is then only performed once).
943        * @param usesuperlu_ Set false, to suppress the no SuperLU warning
944        */
ISTLBackend_SEQ_LS_AMG_SSOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)945       ISTLBackend_SEQ_LS_AMG_SSOR(unsigned maxiter_=5000, int verbose_=1,
946                                   bool reuse_=false, bool usesuperlu_=true)
947         : ISTLBackend_SEQ_AMG<GO, Dune::SeqSSOR, Dune::LoopSolver>
948           (maxiter_, verbose_, reuse_, usesuperlu_)
949       {}
950     };
951 
952     /**
953      * @brief Sequential Loop solver preconditioned with AMG smoothed by SOR
954      * @tparam GO The type of the grid operator
955      * (or the fakeGOTraits class for the old grid operator space).
956      */
957     template<class GO>
958     class ISTLBackend_SEQ_LS_AMG_SOR
959       : public ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::LoopSolver>
960     {
961 
962     public:
963       /**
964        * @brief Constructor
965        * @param maxiter_ The maximum number of iterations allowed.
966        * @param verbose_ The verbosity level to use.
967        * @param reuse_ Set true, if the Matrix to be used is always identical
968        * (AMG aggregation is then only performed once).
969        * @param usesuperlu_ Set false, to suppress the no SuperLU warning
970        */
ISTLBackend_SEQ_LS_AMG_SOR(unsigned maxiter_=5000,int verbose_=1,bool reuse_=false,bool usesuperlu_=true)971       ISTLBackend_SEQ_LS_AMG_SOR(unsigned maxiter_=5000, int verbose_=1,
972                                  bool reuse_=false, bool usesuperlu_=true)
973         : ISTLBackend_SEQ_AMG<GO, Dune::SeqSOR, Dune::LoopSolver>
974           (maxiter_, verbose_, reuse_, usesuperlu_)
975       {}
976     };
977 
978     /** \brief Linear solver backend for Restarted GMRes
979         preconditioned with ILU(0)
980 
981     */
982 
983     class ISTLBackend_SEQ_GMRES_ILU0
984       : public SequentialNorm, public LinearResultStorage
985     {
986     public :
987 
988       /** \brief make linear solver object
989 
990           \param[in] restart_ number of iterations when GMRes has to be restarted
991           \param[in] maxiter_ maximum number of iterations to do
992           \param[in] verbose_ print messages if true
993       */
ISTLBackend_SEQ_GMRES_ILU0(int restart_=200,int maxiter_=5000,int verbose_=1)994       explicit ISTLBackend_SEQ_GMRES_ILU0(int restart_ = 200, int maxiter_ = 5000, int verbose_ = 1)
995         : restart(restart_), maxiter(maxiter_), verbose(verbose_)
996       {}
997 
998       /** \brief solve the given linear system
999 
1000           \param[in] A the given matrix
1001           \param[out] z the solution vector to be computed
1002           \param[in] r right hand side
1003           \param[in] reduction to be achieved
1004       */
1005       template<class M, class V, class W>
apply(M & A,V & z,W & r,typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)1006       void apply(M& A, V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType>::real_type reduction)
1007       {
1008         using Backend::Native;
1009         using Backend::native;
1010         Dune::MatrixAdapter<
1011           Native<M>,
1012           Native<V>,
1013           Native<W>
1014           > opa(native(A));
1015         Dune::SeqILU<
1016           Native<M>,
1017           Native<V>,
1018           Native<W>
1019           > ilu0(native(A), 1.0);
1020         Dune::RestartedGMResSolver<Native<V>> solver(opa,ilu0,reduction,restart,maxiter,verbose);
1021         Dune::InverseOperatorResult stat;
1022         solver.apply(native(z), native(r), stat);
1023         res.converged  = stat.converged;
1024         res.iterations = stat.iterations;
1025         res.elapsed    = stat.elapsed;
1026         res.reduction  = stat.reduction;
1027         res.conv_rate  = stat.conv_rate;
1028       }
1029 
1030     private :
1031       int restart, maxiter, verbose;
1032     };
1033 
1034     //============================
1035     // Matrix free solver backends
1036     //============================
1037 
1038     template <class GO>
1039     class ISTLBackend_SEQ_MatrixFree_BCGS_Richardson
1040       : public ISTLBackend_SEQ_MatrixFree_Richardson<GO, Dune::BiCGSTABSolver>
1041     {
1042     public:
1043       /*! \brief make a linear solver object
1044         \param[in] op_ Operator that will be passed to ISTL solver
1045         \param[in] maxiter_ maximum number of iterations to do
1046         \param[in] verbose_ print messages if true
1047       */
ISTLBackend_SEQ_MatrixFree_BCGS_Richardson(const GO & go_,unsigned maxiter_=5000,int verbose_=1)1048       explicit ISTLBackend_SEQ_MatrixFree_BCGS_Richardson (const GO& go_, unsigned maxiter_=5000, int verbose_=1)
1049         : ISTLBackend_SEQ_MatrixFree_Richardson<GO, Dune::BiCGSTABSolver>(go_, maxiter_, verbose_)
1050       {}
1051     };
1052 
1053 
1054     //! \} group Sequential Solvers
1055     //! \} group Backend
1056 
1057   } // namespace PDELab
1058 } // namespace Dune
1059 
1060 #endif // DUNE_PDELAB_BACKEND_ISTL_SEQISTLSOLVERBACKEND_HH
1061