1#ifndef DUNE_FEM_GMRES_HH
2#define DUNE_FEM_GMRES_HH
10#include <dune/fem/solver/parameter.hh>
24 Matrix(
int n,
int m) : n_(n), m_(m), data_( n*m, T(0) ) {}
25 Matrix(
int n) : Matrix(n,n) {}
28 T& operator()(
int i,
int j)
30 assert(i>=0 && i<n_ && j>=0 && j<m_);
31 return data_[i*m_ + j];
35 T operator()(
int i,
int j)
const
37 assert(i>=0 && i<n_ && j>=0 && j<m_);
38 return data_[i*m_ + j];
42 operator T*() {
return data_.data(); }
43 operator const T *()
const {
return data_.data(); }
47 std::vector< T > data_;
52 template <
class FieldType>
53 FieldType scalarProduct(
const int dim,
const FieldType *x,
const FieldType* y )
56 for(
int i=0; i<dim; ++i )
58 scp += x[ i ] * y[ i ];
64 template <
class Communication,
class FieldType,
class DiscreteFunction>
65 void gemv(
const Communication& comm,
67 std::vector< DiscreteFunction >& v,
68 const DiscreteFunction& vjp,
72 for(
int l=0; l<m; ++l)
77 const auto& auxiliaryDofs = vjp.space().auxiliaryDofs();
78 const auto& vj = vjp.dofVector();
80 auto scp = [&m, &y, &vj, &v] (
const size_t dof)
82 for(
int l=0; l<m; ++l)
84 y[ l ] += (vj[ dof ] * v[ l ].dofVector()[ dof ]);
95 template<
class FieldType>
96 void rotate(
const int dim,
97 FieldType* x, FieldType* y,
98 const FieldType c,
const FieldType s)
103 const FieldType _x = *x;
104 const FieldType _y = *y;
116 template <
class Operator,
class Preconditioner,
class DiscreteFunction>
117 inline int gmres( Operator& op, Preconditioner* preconditioner,
118 std::vector< DiscreteFunction >& v,
120 const DiscreteFunction& b,
122 const double tolerance,
123 const int maxIterations,
124 const int toleranceCriteria,
125 std::ostream* os =
nullptr )
127 typedef typename DiscreteFunction :: RangeFieldType FieldType;
129 const auto& comm = u.space().gridPart().comm();
131 detail::Matrix< FieldType > H( m+1, m );
132 std::vector< FieldType > g_( 6*m, 0.0 );
134 FieldType* g = g_.data();
135 FieldType* s = g + (m+1);
136 FieldType* c = s + m;
137 FieldType* y = c + m;
139 DiscreteFunction& v0 = v[ 0 ];
141 std::vector< FieldType > global_dot( m+1, FieldType(0) );
144 double _tolerance = tolerance;
145 if (toleranceCriteria == ToleranceCriteria::relative)
147 global_dot[ 0 ] = b.scalarProductDofs( b );
148 _tolerance *= std::sqrt(global_dot[0]);
161 global_dot[ 0 ] = v0.scalarProductDofs( v0 );
164 FieldType res = std::sqrt(global_dot[0]);
166 if (toleranceCriteria == ToleranceCriteria::residualReduction && iterations==0)
173 (*os) <<
"Fem::GMRES outer iteration : " << res << std::endl;
176 if (res < _tolerance)
break;
179 for(
int i=1; i<=m; i++) g[i] = 0.0;
187 for(
int j=0; j<m; j++)
189 DiscreteFunction& vj = v[ j ];
190 DiscreteFunction& vjp = v[ j + 1 ];
196 DiscreteFunction& z = v[ m+1 ];
197 (*preconditioner)(vj, z );
206 gemv(comm, j+1, v, vjp, global_dot.data());
208 for(
int i=0; i<=j; i++) H(i,j) = global_dot[i];
211 for(
int l=0; l<j+1; ++l)
213 vjp.axpy( -global_dot[l], v[l] );
217 global_dot[ 0 ] = vjp.scalarProductDofs( vjp );
219 H(j+1,j) = std::sqrt(global_dot[0]);
224 for(
int i=0; i<j; i++)
226 rotate(1, &H(i+1,j), &H(i,j), c[i], s[i]);
229 const FieldType h_j_j = H(j,j);
230 const FieldType h_jp_j = H(j+1,j);
231 const FieldType norm = std::sqrt(h_j_j*h_j_j + h_jp_j*h_jp_j);
233 s[j] = -h_jp_j / norm;
234 rotate(1, &H(j+1,j), &H(j,j), c[j], s[j]);
235 rotate(1, &g[j+1], &g[j], c[j], s[j]);
239 (*os) <<
"Fem::GMRES it: " << iterations <<
" : " << std::abs(g[j+1]) << std::endl;
243 if (std::abs(g[j+1]) < _tolerance
244 || iterations >= maxIterations )
break;
251 int last = iterations%m;
252 if (last == 0) last = m;
255 for(
int i=last-1; i>=0; --i)
257 const FieldType
dot = scalarProduct( last-(i+1), &H(i,i)+1, &y[i+1] );
258 y[i] = (g[i] -
dot)/ H(i,i);
265 DiscreteFunction& u_tmp = v[ m ];
266 DiscreteFunction& z = v[ m+1 ];
270 for(
int i=0; i<last; ++i)
272 u_tmp.axpy( y[ i ], v[ i ] );
275 (*preconditioner)(u_tmp, z);
280 for(
int i=0; i<last; ++i)
282 u.axpy( y[ i ], v[ i ] );
286 if (std::abs(g[last]) < _tolerance)
break;
291 (*os) <<
"Fem::GMRES: number of iterations: "
296 return (iterations < maxIterations) ? iterations : -iterations;
auto dot(const A &a, const B &b) -> typename std::enable_if< IsNumber< A >::value &&!IsVector< A >::value &&!std::is_same< typename FieldTraits< A >::field_type, typename FieldTraits< A >::real_type > ::value, decltype(conj(a) *b)>::type
computes the dot product for fundamental data types according to Petsc's VectDot function: dot(a,...
Definition: dotproduct.hh:42
static void forEachPrimaryDof(const AuxiliaryDofs &auxiliaryDofs, F &&f)
Apply action encoded in Functor f to all primary dofs.
Definition: auxiliarydofs.hh:303
Dune namespace.
Definition: alignedallocator.hh:13