9#include <dune/fem/solver/parameter.hh>
18 template <
class Operator,
class Precoditioner,
class DiscreteFunction>
19 inline int cg( Operator &op,
20 Precoditioner* preconditioner,
21 std::vector< DiscreteFunction >& tempMem,
23 const DiscreteFunction& b,
25 const int maxIterations,
26 const int toleranceCriteria,
27 std::ostream* os =
nullptr )
29 typedef typename DiscreteFunction::RangeFieldType RangeFieldType;
30 typedef typename Dune::FieldTraits< RangeFieldType >::real_type RealType;
32 assert( preconditioner ? tempMem.size() == 5 : tempMem.size() == 3 );
34 DiscreteFunction& h = tempMem[ 0 ];
40 DiscreteFunction& r = tempMem[ 1 ];
45 DiscreteFunction& p = tempMem[ 2 ];
49 DiscreteFunction& s = ( preconditioner ) ? tempMem[ 3 ] : p;
52 DiscreteFunction& q = ( preconditioner ) ? tempMem[ 4 ] : p;
55 (*preconditioner)( p, q );
59 RangeFieldType prevResidual = 0;
60 RangeFieldType residual = p.scalarProductDofs( q );
62 const RealType tolerance = epsilon * epsilon * (
63 toleranceCriteria == ToleranceCriteria::relative ? b.normSquaredDofs( ) :
64 toleranceCriteria == ToleranceCriteria::residualReduction ? std::real(residual) :
70 for( iterations = 0; (std::real(residual) > tolerance) && (iterations < maxIterations); ++iterations )
74 assert( residual/prevResidual == residual/prevResidual );
75 const RangeFieldType beta= residual / prevResidual;
89 RangeFieldType qdoth = q.scalarProductDofs( h );
90 const RangeFieldType alpha = residual / qdoth;
91 assert( !std::isnan( alpha ) );
97 (*preconditioner)( p, s);
99 prevResidual = residual;
100 residual = p.scalarProductDofs( s );
106 prevResidual = residual;
107 residual = r.normSquaredDofs( );
112 (*os) <<
"Fem::CG it: " << iterations <<
" : residual " << std::sqrt(residual) << std::endl;
116 return (iterations < maxIterations) ? iterations : -iterations;
Type traits to determine the type of reals (when working with complex numbers)
Dune namespace.
Definition: alignedallocator.hh:13