DUNE-FEM (unstable)

istlinverseoperators.hh
1#ifndef DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
2#define DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
3
4#include <dune/fem/function/blockvectorfunction.hh>
5#include <dune/fem/function/common/scalarproducts.hh>
6#include <dune/fem/operator/common/operator.hh>
7#include <dune/fem/io/parameter.hh>
8#include <dune/fem/misc/mpimanager.hh>
9
10#include <dune/fem/solver/parameter.hh>
11#include <dune/fem/solver/inverseoperatorinterface.hh>
12
13#if HAVE_DUNE_ISTL
15
16#include <dune/fem/operator/linear/istladapter.hh>
17#include <dune/fem/operator/linear/istloperator.hh>
18
20#include <dune/istl/solvers.hh>
21#include <dune/istl/preconditioner.hh>
22
23namespace Dune
24{
25
26 namespace Fem
27 {
28
29 // wrapper for Fem Preconditioners (Operators acting as preconditioners) into ISTL preconditioners
30 template< class Preconditioner >
31 class ISTLPreconditionAdapter
32 : public Dune::Preconditioner< typename Preconditioner::RangeFunctionType::DofStorageType, typename Preconditioner::DomainFunctionType::DofStorageType >
33 {
34 typedef ISTLPreconditionAdapter< Preconditioner > ThisType;
36
37 typedef typename Preconditioner::DomainFunctionType DomainFunctionType;
38 typedef typename Preconditioner::RangeFunctionType RangeFunctionType;
39
40 public:
41 typedef typename BaseType::domain_type domain_type;
42 typedef typename BaseType::range_type range_type;
43 typedef typename BaseType::field_type field_type;
44
45 typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainFunctionSpaceType;
46 typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeFunctionSpaceType;
47
48 ISTLPreconditionAdapter ( const Preconditioner *precon, const DomainFunctionSpaceType &domainSpace, const RangeFunctionSpaceType &rangeSpace )
49 : precon_( precon ),
50 domainSpace_( domainSpace ),
51 rangeSpace_( rangeSpace )
52 {}
53
54 // pre and post do nothing here
55 virtual void pre ( domain_type &x, range_type &y ) override {}
56 virtual void post ( domain_type &x ) override {}
57
58 virtual void apply ( domain_type &x, const range_type &y ) override
59 {
60 // no precon
61 if( !precon_ )
62 {
63 x = y;
64 }
65 else
66 {
67 // note: ISTL switches the arguments !!!
68 // it is assumed that we have a left preconditioner
69 RangeFunctionType px( "ISTLPreconditionAdapter::apply::x", rangeSpace_, x );
70 DomainFunctionType py( "ISTLPreconditionAdapter::apply::y", domainSpace_, y );
71
72 (*precon_)( px, py );
73 }
74 }
75
76 SolverCategory::Category category () const override { return SolverCategory::sequential; }
77
78 protected:
79 const Preconditioner *precon_;
80 const DomainFunctionSpaceType &domainSpace_;
81 const RangeFunctionSpaceType &rangeSpace_;
82 };
83
84
85 template< class BlockVector >
86 struct ISTLSolverReduction
87 {
88 ISTLSolverReduction ( std::shared_ptr< ISTLSolverParameter > parameter )
89 : parameter_( parameter )
90 {}
91
92 double operator() ( const Dune::LinearOperator< BlockVector, BlockVector > &op,
94 const BlockVector &rhs, const BlockVector &x ) const
95 {
96
97 if( parameter_->errorMeasure() == 0)
98 {
99 BlockVector residuum( rhs );
100 op.applyscaleadd( -1., x, residuum );
101 const double res = scp.norm( residuum );
102 return (res > 0 ? parameter_->tolerance() / res : 1e-3);
103 }
104 else
105 return parameter_->tolerance();
106 }
107
108 private:
109 std::shared_ptr<ISTLSolverParameter> parameter_;
110 };
111
112
113 struct ISTLInverseOperatorMethods
114 {
115 static std::vector< int > supportedSolverMethods() {
116 return std::vector< int > ({
117 SolverParameter::gmres, // default solver
118 SolverParameter::cg,
119 SolverParameter::bicgstab,
120 SolverParameter::minres,
121 SolverParameter::gradient,
122 SolverParameter::loop,
123 SolverParameter::superlu
124 });
125 }
126 };
127
128 template< int method,
129 class X,
130 class Reduction = ISTLSolverReduction< X > >
131 struct ISTLSolverAdapter
132 {
133 typedef Reduction ReductionType;
134
135 typedef X domain_type;
136 typedef X range_type;
137
138 ISTLSolverAdapter ( const ReductionType &reduction, std::shared_ptr<ISTLSolverParameter> parameter )
139 : reduction_( reduction ),
140 method_( method < 0 ? parameter->solverMethod( ISTLInverseOperatorMethods::supportedSolverMethods() ) : method ),
141 parameter_( parameter )
142 {}
143
144 template<class Op, class ScP, class PC >
145 void operator () ( Op& op, ScP &scp, PC &pc,
146 range_type &rhs, domain_type &x,
147 Dune::InverseOperatorResult &result ) const
148 {
149 int verbosity = (Parameter::verbose( Parameter::solverStatistics ) && parameter_->verbose()) ? 2 : 0;
150 if ( verbosity && Parameter::verbose( Parameter::extendedStatistics ) )
151 verbosity += 2;
152
153 int maxIterations = std::min( std::numeric_limits< int >::max(), parameter_->maxIterations() );
154 if( method_ == SolverParameter::cg )
155 {
156 typedef Dune::CGSolver< X > SolverType;
157 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbosity );
158 solver.apply( x, rhs, result );
159 return ;
160 }
161 else if( method_ == SolverParameter::bicgstab )
162 {
163 typedef Dune::BiCGSTABSolver< X > SolverType;
164 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbosity );
165 solver.apply( x, rhs, result );
166 return ;
167 }
168 else if( method_ == SolverParameter::gmres )
169 {
170 typedef Dune::RestartedGMResSolver< X > SolverType;
171 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), parameter_->gmresRestart(), maxIterations, verbosity );
172 solver.apply( x, rhs, result );
173 return ;
174 }
175 else if( method_ == SolverParameter::minres )
176 {
177 typedef Dune::MINRESSolver< X > SolverType;
178 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbosity );
179 solver.apply( x, rhs, result );
180 }
181 else if( method_ == SolverParameter::gradient )
182 {
183 typedef Dune::GradientSolver< X > SolverType;
184 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbosity );
185 solver.apply( x, rhs, result );
186 return ;
187 }
188 else if( method_ == SolverParameter::loop )
189 {
190 typedef Dune::LoopSolver< X > SolverType;
191 SolverType solver( op, scp, pc, reduction_( op, scp, rhs, x ), maxIterations, verbosity );
192 solver.apply( x, rhs, result );
193 return ;
194 }
195 else if( method_ == SolverParameter::superlu )
196 {
197 callSuperLU( op, rhs, x, result );
198 }
199 else
200 {
201 DUNE_THROW(NotImplemented,"ISTLSolverAdapter::operator(): wrong method solver identifier" << method_ );
202 }
203 }
204
205 void setMaxLinearIterations( unsigned int maxIterations ) { parameter_->setMaxIterations(maxIterations); }
206 void setMaxIterations( unsigned int maxIterations ) { parameter_->setMaxIterations(maxIterations); }
207
208 std::shared_ptr<ISTLSolverParameter> parameter () const { return parameter_; }
209
210 protected:
211 template< class ImprovedMatrix >
212 void callSuperLU ( ISTLParallelMatrixAdapterInterface< ImprovedMatrix >& op,
213 range_type &rhs, domain_type &x,
214 Dune::InverseOperatorResult &result ) const
215 {
216#if HAVE_SUPERLU
217 const int verbosity = (Dune::Fem::Parameter::verbose( Parameter::solverStatistics ) && parameter_->verbose()) ? 2 : 0;
218 typedef typename ImprovedMatrix :: BaseType Matrix;
219 const ImprovedMatrix& matrix = op.getmat();
220 SuperLU< Matrix > solver( matrix, verbosity );
221 solver.apply( x, rhs, result );
222#else
223 DUNE_THROW(NotImplemented,"ISTLSolverAdapter::callSuperLU: SuperLU solver selected but SuperLU not available!");
224#endif
225 }
226
227 template< class Op >
228 void callSuperLU ( Op& op, range_type &rhs, domain_type &x,
229 Dune::InverseOperatorResult &result ) const
230 {
231 DUNE_THROW(NotImplemented,"ISTLSolverAdapter::callSuperLU: SuperLU only works for AssembledLinearOperators!");
232 }
233
234 ReductionType reduction_;
235 const int method_;
236
237 std::shared_ptr<ISTLSolverParameter> parameter_;
238 };
239
240
241
242 // ISTLInverseOperator
243 // -------------------
244
245 template< class DiscreteFunction, int method = -1,
246 class Preconditioner = Fem::Operator< DiscreteFunction, DiscreteFunction > >
247 class ISTLInverseOperator;
248
249 template< class DiscreteFunction, int method, class Preconditioner >
250 struct ISTLInverseOperatorTraits
251 {
252 typedef DiscreteFunction DiscreteFunctionType;
254 typedef Preconditioner PreconditionerType;
255
256 typedef ISTLBlockVectorDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType ;
257 typedef Dune::Fem::ISTLLinearOperator< DiscreteFunction, DiscreteFunction > AssembledOperatorType;
258
259 typedef ISTLInverseOperator< DiscreteFunction, method, Preconditioner > InverseOperatorType;
260 typedef ISTLSolverParameter SolverParameterType;
261 };
262
263 template< class DiscreteFunction, int method, class Preconditioner >
264 class ISTLInverseOperator : public InverseOperatorInterface<
265 ISTLInverseOperatorTraits< DiscreteFunction,
266 method, Preconditioner > >
267 {
268 typedef ISTLInverseOperatorTraits< DiscreteFunction, method, Preconditioner > Traits;
269 typedef InverseOperatorInterface< Traits > BaseType;
270
271 friend class InverseOperatorInterface< Traits >;
272 public:
273 typedef typename BaseType::DomainFunctionType DomainFunctionType;
274 typedef typename BaseType::RangeFunctionType RangeFunctionType;
275 typedef typename BaseType::OperatorType OperatorType;
276 typedef typename BaseType::PreconditionerType PreconditionerType;
277 typedef typename BaseType::AssembledOperatorType AssembledOperatorType;
278
279 using BaseType :: bind;
280 using BaseType :: unbind;
281 using BaseType :: setMaxIterations;
282 using BaseType :: setMaxLinearIterations;
283
284 protected:
285 typedef typename Traits::SolverDiscreteFunctionType SolverDiscreteFunctionType;
286
287 typedef typename DomainFunctionType :: DiscreteFunctionSpaceType
288 DiscreteFunctionSpaceType;
289
290
291 typedef typename SolverDiscreteFunctionType::ScalarProductType ParallelScalarProductType;
292 typedef typename SolverDiscreteFunctionType::DofStorageType BlockVectorType;
293
294 typedef ISTLSolverAdapter< method, BlockVectorType > SolverAdapterType;
295 typedef typename SolverAdapterType::ReductionType ReductionType;
296 public:
297
298 //non-deprecated constructors
299 ISTLInverseOperator ( const ISTLSolverParameter & parameter = ISTLSolverParameter() )
300 : BaseType( parameter ), solverAdapter_( ReductionType( parameter_ ), parameter_ )
301 {}
302
303 ISTLInverseOperator ( const OperatorType &op,
304 const ISTLSolverParameter & parameter = ISTLSolverParameter() )
305 : ISTLInverseOperator ( parameter )
306 {
307 bind( op );
308 }
309
310 ISTLInverseOperator ( const OperatorType &op, PreconditionerType &preconditioner,
311 const ISTLSolverParameter & parameter = ISTLSolverParameter() )
312 : ISTLInverseOperator( parameter )
313 {
314 bind( op, preconditioner );
315 }
316
317 protected:
318 // apply for arbitrary domain function type and matching range function type
319 template <class DomainFunction>
320 int apply( const DomainFunction& u, SolverDiscreteFunctionType& w ) const
321 {
322 auto& scp = w.scalarProduct();
323 // u may not be a discrete function, therefore use w.space()
324 const DiscreteFunctionSpaceType& space = w.space();
325
327 std::shared_ptr< ISTLPreconditionerType > istlPre;
328 if constexpr (std::is_same< SolverDiscreteFunctionType, RangeFunctionType >::value )
329 {
330 typedef ISTLPreconditionAdapter< PreconditionerType > ISTLPreconditionerAdapterType;
331 istlPre.reset( new ISTLPreconditionerAdapterType( preconditioner_, space, space ) );
332 }
333
334 if( assembledOperator_ )
335 {
336 auto& matrix = assembledOperator_->matrixAdapter( *(solverAdapter_.parameter()) );
337 // if preconditioner_ was set use that one, otherwise the one from the matrix object
338 ISTLPreconditionerType& matrixPre = matrix.preconditionAdapter();
339 ISTLPreconditionerType& precon = ( preconditioner_ ) ? (*istlPre) : matrixPre;
340 return solve( matrix, scp, precon, u, w );
341 }
342
343 if constexpr (std::is_same< SolverDiscreteFunctionType, RangeFunctionType >::value )
344 {
345 assert( operator_ );
346 assert( istlPre );
347 typedef ISTLLinearOperatorAdapter< OperatorType > ISTLOperatorType;
348 ISTLOperatorType istlOperator( *operator_, space, space );
349 return solve( istlOperator, scp, *istlPre, u, w );
350 }
351
352 DUNE_THROW(InvalidStateException,"ISTLInverseOperator::apply: No valid operator found!");
353 return -1;
354 }
355
357 template< class OperatorAdapter, class ISTLPreconditioner, class DomainFunction >
358 int solve ( OperatorAdapter &istlOperator, ParallelScalarProductType &scp,
359 ISTLPreconditioner &preconditioner,
360 const DomainFunction& u,
361 SolverDiscreteFunctionType& w ) const
362 {
363 if( ! rhs_ )
364 {
365 // u may not be a discrete function, therefore use w.space()
366 rhs_.reset( new SolverDiscreteFunctionType( "ISTLInvOp::rhs", w.space() ) );
367 rightHandSideCopied_ = false;
368 }
369
370 if( ! rightHandSideCopied_ )
371 {
372 // copy right hand side since ISTL solvers seem to modify it
373 rhs_->assign( u );
374 rightHandSideCopied_ = true;
375 }
376
378 solverAdapter_.setMaxIterations( parameter_->maxIterations() );
379 solverAdapter_( istlOperator, scp, preconditioner, rhs_->blockVector(), w.blockVector(), result );
380 return (result.converged) ? result.iterations : -(result.iterations);
381 }
382
383 using BaseType :: operator_;
384 using BaseType :: assembledOperator_;
385 using BaseType :: preconditioner_;
386
387 using BaseType :: rhs_;
388 using BaseType :: x_;
389
390 using BaseType :: rightHandSideCopied_;
391 using BaseType :: parameter_;
392
393 mutable SolverAdapterType solverAdapter_;
394 };
395
396 } // namespace Fem
397
398} // namespace Dune
399
400#endif // #if HAVE_ISTL
401
402#endif // #ifndef DUNE_FEM_SOLVER_ISTLINVERSEOPERATORS_HH
Bi-conjugate Gradient Stabilized (BiCG-STAB)
Definition: solvers.hh:419
conjugate gradient method
Definition: solvers.hh:193
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
static bool verbose()
obtain the cached value for fem.verbose with default verbosity level 2
Definition: parameter.hh:466
forward declaration
Definition: discretefunction.hh:51
gradient method
Definition: solvers.hh:124
A linear operator.
Definition: operators.hh:68
virtual void applyscaleadd(field_type alpha, const X &x, Y &y) const =0
apply operator to x, scale and add:
Preconditioned loop solver.
Definition: solvers.hh:59
Minimal Residual Method (MINRES)
Definition: solvers.hh:609
Base class for matrix free definition of preconditioners.
Definition: preconditioner.hh:33
implements the Generalized Minimal Residual (GMRes) method
Definition: solvers.hh:827
Base class for scalar product and norm computation.
Definition: scalarproducts.hh:52
virtual real_type norm(const X &x) const
Norm of a right-hand side vector. The vector must be consistent on the interior+border partition.
Definition: scalarproducts.hh:71
Various macros to work with Dune module version numbers.
Define base class for scalar product and norm.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Dune namespace.
Definition: alignedallocator.hh:13
Implementations of the inverse operator interface.
Statistics about the application of an inverse operator.
Definition: solver.hh:50
int iterations
Number of iterations.
Definition: solver.hh:69
bool converged
True if convergence criterion has been met.
Definition: solver.hh:75
Category
Definition: solvercategory.hh:23
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:25
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)