Discontinuous Galerkin Library
#include "dg/algorithm.h"
bicgstabl.h
Go to the documentation of this file.
1#ifndef _DG_BICGSTABl_
2#define _DG_BICGSTABl_
3
4#include <iostream>
5#include <cstring>
6#include <cmath>
7#include <algorithm>
8
9#include "blas.h"
10#include "functors.h"
11#include "backend/typedefs.h"
12
19namespace dg{
20
33template< class ContainerType>
35{
36 public:
37 using container_type = ContainerType;
40 BICGSTABl() = default;
50 BICGSTABl( const ContainerType& copyable, unsigned max_iterations,
51 unsigned l_input):
52 max_iter(max_iterations),
53 m_l(l_input),
54 m_tmp(copyable)
55 {
56 rhat.assign(m_l+1,copyable);
57 uhat.assign(m_l+1,copyable);
58 sigma.assign(m_l+1,0);
59 gamma.assign(m_l+1,0);
60 gammap.assign(m_l+1,0);
61 gammapp.assign(m_l+1,0);
62 tau.assign( m_l+1, std::vector<value_type>( m_l+1, 0));
63 }
70 template<class ...Params>
71 void construct( Params&& ...ps)
72 {
73 //construct and swap
74 *this = BICGSTABl( std::forward<Params>( ps)...);
75 }
78 void set_max( unsigned new_max) {max_iter = new_max;}
81 unsigned get_max() const {return max_iter;}
84 const ContainerType& copyable()const{ return m_tmp;}
85
88 void set_verbose( bool verbose){ m_verbose = verbose;}
89
91 void set_throw_on_fail( bool throw_on_fail){
92 m_throw_on_fail = throw_on_fail;
93 }
94
115 template< class MatrixType0, class ContainerType0, class ContainerType1, class MatrixType1, class ContainerType2 >
116 unsigned solve( MatrixType0&& A, ContainerType0& x, const ContainerType1& b, MatrixType1&& P, const ContainerType2& W, value_type eps = 1e-12, value_type nrmb_correction = 1);
117
118 private:
119 unsigned max_iter, m_l;
120 ContainerType m_tmp;
121 std::vector<ContainerType> rhat;
122 std::vector<ContainerType> uhat;
123 std::vector<value_type> sigma, gamma, gammap, gammapp;
124 std::vector<std::vector<value_type>> tau;
125 bool m_verbose = false, m_throw_on_fail = true;
126
127};
129
130template< class ContainerType>
131template< class Matrix, class ContainerType0, class ContainerType1, class Preconditioner, class ContainerType2>
132unsigned BICGSTABl< ContainerType>::solve( Matrix&& A, ContainerType0& x, const ContainerType1& b, Preconditioner&& P, const ContainerType2& W, value_type eps, value_type nrmb_correction)
133{
134#ifdef MPI_VERSION
135 int rank;
136 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
137#endif //MPI
138 dg::blas2::symv(std::forward<Preconditioner>(P),b,m_tmp);
139 value_type nrmb = sqrt(dg::blas2::dot(W,m_tmp));
140 value_type tol = eps*(nrmb + nrmb_correction);
141 if( nrmb == 0)
142 {
143 blas1::copy( 0., x);
144 return 0;
145 }
146 dg::blas2::symv(std::forward<Matrix>(A),x,m_tmp);
147 dg::blas1::axpby(1.,b,-1.,m_tmp);
148 if( sqrt( blas2::dot(W,m_tmp) ) < tol) //if x happens to be the solution
149 return 0;
150 dg::blas2::symv(std::forward<Preconditioner>(P),m_tmp,rhat[0]);
151
152 dg::blas1::copy(0., uhat[0]);
153
154 value_type rho_0 = 1;
155 value_type alpha = 0;
156 value_type omega = 1;
157 ContainerType0& xhat=x; // alias x for ease of notation
158
159 for (unsigned k = 0; k < max_iter; k+= m_l){
160
161 rho_0 = -omega*rho_0;
162
164 for(unsigned j = 0; j<m_l;j++)
165 {
166 value_type rho_1 = dg::blas2::dot(rhat[j],W,b);
167 value_type beta = alpha*rho_1/rho_0;
168 rho_0 = rho_1;
169 for(unsigned i = 0; i<=j;i++)
170 {
171 dg::blas1::axpby(1.,rhat[i],-1.0*beta,uhat[i]);
172 }
173 dg::blas2::symv(std::forward<Matrix>(A),uhat[j],m_tmp);
174 dg::blas2::symv(std::forward<Preconditioner>(P),m_tmp,uhat[j+1]);
175 if( rho_0 == 0)
176 alpha = 0;
177 else
178 alpha = rho_0/dg::blas2::dot(uhat[j+1],W,b);
179 for(unsigned i = 0; i<=j; i++)
180 {
181 dg::blas1::axpby(-1.0*alpha,uhat[i+1],1.,rhat[i]);
182 }
183 dg::blas2::symv(std::forward<Matrix>(A),rhat[j],m_tmp);
184 dg::blas2::symv(std::forward<Preconditioner>(P),m_tmp,rhat[j+1]);
185 dg::blas1::axpby(alpha,uhat[0],1.,xhat);
186 }
187
189 for(unsigned j = 1; j<=m_l; j++){
190 for(unsigned i = 1; i<j;i++){
191 tau[i][j] = 1.0/sigma[i]*dg::blas2::dot(rhat[j],W,rhat[i]);
192 dg::blas1::axpby(-tau[i][j],rhat[i],1.,rhat[j]);
193 }
194 sigma[j] = dg::blas2::dot(rhat[j],W,rhat[j]);
195 gammap[j] = 1.0/sigma[j]*dg::blas2::dot(rhat[0],W,rhat[j]);
196 }
197
198 gamma[m_l] = gammap[m_l];
199 omega = gamma[m_l];
200
201 for(unsigned j=m_l-1;j>=1;j--){
202 value_type tmp = 0;
203 for(unsigned i=j+1;i<=m_l;i++){
204 tmp += tau[j][i]*gamma[i];
205 }
206 gamma[j] = gammap[j]-tmp;
207 }
208 for(unsigned j=1;j<=m_l-1;j++){
209 value_type tmp = 0.;
210 for(unsigned i=j+1;i<=m_l-1;i++){
211 tmp += tau[j][i]*gamma[i+1];
212 }
213 gammapp[j] = gamma[j+1]+tmp;
214 }
215 dg::blas1::axpby(gamma[1],rhat[0],1.,xhat);
216 dg::blas1::axpby(-gammap[m_l],rhat[m_l],1.,rhat[0]);
217 dg::blas1::axpby(-gamma[m_l],uhat[m_l],1.,uhat[0]);
218 for(unsigned j = 1; j<=m_l-1; j++){
219 dg::blas1::axpby(gammapp[j],rhat[j],1.,xhat);
220 dg::blas1::axpby(-gamma[j],uhat[j],1.,uhat[0]);
221 dg::blas1::axpby(-gammap[j],rhat[j],1.,rhat[0]);
222 }
223
224 // rhat[0] is P dot the actual residual
225 value_type err = sqrt(dg::blas2::dot(W,rhat[0]));
226 if( m_verbose)
227 DG_RANK0 std::cout << "# Error is now : " << err << " Against " << tol << std::endl;
228 if( err < tol){
229 if( m_verbose)
230 DG_RANK0 std::cout << "# Exited with error : " << err << " After " << k+m_l << " Iterations." << std::endl;
231 return k+m_l;
232 }
233 }
234 if( m_verbose)
235 DG_RANK0 std::cout << "# Failed to converge within max_iter" << std::endl;
236 if( m_throw_on_fail)
237 {
238 throw dg::Fail( tol, Message(_ping_)
239 <<"After "<<max_iter<<" BICGSTABL iterations with rtol "<<eps<<" and atol "<<eps*nrmb_correction );
240 }
241 return max_iter;
242}
244
245}//namespace dg
246#endif
Preconditioned BICGSTAB(l) method to solve .
Definition: bicgstabl.h:35
void set_max(unsigned new_max)
Set the maximum number of iterations.
Definition: bicgstabl.h:78
void set_throw_on_fail(bool throw_on_fail)
Set or unset a throw on failure-to-converge.
Definition: bicgstabl.h:91
void set_verbose(bool verbose)
Set or unset debugging output during iterations.
Definition: bicgstabl.h:88
BICGSTABl()=default
Allocate nothing, Call construct method before usage.
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: bicgstabl.h:71
unsigned get_max() const
Get the current maximum number of iterations.
Definition: bicgstabl.h:81
dg::get_value_type< ContainerType > value_type
Definition: bicgstabl.h:38
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition: bicgstabl.h:84
ContainerType container_type
Definition: bicgstabl.h:37
BICGSTABl(const ContainerType &copyable, unsigned max_iterations, unsigned l_input)
Allocate memory for the preconditioned BICGSTABl method.
Definition: bicgstabl.h:50
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 preconditioned BICGSTABl method.
#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 symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
Definition: blas2.h:287
get_value_type< MatrixType > dot(const ContainerType1 &x, const MatrixType &m, const ContainerType2 &y)
; Binary reproducible general dot product
Definition: blas2.h:85
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
Useful typedefs of commonly used types.
#define DG_RANK0
Definition: typedefs.h:147