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