DUNE-FEM (unstable)

cginverseoperator.hh
1#ifndef DUNE_FEM_CGINVERSEOPERATOR_HH
2#define DUNE_FEM_CGINVERSEOPERATOR_HH
3
4#include <limits>
5#include <memory>
6#include <type_traits>
7
8#include <dune/fem/io/parameter.hh>
9#include <dune/fem/function/common/discretefunction.hh>
10#include <dune/fem/operator/common/operator.hh>
11#include <dune/fem/solver/diagonalpreconditioner.hh>
12#include <dune/fem/solver/parameter.hh>
13
14namespace Dune
15{
16
17 namespace Fem
18 {
19
20 // ConjugateGradientSolver
21 // -----------------------
22
29 template< class Operator>
31 {
33
34 public:
37
42 typedef typename Dune::FieldTraits< RangeFieldType >::real_type RealType;
43
48
51
52
53 private:
54 static_assert( (std::is_same< DomainFunctionType, RangeFunctionType >::value),
55 "DomainFunctionType must equal RangeFunctionType." );
56
57 public:
65 ConjugateGradientSolver ( const RealType &epsilon,
66 unsigned int maxIterations,
67 int errorMeasure,
68 bool verbose )
69 : epsilon_( epsilon ),
70 maxIterations_( maxIterations ),
71 errorMeasure_( errorMeasure ),
72 verbose_( verbose && Fem::Parameter::verbose() ),
73 averageCommTime_( 0.0 ),
74 realCount_( 0 )
75 {}
76 ConjugateGradientSolver ( const RealType &epsilon,
77 unsigned int maxIterations,
78 bool verbose,
79 const ParameterReader &parameter = Parameter::container() )
80 : epsilon_( epsilon ),
81 maxIterations_( maxIterations ),
82 errorMeasure_( 1 ),
83 verbose_( verbose && Fem::Parameter::verbose() ),
84 averageCommTime_( 0.0 ),
85 realCount_( 0 )
86 {}
87
93 ConjugateGradientSolver ( RealType epsilon,
94 unsigned int maxIterations,
95 const ParameterReader &parameter = Parameter::container() )
96 : epsilon_( epsilon ),
97 maxIterations_( maxIterations ),
98 errorMeasure_( 1 ),
99 verbose_( parameter.getValue< bool >( "fem.solver.verbose", false ) ),
100 averageCommTime_( 0.0 ),
101 realCount_( 0 )
102 {}
103
104 // ConjugateGradientSolver ( const ThisType & )=delete;
105
117 void solve ( const OperatorType &op, const RangeFunctionType &b, DomainFunctionType &x ) const;
118
131 void solve ( const OperatorType &op, const PreconditionerType &p,
132 const RangeFunctionType &b, DomainFunctionType &x ) const;
133
135 unsigned int iterations () const
136 {
137 return realCount_;
138 }
139
140 void setMaxIterations ( unsigned int maxIterations ) { maxIterations_ = maxIterations; }
141
142
144 double averageCommTime() const
145 {
146 return averageCommTime_;
147 }
148
149 protected:
150 const RealType epsilon_;
151 unsigned int maxIterations_;
152 int errorMeasure_;
153 const bool verbose_;
154 mutable double averageCommTime_;
155 mutable unsigned int realCount_;
156 };
157
158
159 namespace Solver
160 {
161 // CGInverseOperator
162 // -----------------
163
169 template< class DiscreteFunction >
171 : public Fem::Operator< DiscreteFunction, DiscreteFunction >
172 {
175
176 public:
177 typedef typename BaseType::DomainFunctionType DomainFunctionType;
178 typedef typename BaseType::RangeFunctionType RangeFunctionType;
179
182
183 typedef typename OperatorType::RangeFieldType RangeFieldType;
184 typedef typename Dune::FieldTraits< RangeFieldType >::real_type RealType;
185
186 // non-const version
187 using BaseType::finalize;
188
189 private:
191
192 public:
200 CGInverseOperator ( RealType redEps, RealType absLimit,
201 unsigned int maxIter, bool verbose,
202 const ParameterReader &parameter = Parameter::container() )
203 : solver_( absLimit, maxIter, verbose, parameter ),
204 parameter_( parameter )
205 {}
206
207 CGInverseOperator ( const SolverParameter& param = SolverParameter(Parameter::container() ) )
208 : solver_( param.tolerance(),
209 param.maxIterations(),
210 param.errorMeasure(),
211 param.verbose() ),
212 parameter_( param )
213 {
214 }
215
216
223 CGInverseOperator ( RealType redEps, RealType absLimit,
224 unsigned int maxIter,
225 const ParameterReader &parameter = Parameter::container() )
226 : solver_( absLimit, maxIter, parameter ),
227 parameter_( parameter )
228 {}
229
230 CGInverseOperator ( RealType redEps, RealType absLimit,
231 const ParameterReader &parameter = Parameter::container() )
232 : CGInverseOperator( redEps, absLimit, std::numeric_limits< unsigned int >::max(), parameter )
233 {}
234
244 RealType redEps, RealType absLimit,
245 unsigned int maxIter, bool verbose,
246 const ParameterReader &parameter = Parameter::container() )
247 : CGInverseOperator( redEps, absLimit, maxIter, verbose, parameter )
248 {
249 bind( op );
250 }
251
252
261 RealType redEps, RealType absLimit,
262 unsigned int maxIter,
263 const ParameterReader &parameter = Parameter::container() )
264 : CGInverseOperator( redEps, absLimit, maxIter, parameter )
265 {
266 bind( op );
267 }
268
269 CGInverseOperator ( const OperatorType &op,
270 RealType redEps, RealType absLimit,
271 const ParameterReader &parameter = Parameter::container() )
272 : CGInverseOperator( redEps, absLimit, parameter )
273 {
274 bind( op );
275 }
276
287 const PreconditionerType &precond,
288 RealType redEps, RealType absLimit,
289 unsigned int maxIter, bool verbose,
290 const ParameterReader &parameter = Parameter::container() )
291 : CGInverseOperator( redEps, absLimit, maxIter, verbose )
292 {
293 bind( op, precond );
294 }
295
305 const PreconditionerType &precond,
306 RealType redEps, RealType absLimit,
307 const ParameterReader &parameter = Parameter::container() )
308 : CGInverseOperator( redEps, absLimit, parameter )
309 {
310 bind( op, precond );
311 }
312
313 CGInverseOperator ( const OperatorType &op,
314 const PreconditionerType &precond,
315 RealType redEps, RealType absLimit,
316 unsigned int maxIter,
317 const ParameterReader &parameter = Parameter::container() )
318 : CGInverseOperator( redEps, absLimit, maxIter, parameter )
319 {
320 bind( op, precond );
321 }
322
323 void bind ( const OperatorType &op ) { operator_ = &op; preconditioner_ = nullptr; }
324 void bind ( const OperatorType &op, const PreconditionerType &precond )
325 {
326 operator_ = &op;
327 preconditioner_ = &precond;
328 }
329 void unbind () { operator_ = nullptr; preconditioner_ = nullptr; }
330
339 virtual void operator()( const DomainFunctionType &arg, RangeFunctionType &dest ) const
340 {
341 prepare();
342 apply(arg,dest);
343 const_cast< ThisType& > (*this).finalize();
344 }
345
346 template<typename... A>
347 inline void prepare(A... ) const
348 {}
349
358 virtual void apply( const DomainFunctionType &arg, RangeFunctionType &dest ) const
359 {
360 assert(operator_);
361 if(preconditioner_)
362 solver_.solve( *operator_, *preconditioner_, arg, dest );
363 else
364 solver_.solve( *operator_, arg, dest );
365 }
366
368 unsigned int iterations () const
369 {
370 return solver_.iterations();
371 }
372
373 void setMaxIterations ( unsigned int maxIter ) { solver_.setMaxIterations( maxIter ); }
374
376 double averageCommTime() const
377 {
378 return solver_.averageCommTime();
379 }
380
381 SolverParameter& parameter () const
382 {
383 return parameter_;
384 }
385
386 protected:
387 const OperatorType *operator_ = nullptr;
388 const PreconditionerType *preconditioner_ = nullptr;
389 SolverType solver_;
390 mutable SolverParameter parameter_;
391 };
392 }
393
394 // CGInverseOperator
395 // -----------------
396
404 template< class DiscreteFunction,
405 class Op = Fem::Operator< DiscreteFunction, DiscreteFunction > >
407 : public Fem::Solver::CGInverseOperator< DiscreteFunction >
408 {
410
411 public:
412 using BaseType::bind;
413
414 typedef SolverParameter SolverParameterType;
415 typedef typename BaseType::DomainFunctionType DomainFunctionType;
416 typedef typename BaseType::RangeFunctionType RangeFunctionType;
417
418 typedef DomainFunctionType DestinationType;
419
421 typedef Op OperatorType;
422
423 typedef typename OperatorType::RangeFieldType RangeFieldType;
424 typedef typename Dune::FieldTraits< RangeFieldType >::real_type RealType;
425
426 // Preconditioner is to approximate op^-1 !
428
429 CGInverseOperator ( const SolverParameter& param = SolverParameter(Parameter::container()) )
430 : BaseType( param )
431 {}
432
433
441 CGInverseOperator ( RealType redEps, RealType absLimit,
442 unsigned int maxIter, bool verbose,
443 const ParameterReader &parameter = Parameter::container() )
444 : BaseType( redEps, absLimit, maxIter, verbose, parameter )
445 {}
446
453 CGInverseOperator ( RealType redEps, RealType absLimit,
454 unsigned int maxIter,
455 const ParameterReader &parameter = Parameter::container() )
456 : BaseType( redEps, absLimit, maxIter, parameter )
457 {}
458
459 CGInverseOperator ( RealType redEps, RealType absLimit,
460 const ParameterReader &parameter = Parameter::container() )
461 : BaseType( redEps, absLimit, parameter )
462 {}
463
472 template< class LinearOperator, std::enable_if_t< std::is_base_of< OperatorType, LinearOperator >::value, int > = 0 >
474 RealType redEps, RealType absLimit,
475 unsigned int maxIter, bool verbose,
476 const ParameterReader &parameter = Parameter::container() )
477 : BaseType( redEps, absLimit, maxIter, verbose, parameter )
478 {
479 bind( op );
480 }
481
489 template< class LinearOperator, std::enable_if_t< std::is_base_of< OperatorType, LinearOperator >::value, int > = 0 >
491 RealType redEps, RealType absLimit,
492 unsigned int maxIter,
493 const ParameterReader &parameter = Parameter::container() )
494 : BaseType( redEps, absLimit, maxIter, parameter )
495 {
496 bind( op );
497 }
498
499 template< class LinearOperator, std::enable_if_t< std::is_base_of< OperatorType, LinearOperator >::value, int > = 0 >
501 RealType redEps, RealType absLimit,
502 const ParameterReader &parameter = Parameter::container() )
503 : BaseType( redEps, absLimit, parameter )
504 {
505 bind( op );
506 }
507
517 const PreconditioningType &precond,
518 RealType redEps, RealType absLimit,
519 unsigned int maxIter, bool verbose,
520 const ParameterReader &parameter = Parameter::container() )
521 : BaseType( op, precond, redEps, absLimit, maxIter, verbose, parameter )
522 {}
523
533 const PreconditioningType &precond,
534 RealType redEps, RealType absLimit,
535 unsigned int maxIter,
536 const ParameterReader &parameter = Parameter::container() )
537 : BaseType( op, precond, redEps, absLimit, maxIter, parameter )
538 {}
539
541 const PreconditioningType &precond,
542 RealType redEps, RealType absLimit,
543 const ParameterReader &parameter = Parameter::container() )
544 : BaseType( op, precond, redEps, absLimit, parameter )
545 {}
546
547
548 template< class LinearOperator, std::enable_if_t< std::is_base_of< OperatorType, LinearOperator >::value, int > = 0 >
549 void bind ( const LinearOperator &op )
550 {
551 BaseType::bind( op );
552 checkPreconditioning( op );
553 }
554
555 void unbind ()
556 {
557 BaseType::unbind();
558 precondObj_.reset();
559 }
560
561 protected:
562 template< class LinearOperator >
563 void checkPreconditioning( const LinearOperator &linearOp )
564 {
565 bool preconditioning = false;
566 if (!parameter_.parameter().exists(parameter_.keyPrefix()+"preconditioning.method") &&
567 parameter_.parameter().exists("fem.preconditioning"))
568 {
569 preconditioning = parameter_.parameter().template getValue< bool >( "fem.preconditioning", false );
570 std::cout << "WARNING: using deprecated parameter `fem.preconditioning` use "
571 << parameter_.keyPrefix() << "preconditioning.method instead\n";
572 }
573 else
574 preconditioning = parameter_.preconditionMethod(
575 {
576 SolverParameter::none, // no preconditioning
577 SolverParameter::jacobi // Jacobi preconditioning
578 });
579 if( preconditioning && std::is_base_of< AssembledOperator< DomainFunctionType, DomainFunctionType > ,LinearOperator > :: value )
580 {
581 // create diagonal preconditioner
582 precondObj_.reset( new DiagonalPreconditioner< DomainFunctionType, LinearOperator >( linearOp ) );
583 preconditioner_ = precondObj_.get();
584 }
585 }
586
587 using BaseType::preconditioner_;
588 using BaseType::parameter_;
589 std::unique_ptr< PreconditioningType > precondObj_;
590 };
591
592 // Implementation of ConjugateGradientSolver
593 // -----------------------------------------
594
595 template< class Operator >
598 {
599
600 RealType tolerance = (epsilon_ * epsilon_);
601 if (errorMeasure_ == 1)
602 tolerance *= b.normSquaredDofs( );
603
604 averageCommTime_ = 0.0;
605
606 RangeFunctionType h( b );
607 op( x, h );
608
609 RangeFunctionType r( h );
610 r -= b;
611
612 RangeFunctionType p( b );
613 p -= h;
614
615 RealType prevResiduum = 0;
616 RealType residuum = r.normSquaredDofs( );
617
618 for( realCount_ = 0; (residuum > tolerance) && (realCount_ < maxIterations_); ++realCount_ )
619 {
620 if( realCount_ > 0 )
621 {
622 assert( residuum/prevResiduum == residuum/prevResiduum );
623 p *= (residuum / prevResiduum);
624 p -= r;
625 }
626
627 op( p, h );
628
629 RangeFieldType pdoth = p.scalarProductDofs( h );
630 const RangeFieldType alpha = residuum / pdoth;
631 assert( alpha == alpha );
632 x.axpy( alpha, p );
633 r.axpy( alpha, h );
634
635 prevResiduum = residuum;
636 residuum = r.normSquaredDofs( );
637
638 double exchangeTime = h.space().communicator().exchangeTime();
639 if( verbose_ )
640 {
641 std::cout << "CG-Iteration: " << realCount_ << ", Residuum: " << std::sqrt(residuum)
642 << ", Tolerance: " << std::sqrt(tolerance) << std::endl;
643 // only for parallel apps
644 if( b.space().gridPart().comm().size() > 1 )
645 std::cout << "Communication needed: " << exchangeTime << " s" << std::endl;
646 }
647
648 averageCommTime_ += exchangeTime;
649 }
650 }
651
652
653 template< class Operator >
655 ::solve ( const OperatorType &op, const PreconditionerType &precond, const RangeFunctionType &b, DomainFunctionType &x ) const
656 {
657 RealType tolerance = (epsilon_ * epsilon_);
658 if (errorMeasure_ == 1)
659 tolerance *= b.normSquaredDofs( );
660
661 averageCommTime_ = 0.0;
662
663 RangeFunctionType h( b );
664 //h=Ax
665 op( x, h );
666
667 //r=Ax-b
668 RangeFunctionType r( h );
669 r -= b;
670
671 //p=b-A*x <= r_0 Deufelhard
672 RangeFunctionType p( b );
673 p -= h;
674
675 //q=B*p <=q Deuf
676 RangeFunctionType q ( b );
677 precond(p,q);
678
679 RangeFunctionType s (q);
680
681 RangeFieldType prevResiduum = 0; // note that these will be real_type but require scalar product evaluation
682 RangeFieldType residuum = p.scalarProductDofs( q );//<p,Bp>
683
684 for( realCount_ = 0; (std::real(residuum) > tolerance) && (realCount_ < maxIterations_); ++realCount_ )
685 {
686 if( realCount_ > 0 )
687 {
688 assert( residuum/prevResiduum == residuum/prevResiduum );
689 const RangeFieldType beta=residuum/prevResiduum;
690 q*=beta;
691 q+=(s);
692 }
693
694 op( q, h );
695
696 RangeFieldType qdoth = q.scalarProductDofs( h );
697 const RangeFieldType alpha = residuum / qdoth;//<p,Bp>/<q,Aq>
698 assert( alpha == alpha );
699 x.axpy( alpha, q );
700
701 p.axpy( -alpha, h );//r_k
702
703 precond(p,s); //B*r_k
704
705 prevResiduum = residuum;//<rk-1,B*rk-1>
706
707 residuum = p.scalarProductDofs( s );//<rk,B*rk>
708
709 double exchangeTime = h.space().communicator().exchangeTime();
710 if( verbose_ )
711 {
712 std::cout << "CG-Iteration: " << realCount_ << ", Residuum: " << std::sqrt(residuum)
713 << ", Tolerance: " << std::sqrt(tolerance) << std::endl;
714 // only for parallel apps
715 if( b.space().gridPart().comm().size() > 1 )
716 std::cout << "Communication needed: " << exchangeTime << " s" << std::endl;
717 }
718
719 averageCommTime_ += exchangeTime;
720 }
721 }
722
723 } // namespace Fem
724
725} // namespace Dune
726
727#endif // #ifndef DUNE_FEM_CGINVERSEOPERATOR_HH
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
CGInverseOperator(RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:441
Op OperatorType
type of operator
Definition: cginverseoperator.hh:421
CGInverseOperator(const LinearOperator &op, RealType redEps, RealType absLimit, unsigned int maxIter, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:490
CGInverseOperator(RealType redEps, RealType absLimit, unsigned int maxIter, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:453
CGInverseOperator(const OperatorType &op, const PreconditioningType &precond, RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:516
CGInverseOperator(const LinearOperator &op, RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:473
CGInverseOperator(const OperatorType &op, const PreconditioningType &precond, RealType redEps, RealType absLimit, unsigned int maxIter, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:532
linear solver using the CG algorithm
Definition: cginverseoperator.hh:31
OperatorType::RangeFunctionType RangeFunctionType
type of the operator's range vectors
Definition: cginverseoperator.hh:47
ConjugateGradientSolver(RealType epsilon, unsigned int maxIterations, const ParameterReader &parameter=Parameter::container())
constructor
Definition: cginverseoperator.hh:93
unsigned int iterations() const
number of iterations needed for last solve
Definition: cginverseoperator.hh:135
void solve(const OperatorType &op, const RangeFunctionType &b, DomainFunctionType &x) const
solve
Definition: cginverseoperator.hh:597
double averageCommTime() const
return average communication time during last solve
Definition: cginverseoperator.hh:144
void solve(const OperatorType &op, const PreconditionerType &p, const RangeFunctionType &b, DomainFunctionType &x) const
solve
Definition: cginverseoperator.hh:655
Fem::Operator< RangeFunctionType, DomainFunctionType > PreconditionerType
type of the preconditioner, maps from the range of the operator (the dual space) in it's domain
Definition: cginverseoperator.hh:50
OperatorType::RangeFieldType RangeFieldType
field type of the operator's range vectors
Definition: cginverseoperator.hh:41
OperatorType::DomainFieldType DomainFieldType
field type of the operator's domain vectors
Definition: cginverseoperator.hh:39
OperatorType::DomainFunctionType DomainFunctionType
type of the operator's domain vectors
Definition: cginverseoperator.hh:45
Operator OperatorType
type of the operators to invert
Definition: cginverseoperator.hh:36
ConjugateGradientSolver(const RealType &epsilon, unsigned int maxIterations, int errorMeasure, bool verbose)
constructor
Definition: cginverseoperator.hh:65
Container for User Specified Parameters.
Definition: parameter.hh:191
Inverse operator base on CG method. This is the base class for the cg solver and does not imvolve any...
Definition: cginverseoperator.hh:172
CGInverseOperator(const OperatorType &op, RealType redEps, RealType absLimit, unsigned int maxIter, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:260
CGInverseOperator(RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:200
virtual void operator()(const DomainFunctionType &arg, RangeFunctionType &dest) const
application operator
Definition: cginverseoperator.hh:339
CGInverseOperator(const OperatorType &op, const PreconditionerType &precond, RealType redEps, RealType absLimit, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:304
CGInverseOperator(RealType redEps, RealType absLimit, unsigned int maxIter, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:223
unsigned int iterations() const
number of iterations needed for last solve
Definition: cginverseoperator.hh:368
virtual void apply(const DomainFunctionType &arg, RangeFunctionType &dest) const
application operator
Definition: cginverseoperator.hh:358
CGInverseOperator(const OperatorType &op, const PreconditionerType &precond, RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:286
double averageCommTime() const
return average communication time during last solve
Definition: cginverseoperator.hh:376
CGInverseOperator(const OperatorType &op, RealType redEps, RealType absLimit, unsigned int maxIter, bool verbose, const ParameterReader &parameter=Parameter::container())
constructor of CGInverseOperator
Definition: cginverseoperator.hh:243
A linear operator.
Definition: operators.hh:69
constexpr GeometryType none(unsigned int dim)
Returns a GeometryType representing a singular of dimension dim.
Definition: type.hh:471
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Dune namespace.
Definition: alignedallocator.hh:13
STL namespace.
abstract affine-linear operator
Definition: operator.hh:90
abstract operator
Definition: operator.hh:34
virtual void finalize()
finalization of operator
Definition: operator.hh:61
DomainFunction DomainFunctionType
type of discrete function in the operator's domain
Definition: operator.hh:36
RangeFunction::RangeFieldType RangeFieldType
field type of the operator's range
Definition: operator.hh:43
DomainFunction::RangeFieldType DomainFieldType
field type of the operator's domain
Definition: operator.hh:41
RangeFunction RangeFunctionType
type of discrete function in the operator's range
Definition: operator.hh:38
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 27, 22:29, 2024)