DUNE-FEM (unstable)

krylovinverseoperators.hh
1#ifndef DUNE_FEM_SOLVER_INVERSEOPERATORS_HH
2#define DUNE_FEM_SOLVER_INVERSEOPERATORS_HH
3
4#include <dune/fem/function/adaptivefunction.hh>
5#include <dune/fem/operator/common/operator.hh>
6#include <dune/fem/io/parameter.hh>
7#include <dune/fem/solver/parameter.hh>
8
9#include <dune/fem/solver/cginverseoperator.hh>
10#include <dune/fem/solver/fempreconditioning.hh>
11
12#include <dune/fem/solver/linear/gmres.hh>
13#include <dune/fem/solver/linear/bicgstab.hh>
14#include <dune/fem/solver/linear/cg.hh>
15#include <dune/fem/solver/inverseoperatorinterface.hh>
16
17#include <dune/fem/misc/mpimanager.hh>
18
19namespace Dune
20{
21
22 namespace Fem
23 {
24
25 // KrylovInverseOperator
26 // ---------------------
27
28 template< class DiscreteFunction, int method = -1 >
29 class KrylovInverseOperator;
30
31 template< class DiscreteFunction, int method >
32 struct KrylovInverseOperatorTraits
33 {
34 typedef DiscreteFunction DiscreteFunctionType;
36 typedef OperatorType PreconditionerType;
37
38 typedef OperatorType AssembledOperatorType;
39 typedef DiscreteFunction SolverDiscreteFunctionType ;
40
41 typedef KrylovInverseOperator< DiscreteFunction, method > InverseOperatorType;
42 typedef SolverParameter SolverParameterType;
43 };
44
45
46 template< class DiscreteFunction, int method >
47 class KrylovInverseOperator
48 : public InverseOperatorInterface< KrylovInverseOperatorTraits< DiscreteFunction, method > >
49 {
50 typedef KrylovInverseOperatorTraits< DiscreteFunction, method > Traits;
51 typedef InverseOperatorInterface< Traits > BaseType;
52
53 friend class InverseOperatorInterface< Traits >;
54 public:
55 typedef typename BaseType::DomainFunctionType DomainFunctionType;
56 typedef typename BaseType::RangeFunctionType RangeFunctionType;
57 typedef typename BaseType::OperatorType OperatorType;
58 typedef typename BaseType::PreconditionerType PreconditionerType;
59 typedef typename BaseType::AssembledOperatorType AssembledOperatorType;
60
61 using BaseType :: bind;
62 using BaseType :: unbind;
63 using BaseType :: setMaxLinearIterations;
64 using BaseType :: setMaxIterations;
65
66 public:
67 KrylovInverseOperator ( const OperatorType &op, const SolverParameter &parameter = SolverParameter(Parameter::container()) )
68 : KrylovInverseOperator( parameter )
69 {
70 bind( op );
71 }
72
73 KrylovInverseOperator ( const OperatorType &op, const PreconditionerType& preconditioner,
74 const SolverParameter &parameter = SolverParameter(Parameter::container()) )
75 : KrylovInverseOperator( op, &preconditioner, parameter )
76 {}
77
79 KrylovInverseOperator ( const SolverParameter &parameter = SolverParameter(Parameter::container()) )
80 : BaseType( parameter ),
81 precondObj_(),
82 verbose_( parameter.verbose() ),
83 method_( method < 0 ? parameter.solverMethod( supportedSolverMethods() ) : method ),
84 precondMethod_( parameter.preconditionMethod( supportedPreconditionMethods() ) )
85 {
86 // assert( parameter_->errorMeasure() == 0 );
87 }
88
89 template <class Operator>
90 void bind ( const Operator &op )
91 {
92 if( precondMethod_ && std::is_base_of< AssembledOperator< DomainFunctionType, DomainFunctionType >, Operator > :: value )
93 {
94 createPreconditioner( op );
95 }
96
97 if( precondObj_ )
98 BaseType::bind( op, *precondObj_ );
99 else
100 BaseType::bind( op );
101 }
102
103 static std::vector< int > supportedSolverMethods() {
104 return std::vector< int > ({ SolverParameter::gmres, // default solver
105 SolverParameter::cg,
106 SolverParameter::bicgstab });
107 }
108
109 static std::vector< int > supportedPreconditionMethods() {
110 return std::vector< int > ({ SolverParameter::none,
111 SolverParameter::sor,
112 SolverParameter::ssor,
113 SolverParameter::gauss_seidel,
114 SolverParameter::jacobi } );
115 }
116
117 protected:
118 int apply( const DomainFunctionType &u, RangeFunctionType &w ) const
119 {
120 std::ostream* os = nullptr;
121 // only set output when general verbose mode is enabled
122 // (basically to avoid output on every rank)
123 if( verbose_ && Parameter :: verbose( Parameter::solverStatistics ) )
124 {
125 os = &std::cout;
126 if( method_ == SolverParameter::gmres )
127 std::cout << "Fem::GMRES";
128 else if ( method_ == SolverParameter::bicgstab )
129 std::cout << "Fem::BiCGstab";
130 else if ( method_ == SolverParameter::cg )
131 std::cout << "Fem::CG";
132
133 std::cout << " preconditioning="<< SolverParameter::preconditionMethodTable( precondMethod_ ) << std::endl;
134 }
135
136 int numIter = 0;
137
138 if( method_ == SolverParameter::gmres )
139 {
140 if( v_.empty() )
141 {
142 const int extra = ( preconditioner_ ) ? 2 : 1 ;
143 v_.reserve( parameter_->gmresRestart()+extra );
144 for( int i=0; i<=parameter_->gmresRestart(); ++i )
145 {
146 v_.emplace_back( DiscreteFunction( "GMRes::v", u.space() ) );
147 }
148 if( preconditioner_ )
149 v_.emplace_back( DiscreteFunction( "GMRes::z", u.space() ) );
150 }
151
152 // if solver convergence failed numIter will be negative
153 numIter = LinearSolver::gmres( *operator_, preconditioner_,
154 v_, w, u, parameter_->gmresRestart(),
155 parameter_->tolerance(), parameter_->maxIterations(),
156 parameter_->errorMeasure(), os );
157 }
158 else if( method_ == SolverParameter::bicgstab )
159 {
160 if( v_.empty() )
161 {
162 v_.emplace_back( DomainFunctionType( "BiCGStab::r", u.space() ) );
163 v_.emplace_back( DomainFunctionType( "BiCGStab::r*", u.space() ) );
164 v_.emplace_back( DomainFunctionType( "BiCGStab::p", u.space() ) );
165 v_.emplace_back( DomainFunctionType( "BiCGStab::s", u.space() ) );
166 v_.emplace_back( DomainFunctionType( "BiCGStab::tmp", u.space() ) );
167 if( preconditioner_ )
168 v_.emplace_back( DomainFunctionType( "BiCGStab::z", u.space() ) );
169 }
170
171 // if solver convergence failed numIter will be negative
172 numIter = LinearSolver::bicgstab( *operator_, preconditioner_,
173 v_, w, u,
174 parameter_->tolerance(), parameter_->maxIterations(),
175 parameter_->errorMeasure(), os );
176 }
177 else if( method_ == SolverParameter::cg )
178 {
179 if( v_.empty() )
180 {
181 v_.emplace_back( DomainFunctionType( "CG::h", u.space() ) );
182 v_.emplace_back( DomainFunctionType( "CG::r", u.space() ) );
183 v_.emplace_back( DomainFunctionType( "CG::p", u.space() ) );
184
185 if( preconditioner_ )
186 {
187 v_.emplace_back( DomainFunctionType( "CG::s", u.space() ) );
188 v_.emplace_back( DomainFunctionType( "CG::q", u.space() ) );
189 }
190 }
191
192 // if solver convergence failed numIter will be negative
193 numIter = LinearSolver::cg( *operator_, preconditioner_,
194 v_, w, u,
195 parameter_->tolerance(), parameter_->maxIterations(),
196 parameter_->errorMeasure(), os );
197 }
198 else
199 {
200 DUNE_THROW(InvalidStateException,"KrylovInverseOperator: invalid method " << method_ );
201 }
202
203 return numIter;
204 }
205
206 template <class LinearOperator>
207 KrylovInverseOperator ( const LinearOperator &op,
208 const PreconditionerType *preconditioner,
209 const SolverParameter &parameter = SolverParameter(Parameter::container()) )
210 : KrylovInverseOperator( parameter )
211 {
212 bind(op);
213 }
214
215 protected:
216 template <class LinearOperator>
217 void createPreconditioner( const LinearOperator &op )
218 {
219 if( precondMethod_ > 0 && std::is_base_of< AssembledOperator< DomainFunctionType, DomainFunctionType >, LinearOperator > :: value )
220 {
221 const int n = parameter_->preconditionerIteration();
222 const double w = parameter_->relaxation();
223
224 if( precondMethod_ == SolverParameter::jacobi )
225 {
226 // create diagonal preconditioner
227 precondObj_.reset( new FemJacobiPreconditioning< DomainFunctionType, LinearOperator >( op, n, w ) );
228 }
229 else if( precondMethod_ == SolverParameter::gauss_seidel )
230 {
231 // create diagonal preconditioner
232 precondObj_.reset( new FemGaussSeidelPreconditioning< DomainFunctionType, LinearOperator >( op, n, w ) );
233 }
234 else if( precondMethod_ == SolverParameter::sor )
235 {
236 // create diagonal preconditioner
237 precondObj_.reset( new FemSORPreconditioning< DomainFunctionType, LinearOperator >( op, n, w ) );
238 }
239 else if( precondMethod_ == SolverParameter::ssor )
240 {
241 // create diagonal preconditioner
242 precondObj_.reset( new FemSSORPreconditioning< DomainFunctionType, LinearOperator >( op, n, w ) );
243 }
244
245 // if preconditioner was created, set pointer
246 if( precondObj_ )
247 {
248 preconditioner_ = precondObj_.operator->();
249 }
250 }
251 }
252
253 using BaseType :: operator_;
254 using BaseType :: preconditioner_;
255
256 using BaseType :: parameter_;
257 using BaseType :: iterations_;
258
259 std::unique_ptr< PreconditionerType > precondObj_;
260
261 mutable std::vector< DomainFunctionType > v_;
262
263 const bool verbose_;
264
265 const int method_;
266 const int precondMethod_;
267 };
268
269
270 // CgInverseOperator
271 // -----------------
272
273 template< class DiscreteFunction >
274 using CgInverseOperator = KrylovInverseOperator< DiscreteFunction, SolverParameter :: cg >;
275
276
277 // BicgstabInverseOperator
278 // -----------------------
279
280 template< class DiscreteFunction >
281 using BicgstabInverseOperator = KrylovInverseOperator< DiscreteFunction, SolverParameter :: bicgstab >;
282
283
284 // GmresInverseOperator
285 // --------------------
286
287 template< class DiscreteFunction >
288 using GmresInverseOperator = KrylovInverseOperator< DiscreteFunction, SolverParameter :: gmres >;
289
290
291 // ParDGGeneralizedMinResInverseOperator
292 // -------------------------------------
293
294 template< class DiscreteFunction >
295 using ParDGGeneralizedMinResInverseOperator = GmresInverseOperator< DiscreteFunction >;
296
297 // ParDGBiCGStabInverseOperator
298 // ----------------------------
299
300 template< class DiscreteFunction >
301 using ParDGBiCGStabInverseOperator = BicgstabInverseOperator< DiscreteFunction >;
302
303 template <class DiscreteFunctionType, class OpType >
304 using OEMCGOp = CgInverseOperator< DiscreteFunctionType >;
305
306 template <class DiscreteFunctionType, class OpType >
307 using OEMBICGSTABOp = BicgstabInverseOperator< DiscreteFunctionType >;
308
309 template <class DiscreteFunctionType, class OpType >
310 using OEMBICGSQOp = BicgstabInverseOperator< DiscreteFunctionType >;
311
312 template <class DiscreteFunctionType, class OpType >
313 using OEMGMRESOp = GmresInverseOperator< DiscreteFunctionType >;
314
315 template <class DiscreteFunctionType, class OpType >
316 using GMRESOp = GmresInverseOperator< DiscreteFunctionType >;
317
318 } // namespace Fem
319
320} // namespace Dune
321
322#endif // DUNE_FEM_SOLVER_INVERSEOPERATORS_HH
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
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr GeometryType none(unsigned int dim)
Returns a GeometryType representing a singular of dimension dim.
Definition: type.hh:471
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)