50template<
class ContainerType>
67 LGMRES(
const ContainerType&
copyable,
unsigned max_inner,
unsigned max_outer,
unsigned max_restarts):
71 m_maxRestarts( max_restarts),
72 m_inner_m( max_inner),
73 m_outer_k( max_outer),
74 m_krylovDimension( max_inner+max_outer)
76 if( m_inner_m < m_outer_k)
77 std::cerr <<
"WARNING (LGMRES): max_inner is smaller than the restart dimension max_outer. Did you swap the constructor parameters?\n";
79 m_H.assign( m_krylovDimension+1, std::vector<value_type>( m_krylovDimension, 0));
82 m_givens.assign( m_krylovDimension+1, {0,0});
84 m_s.assign(m_krylovDimension+1,0);
87 m_outer_w.assign(m_outer_k,
copyable);
88 m_outer_Az.assign(m_outer_k,
copyable);
89 m_V.assign(m_krylovDimension+1,
copyable);
97 template<
class ...Params>
101 *
this =
LGMRES( std::forward<Params>( ps)...);
105 void set_max(
unsigned new_Restarts) {m_maxRestarts = new_Restarts;}
108 unsigned get_max()
const {
return m_maxRestarts;}
111 m_throw_on_fail = throw_on_fail;
115 const ContainerType&
copyable()
const{
return m_tmp;}
139 template<
class MatrixType0,
class ContainerType0,
class ContainerType1,
class MatrixType1,
class ContainerType2 >
140 unsigned solve( MatrixType0&& A, ContainerType0& x,
const ContainerType1& b, MatrixType1&& P,
const ContainerType2& W,
value_type eps = 1e-12,
value_type nrmb_correction = 1);
152 template <
class Preconditioner,
class ContainerType0>
153 void Update(Preconditioner&& P, ContainerType &
dx, ContainerType0 &x,
154 unsigned dimension,
const std::vector<std::vector<value_type>> &H,
155 std::vector<value_type> &s,
const std::vector<const ContainerType*> &W);
156 std::vector<std::array<value_type,2>> m_givens;
157 std::vector<std::vector<value_type>> m_H, m_HH;
158 ContainerType m_tmp, m_dx, m_residual;
159 std::vector<ContainerType> m_V, m_outer_w, m_outer_Az;
160 std::vector<value_type> m_s;
161 unsigned m_maxRestarts, m_inner_m, m_outer_k, m_krylovDimension;
162 bool m_converged =
true, m_throw_on_fail =
true;
166template<
class ContainerType>
167template <
class Preconditioner,
class ContainerType0>
168void LGMRES<ContainerType>::Update(Preconditioner&& P, ContainerType &
dx,
170 unsigned dimension,
const std::vector<std::vector<value_type>> &H,
171 std::vector<value_type> &s,
const std::vector<const ContainerType*> &W)
175 for (
int lupe = dimension; lupe >= 0; --lupe)
177 s[lupe] = s[lupe]/H[lupe][lupe];
178 for (
int innerLupe = lupe - 1; innerLupe >= 0; --innerLupe)
181 s[innerLupe] = DG_FMA( -s[lupe],H[innerLupe][lupe], s[innerLupe]);
192template<
class ContainerType>
193template<
class Matrix,
class ContainerType0,
class ContainerType1,
class Preconditioner,
class ContainerType2>
194unsigned LGMRES< ContainerType>::solve( Matrix&& A, ContainerType0& x,
const ContainerType1& b, Preconditioner&& P,
const ContainerType2& S, value_type eps, value_type nrmb_correction)
202 value_type tol = eps*(nrmb + nrmb_correction);
210 unsigned restartCycle = 0;
211 unsigned counter = 0;
214 std::vector<ContainerType const*> m_W, m_Vptr;
215 m_W.assign(m_krylovDimension,
nullptr);
216 m_Vptr.assign(m_krylovDimension+1,
nullptr);
217 for(
unsigned i=0; i<m_krylovDimension+1; i++)
231 for(
unsigned lupe=1;lupe<=m_krylovDimension;++lupe)
235 for(
unsigned iteration=0;iteration<m_krylovDimension;++iteration)
237 unsigned outer_w_count = std::min(restartCycle,m_outer_k);
238 if(iteration < m_krylovDimension-outer_w_count){
239 m_W[iteration] = &m_V[iteration];
240 dg::blas2::gemv(std::forward<Preconditioner>(P),*m_W[iteration],m_tmp);
243 }
else if( iteration < m_krylovDimension){
244 unsigned w_idx = iteration - (m_krylovDimension - outer_w_count);
245 m_W[iteration] = &m_outer_w[w_idx];
251 for(
unsigned row=0;row<=iteration;++row)
253 m_HH[row][iteration] = m_H[row][iteration]
258 m_HH[iteration+1][iteration] = m_H[iteration+1][iteration]
269 for (
unsigned row = 0; row < iteration; row++)
271 tmp = m_givens[row][0]*m_H[row][iteration] +
272 m_givens[row][1]*m_H[row+1][iteration];
273 m_H[row+1][iteration] = -m_givens[row][1]*m_H[row][iteration]
274 + m_givens[row][0]*m_H[row+1][iteration];
275 m_H[row][iteration] = tmp;
279 if(m_H[iteration+1][iteration] == 0.0)
282 m_givens[iteration][0] = 1.0;
283 m_givens[iteration][1] = 0.0;
285 else if (fabs(m_H[iteration+1][iteration]) > fabs(m_H[iteration][iteration]))
290 tmp = m_H[iteration][iteration]/m_H[iteration+1][iteration];
291 m_givens[iteration][1] = 1.0/sqrt(1.0+tmp*tmp);
292 m_givens[iteration][0] = tmp*m_givens[iteration][1];
299 tmp = m_H[iteration+1][iteration]/m_H[iteration][iteration];
300 m_givens[iteration][0] = 1.0/sqrt(1.0+tmp*tmp);
301 m_givens[iteration][1] = tmp*m_givens[iteration][0];
304 tmp = m_givens[iteration][0]*m_H[iteration][iteration] +
305 m_givens[iteration][1]*m_H[iteration+1][iteration];
306 m_H[iteration+1][iteration] = -m_givens[iteration][1]*m_H[iteration][iteration] +
307 m_givens[iteration][0]*m_H[iteration+1][iteration];
308 m_H[iteration][iteration] = tmp;
310 tmp = m_givens[iteration][0]*m_s[iteration] + m_givens[iteration][1]*m_s[iteration+1];
311 m_s[iteration+1] = -m_givens[iteration][1]*m_s[iteration] + m_givens[iteration][1]*m_s[iteration+1];
312 m_s[iteration] = tmp;
314 rho = fabs(m_s[iteration+1]);
317 Update(std::forward<Preconditioner>(P),m_dx,x,iteration,m_H,m_s,m_W);
321 Update(std::forward<Preconditioner>(P),m_dx,x,m_krylovDimension-1,m_H,m_s,m_W);
324 std::rotate(m_outer_w.rbegin(),m_outer_w.rbegin()+1,m_outer_w.rend());
325 std::rotate(m_outer_Az.rbegin(),m_outer_Az.rbegin()+1,m_outer_Az.rend());
331 std::vector<value_type> coeffs( m_krylovDimension+1, 0.);
332 for(
unsigned i=0; i<m_krylovDimension+1; i++)
335 for(
unsigned k=0; k<m_krylovDimension; k++)
336 coeffs[i] = DG_FMA( m_HH[i][k],m_s[k], coeffs[i]);
343 }
while( (restartCycle < m_maxRestarts) && (rho > tol));
349 <<
"After "<<counter<<
" LGMRES iterations");
Functor class for the right preconditioned LGMRES method to solve .
Definition: lgmres.h:52
bool converged() const
If last call to solve converged or not.
Definition: lgmres.h:147
void set_throw_on_fail(bool throw_on_fail)
Set or unset a throw on failure-to-converge.
Definition: lgmres.h:110
LGMRES(const ContainerType ©able, unsigned max_inner, unsigned max_outer, unsigned max_restarts)
Allocate memory for the preconditioned LGMRES method.
Definition: lgmres.h:67
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition: lgmres.h:115
LGMRES()=default
Allocate nothing, Call construct method before usage.
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: lgmres.h:98
unsigned get_max() const
Get the current maximum number of restarts.
Definition: lgmres.h:108
void set_max(unsigned new_Restarts)
Set the number of restarts.
Definition: lgmres.h:105
ContainerType container_type
Definition: lgmres.h:54
unsigned solve(MatrixType0 &&A, ContainerType0 &x, const ContainerType1 &b, MatrixType1 &&P, const ContainerType2 &W, value_type eps=1e-12, value_type nrmb_correction=1)
Solve using a right preconditioned LGMRES method.
dg::get_value_type< ContainerType > value_type
Definition: lgmres.h:55
#define _ping_
Definition: exceptions.h:12
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:231
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:185
void gemv(get_value_type< ContainerType1 > alpha, MatrixType &&M, const ContainerType1 &x, get_value_type< ContainerType1 > beta, ContainerType2 &y)
; (alias for symv)
Definition: blas2.h:299
get_value_type< MatrixType > dot(const ContainerType1 &x, const MatrixType &m, const ContainerType2 &y)
; Binary reproducible general dot product
Definition: blas2.h:85
EllSparseBlockMat< real_type > dx(const aRealTopology2d< real_type > &g, bc bcx, direction dir=centered)
Create 2d derivative in x-direction.
Definition: derivatives.h:33
auto asDenseMatrix(const std::vector< const ContainerType * > &in)
Lightweight DenseMatrix for dg::blas2::gemv.
Definition: densematrix.h:70
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition: tensor_traits.h:38
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Indicate failure to converge.
Definition: exceptions.h:126