DUNE-FEM (unstable)

cg.hh
1#ifndef DUNE_FEM_CG_HH
2#define DUNE_FEM_CG_HH
3
4#include <type_traits>
5#include <vector>
6
8#include <dune/fem/solver/parameter.hh>
9
10namespace Dune
11{
12namespace Fem
13{
14namespace LinearSolver
15{
16
17 template <class Operator, class Precoditioner, class DiscreteFunction>
18 inline int cg( Operator &op,
19 Precoditioner* preconditioner,
20 std::vector< DiscreteFunction >& tempMem,
21 DiscreteFunction& x,
22 const DiscreteFunction& b,
23 const double epsilon,
24 const int maxIterations,
25 const int toleranceCriteria,
26 std::ostream* os = nullptr )
27 {
28 typedef typename DiscreteFunction::RangeFieldType RangeFieldType;
29 typedef typename Dune::FieldTraits< RangeFieldType >::real_type RealType;
30
31 assert( preconditioner ? tempMem.size() == 5 : tempMem.size() == 3 );
32
33 DiscreteFunction& h = tempMem[ 0 ];
34
35 //h=Ax
36 op( x, h );
37
38 //r=Ax-b
39 DiscreteFunction& r = tempMem[ 1 ];
40 r.assign( h );
41 r -= b;
42
43 //p=b-A*x <= r_0 Deufelhard
44 DiscreteFunction& p = tempMem[ 2 ];
45 p.assign( b );
46 p -= h;
47
48 DiscreteFunction& s = ( preconditioner ) ? tempMem[ 3 ] : p;
49
50 //q=B*p <=q Deufelhard
51 DiscreteFunction& q = ( preconditioner ) ? tempMem[ 4 ] : p;
52 if( preconditioner )
53 {
54 (*preconditioner)( p, q );
55 s.assign( q );
56 }
57
58 RangeFieldType prevResiduum = 0; // note that these will be real_type but require scalar product evaluation
59 RangeFieldType residuum = p.scalarProductDofs( q );//<p,Bp>
60
61 const RealType tolerance = epsilon * epsilon * (
62 toleranceCriteria == ToleranceCriteria::relative ? b.normSquaredDofs( ) :
63 toleranceCriteria == ToleranceCriteria::residualReduction ? std::real(residuum) :
64 // absolute tolerance
65 1.0
66 );
67
68 int iterations = 0;
69 for( iterations = 0; (std::real(residuum) > tolerance) && (iterations < maxIterations); ++iterations )
70 {
71 if( iterations > 0 )
72 {
73 assert( residuum/prevResiduum == residuum/prevResiduum );
74 const RangeFieldType beta= residuum / prevResiduum;
75 q *= beta;
76 if( preconditioner )
77 {
78 q += s;
79 }
80 else
81 {
82 p -= r;
83 }
84 }
85
86 op( q, h );
87
88 RangeFieldType qdoth = q.scalarProductDofs( h );
89 const RangeFieldType alpha = residuum / qdoth;//<p,Bp>/<q,Aq>
90 assert( !std::isnan( alpha ) );
91 x.axpy( alpha, q );
92
93 if( preconditioner )
94 {
95 p.axpy( -alpha, h );//r_k
96 (*preconditioner)( p, s); //B*r_k
97
98 prevResiduum = residuum;//<rk-1,B*rk-1>
99 residuum = p.scalarProductDofs( s );//<rk,B*rk>
100 }
101 else
102 {
103 r.axpy( alpha, h );
104
105 prevResiduum = residuum;
106 residuum = r.normSquaredDofs( );
107 }
108
109 if( os )
110 {
111 (*os) << "Fem::CG it: " << iterations << " : sqr(residuum) " << residuum << std::endl;
112 }
113 }
114
115 return (iterations < maxIterations) ? iterations : -iterations;
116 }
117
118} // naemspace LinearSolver
119} // namespace Fem
120
121} // namespace Dune
122
123#endif // #ifndef DUNE_FEM_CGINVERSEOPERATOR_HH
Type traits to determine the type of reals (when working with complex numbers)
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 13, 23:29, 2024)