dune-fem  2.4.1-rc
istlinverseoperators.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
2 #define DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
3 
4 #include <dune/common/nullptr.hh>
5 
10 
11 #if HAVE_DUNE_ISTL
13 
14 #include <dune/istl/scalarproducts.hh>
15 #include <dune/istl/solvers.hh>
16 #include <dune/istl/preconditioner.hh>
17 
18 namespace Dune
19 {
20 
21  namespace Fem
22  {
23 
24  // wrapper for Fem Preconditioners (Operators acting as preconditioners) into ISTL preconditioners
25  template< class Preconditioner >
26  class ISTLPreconditionAdapter
27  :public Dune::Preconditioner< typename Preconditioner::RangeFunctionType::DofStorageType, typename Preconditioner::DomainFunctionType::DofStorageType >
28  {
29  typedef ISTLPreconditionAdapter< Preconditioner > ThisType;
30  typedef Dune::Preconditioner< typename Preconditioner::RangeFunctionType::DofStorageType, typename Preconditioner::DomainFunctionType::DofStorageType > BaseType;
31 
32  typedef typename Preconditioner::DomainFunctionType DomainFunctionType;
33  typedef typename Preconditioner::RangeFunctionType RangeFunctionType;
34 
35  public:
36  enum {category=SolverCategory::sequential};
37 
38  typedef typename BaseType::domain_type domain_type;
39  typedef typename BaseType::range_type range_type;
40  typedef typename BaseType::field_type field_type;
41 
42  typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainFunctionSpaceType;
43  typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeFunctionSpaceType;
44 
45  ISTLPreconditionAdapter ( const Preconditioner *precon, const DomainFunctionSpaceType &domainSpace, const RangeFunctionSpaceType &rangeSpace )
46  : precon_( precon ),
47  domainSpace_( domainSpace ),
48  rangeSpace_( rangeSpace )
49  {}
50 
51  // pre and post do nothing here
52  virtual void pre ( domain_type &x, range_type &y ) {}
53  virtual void post ( domain_type &x ) {}
54 
55  virtual void apply ( domain_type &x, const range_type &y )
56  {
57  // no precon
58  if( !precon_ )
59  {
60  x = y;
61  }
62  else
63  {
64  // note: ISTL switches the arguments !!!
65  // it is assumed that we have a left preconditioner
66  RangeFunctionType px( "ISTLPreconditionAdapter::apply::x", rangeSpace_, x );
67  DomainFunctionType py( "ISTLPreconditionAdapter::apply::y", domainSpace_, y );
68 
69  (*precon_)( px, py );
70  }
71  }
72 
73  protected:
74  const Preconditioner *precon_;
75  const DomainFunctionSpaceType &domainSpace_;
76  const RangeFunctionSpaceType &rangeSpace_;
77  };
78 
79 
80  template< class BlockVector >
81  struct ISTLSolverReduction
82  {
83  ISTLSolverReduction ( double redEps, double absLimit )
84  : redEps_( redEps ),
85  absLimit_( absLimit )
86  {}
87 
88  double operator() ( const Dune::LinearOperator< BlockVector, BlockVector > &op,
89  Dune::ScalarProduct< BlockVector > &scp,
90  const BlockVector &rhs, const BlockVector &x ) const
91  {
92  if( absLimit_ < std::numeric_limits< double >::max() )
93  {
94  BlockVector residuum( rhs );
95  op.applyscaleadd( -1., x, residuum );
96  const double res = scp.norm( residuum );
97  return (res > 0 ? absLimit_ / res : 1e-3);
98  }
99  else
100  return redEps_;
101  }
102 
103  private:
104  double redEps_;
105  double absLimit_;
106  };
107 
108 
109 
110  template< class Solver, class Reduction = ISTLSolverReduction< typename Solver::range_type > >
111  struct ISTLSolverAdapter
112  {
113  typedef Solver SolverType;
114  typedef Reduction ReductionType;
115 
116  typedef typename SolverType::domain_type domain_type;
117  typedef typename SolverType::range_type range_type;
118 
119  ISTLSolverAdapter ( const ReductionType &reduction, unsigned int maxIterations, int verbose,
120  const ParameterReader &parameter = Parameter::container() )
121  : reduction_( reduction ),
122  maxIterations_( maxIterations ),
123  verbose_( verbose )
124  {}
125 
126  template<class Op, class ScP, class PC >
127  void operator () ( Op& op, ScP &scp, PC &pc,
128  range_type &rhs, domain_type &x,
129  Dune::InverseOperatorResult &result ) const
130  {
131  int maxIterations = std::min( (unsigned int)std::numeric_limits< int >::max(), maxIterations_ );
132  SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbose_ );
133  solver.apply( x, rhs, result );
134  }
135 
136  private:
137  ReductionType reduction_;
138  unsigned int maxIterations_;
139  int verbose_;
140  };
141 
142 
143  template< class X, class Y, class F, class Reduction >
144  struct ISTLSolverAdapter< Dune::RestartedGMResSolver< X, Y, F>, Reduction >
145  {
146  typedef Dune::RestartedGMResSolver< X, Y, F> SolverType;
147  typedef Reduction ReductionType;
148 
149  typedef typename SolverType::domain_type domain_type;
150  typedef typename SolverType::range_type range_type;
151 
152  ISTLSolverAdapter ( const ReductionType &reduction, unsigned int restart, unsigned int maxIterations, int verbose,
153  const ParameterReader &parameter = Parameter::container() )
154  : reduction_( reduction ),
155  restart_( restart ),
156  maxIterations_( maxIterations ),
157  verbose_( verbose )
158  {}
159 
160  ISTLSolverAdapter ( const Reduction &reduction, unsigned int maxIterations, int verbose,
161  const ParameterReader &parameter = Parameter::container() )
162  : reduction_( reduction ),
163  restart_( parameter.getValue< int >( "fem.solver.gmres.restart", 20 ) ),
164  maxIterations_( maxIterations ),
165  verbose_( verbose )
166  {}
167 
168  template<class Op, class ScP, class PC >
169  void operator () ( Op& op, ScP &scp, PC &pc,
170  range_type &rhs, domain_type &x,
171  Dune::InverseOperatorResult &result ) const
172  {
173  int maxIterations = std::min( (unsigned int)std::numeric_limits< int >::max(), maxIterations_ );
174  SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), restart_, maxIterations, verbose_ );
175  solver.apply( x, rhs, result );
176  }
177 
178  private:
179  ReductionType reduction_;
180  unsigned int restart_;
181  unsigned int maxIterations_;
182  int verbose_;
183  };
184 
185 
186  template< class X >
187  struct ISTLLoopSolver { typedef LoopSolver< X > Type; };
188 
189  template< class X >
190  struct ISTLGradientSolver { typedef GradientSolver< X > Type; };
191 
192  template< class X >
193  struct ISTLCGSolver { typedef CGSolver< X > Type; };
194 
195  template< class X >
196  struct ISTLBiCGSTABSolver { typedef BiCGSTABSolver< X > Type; };
197 
198  template< class X >
199  struct ISTLMINRESSolver { typedef MINRESSolver< X > Type; };
200 
201  template< class X >
202  struct ISTLRestartedGMRes { typedef RestartedGMResSolver< X > Type; };
203 
204 
205  // ISTLInverseOperator
206  // -------------------
207 
208  template< class DiscreteFunction, template< class > class Solver,
209  class Preconditioner = const Operator< DiscreteFunction, DiscreteFunction > >
210  class ISTLInverseOperator
211  : public Operator< DiscreteFunction, DiscreteFunction >
212  {
214 
215  public:
216  typedef typename BaseType::DomainFunctionType DomainFunctionType;
217  typedef typename BaseType::RangeFunctionType RangeFunctionType;
218 
220  typedef Preconditioner PreconditionerType;
221 
222  protected:
223  typedef ISTLLinearOperatorAdapter< OperatorType > ISTLOperatorType;
224  typedef ISTLPreconditionAdapter< OperatorType > ISTLPreconditionerAdapterType;
225 
226  typedef Fem::ParallelScalarProduct< RangeFunctionType > ParallelScalarProductType;
227  typedef typename DomainFunctionType::DofStorageType BlockVectorType;
228 
229  typedef ISTLSolverAdapter< typename Solver< BlockVectorType >::Type > SolverAdapterType;
230  typedef typename SolverAdapterType::ReductionType ReductionType;
231  public:
232 
233  typedef typename SolverAdapterType::SolverType SolverType;
234 
235  ISTLInverseOperator ( const OperatorType &op,
236  double redEps, double absLimit, unsigned int maxIterations, bool verbose,
237  const ParameterReader &parameter = Parameter::container() )
238  : ISTLInverseOperator( op, nullptr, redEps, absLimit, maxIterations, verbose, parameter ) {}
239 
240  ISTLInverseOperator ( const OperatorType &op,
241  double redEps, double absLimit,
242  const ParameterReader &parameter = Parameter::container() )
243  : ISTLInverseOperator( op, nullptr, redEps, absLimit, std::numeric_limits< unsigned int >::max(), false, parameter ) {}
244 
245  ISTLInverseOperator ( const OperatorType &op,
246  double redEps, double absLimit, unsigned int maxIterations,
247  const ParameterReader &parameter = Parameter::container() )
248  : ISTLInverseOperator( op, nullptr, redEps, absLimit, maxIterations, false, parameter ) {}
249 
250 
251  ISTLInverseOperator ( const OperatorType &op, PreconditionerType &preconditioner,
252  double redEps, double absLimit, unsigned int maxIterations, bool verbose,
253  const ParameterReader &parameter = Parameter::container() )
254  : ISTLInverseOperator( op, &preconditioner, redEps, absLimit, maxIterations, verbose, parameter ) {}
255 
256  ISTLInverseOperator ( const OperatorType &op, PreconditionerType &preconditioner,
257  double redEps, double absLimit,
258  const ParameterReader &parameter = Parameter::container() )
259  : ISTLInverseOperator( op, &preconditioner, redEps, absLimit, std::numeric_limits< unsigned int >::max(), false, parameter ) {}
260 
261  ISTLInverseOperator ( const OperatorType &op, PreconditionerType &preconditioner,
262  double redEps, double absLimit, unsigned int maxIterations,
263  const ParameterReader &parameter = Parameter::container() )
264  : ISTLInverseOperator( op, &preconditioner, redEps, absLimit, maxIterations, false, parameter ) {}
265 
266 
267  virtual void operator() ( const DomainFunctionType &u, RangeFunctionType &w ) const
268  {
269  ISTLOperatorType istlOperator( operator_, w.space(), u.space() );
270  ParallelScalarProductType scp( u.space() );
271 
272  if( !preconditioner_ )
273  {
274  ISTLPreconditionerAdapterType istlPreconditioner( nullptr, w.space(), u.space() );
275  solve( istlOperator, scp, istlPreconditioner, u, w );
276  }
277  else
278  solve( istlOperator, scp, *preconditioner_, u, w );
279  }
280 
281  unsigned int iterations () const { return result_.iterations; }
282 
283  private:
284  ISTLInverseOperator ( const OperatorType &op, PreconditionerType *preconditioner,
285  double redEps, double absLimit, unsigned int maxIterations, bool verbose,
286  const ParameterReader &parameter )
287  : operator_( op ),
288  preconditioner_( preconditioner ),
289  solverAdapter_( ReductionType( redEps, absLimit ), maxIterations, (Parameter::verbose() && verbose) ? 2 : 0, parameter )
290  {}
291 
292  void solve ( ISTLOperatorType &istlOperator, ParallelScalarProductType &scp,
293  const OperatorType &preconditioner,
294  const DomainFunctionType &u, RangeFunctionType &w ) const
295  {
296  ISTLPreconditionerAdapterType istlPreconditioner( &preconditioner, w.space(), u.space() );
297  solve( istlOperator, scp, istlPreconditioner, u, w );
298  }
299 
300  template< class ISTLPreconditioner >
301  void solve ( ISTLOperatorType &istlOperator, ParallelScalarProductType &scp,
302  ISTLPreconditioner &preconditioner,
303  const DomainFunctionType &u, RangeFunctionType &w ) const
304  {
305  BlockVectorType rhs( u.blockVector() );
306  solverAdapter_( istlOperator, scp, preconditioner, rhs, w.blockVector(), result_ );
307  }
308 
309  const OperatorType &operator_;
310  PreconditionerType *preconditioner_;
311  SolverAdapterType solverAdapter_;
312  mutable Dune::InverseOperatorResult result_;
313  };
314 
315  } // namespace Fem
316 
317 } // namespace Dune
318 
319 #endif // #if HAVE_ISTL
320 
321 #endif // #ifndef DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
static constexpr T min(T a)
Definition: utility.hh:81
BasicParameterReader< std::function< const std::string *(const std::string &, const std::string *) > > ParameterReader
Definition: reader.hh:264
static constexpr T max(T a)
Definition: utility.hh:65
static double max(const Double &v, const double p)
Definition: double.hh:387
Definition: coordinate.hh:4
static ParameterContainer & container()
Definition: io/parameter.hh:190
STL namespace.