1#ifndef DUNE_FEM_BICGSTAB_HH
2#define DUNE_FEM_BICGSTAB_HH
10#include <dune/fem/solver/parameter.hh>
19 template <
class DiscreteFunction,
class FieldType>
20 void scalarProductVecs(
const DiscreteFunction& r_df,
21 const DiscreteFunction& s_df,
22 const DiscreteFunction& r_star_df,
23 FieldType* global_dot )
25 const auto& comm = r_df.space().gridPart().comm();
27 const auto& r = r_df.dofVector();
28 const auto& s = s_df.dofVector();
29 const auto& r_star = r_star_df.dofVector();
31 const auto& auxiliaryDofs = r_df.space().auxiliaryDofs();
33 global_dot[ 4 ] = global_dot[ 3 ] = global_dot[ 2 ] = global_dot[ 1 ] = global_dot[ 0 ] = 0.0;
35 const size_t numAuxiliarys = auxiliaryDofs.size();
36 for(
size_t auxiliary = 0, i = 0 ; auxiliary < numAuxiliarys; ++auxiliary )
38 const size_t nextAuxiliary = auxiliaryDofs[ auxiliary ];
39 for(; i < nextAuxiliary; ++i )
41 global_dot[ 0 ] += r[ i ] * s[ i ];
42 global_dot[ 1 ] += r[ i ] * r[ i ];
43 global_dot[ 2 ] += s[ i ] * s[ i ];
44 global_dot[ 3 ] += s[ i ] * r_star[ i ];
45 global_dot[ 4 ] += r[ i ] * r_star[ i ];
50 comm.sum( global_dot, 5 );
63 template <
class Operator,
class Precoditioner,
class DiscreteFunction>
64 inline int bicgstab( Operator &op,
65 Precoditioner* preconditioner,
66 std::vector< DiscreteFunction >& tempMem,
68 const DiscreteFunction& b,
69 const double tolerance,
70 const int maxIterations,
71 const int toleranceCriteria,
72 std::ostream* os =
nullptr )
74 assert( ( preconditioner ) ? tempMem.size() == 6 : tempMem.size() == 5 );
76 DiscreteFunction& r = tempMem[ 0 ];
77 DiscreteFunction& r_star = tempMem[ 1 ];
78 DiscreteFunction& p = tempMem[ 2 ];
79 DiscreteFunction& s = tempMem[ 3 ];
80 DiscreteFunction& tmp = tempMem[ 4 ];
82 DiscreteFunction& z = ( preconditioner ) ? tempMem[ 5 ] : r;
84 typedef typename DiscreteFunction :: RangeFieldType FieldType;
87 FieldType global_dot[5];
88 double _tolerance = tolerance;
90 if (toleranceCriteria == ToleranceCriteria::relative)
92 global_dot[ 0 ] = b.scalarProductDofs( b );
93 _tolerance *= std::sqrt(global_dot[0]);
99 (*preconditioner)(x, z);
116 global_dot[0] = r.scalarProductDofs( r_star );
118 FieldType nu = global_dot[0];
119 if (toleranceCriteria == ToleranceCriteria::residualReduction)
121 _tolerance *= std::sqrt(nu);
131 (*preconditioner)(p, z);
139 global_dot[0] = tmp.scalarProductDofs( r_star );
141 const FieldType alpha = nu / global_dot[0];
143 s.axpy( -alpha, tmp );
148 (*preconditioner)(s, z);
157 scalarProductVecs( r, s, r_star, global_dot );
160 const FieldType omega = global_dot[0] / global_dot[1];
161 const FieldType res = std::sqrt(global_dot[2]
162 -omega*(2.0*global_dot[0] - omega*global_dot[1]) );
164 const FieldType beta = (global_dot[3] - omega*global_dot[4])
167 nu = (global_dot[3] - omega*global_dot[4]);
175 if (res < _tolerance || iterations >= maxIterations )
break;
183 p.axpy( -omega*beta, tmp );
188 (*os) <<
"Fem::BiCGstab it: " << iterations <<
" : " << res << std::endl;
195 (*os) <<
"Fem::BiCGstab: number of iterations: "
204 (*preconditioner)(x, z);
210 if( iterations >= maxIterations )
Dune namespace.
Definition: alignedallocator.hh:13