Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
pcg.h
Go to the documentation of this file.
1#ifndef _DG_PCG_
2#define _DG_PCG_
3
4#include <cmath>
5
6#include "blas.h"
7#include "functors.h"
8#include "extrapolation.h"
9#include "backend/typedefs.h"
10
11#include "backend/timer.h"
12
17namespace dg{
19namespace detail
20{
21struct NORM
22{
23 template<class T, class Z>
25 auto operator()( T w, Z z) {
26 return w*norm(z);} // returns floating point
27};
28struct DOT
29{
30 template<class Z0, class T, class Z1>
32 auto operator()( Z0 z0, T w, Z1 z1) { // returns floating point
33 return w*(z0.real()*z1.real() + z0.imag()*z1.imag());
34 }
35};
36} // namespace detail
38
39// TODO check for better stopping criteria using condition number estimates?
55
56// TODO test complex behaviour
57
103template<class ContainerType, ComplexMode complex_mode = dg::complex_hermitian>
104class PCG
105{
106 public:
107 using container_type = ContainerType;
109
111 PCG() = default;
118 PCG( const ContainerType& copyable, unsigned max_iterations):
119 m_r(copyable), m_p(m_r), m_ap(m_r), m_max_iter(max_iterations){}
122 void set_max( unsigned new_max) {m_max_iter = new_max;}
125 unsigned get_max() const {return m_max_iter;}
128 const ContainerType& copyable()const{ return m_r;}
129
132 void set_verbose( bool verbose){ m_verbose = verbose;}
136 void set_throw_on_fail( bool throw_on_fail){
137 m_throw_on_fail = throw_on_fail;
138 }
139
141 template<class ...Params>
142 void construct( Params&& ...ps)
143 {
144 //construct and swap
145 *this = PCG( std::forward<Params>( ps)...);
146 }
175 template< class MatrixType0, class ContainerType0, class ContainerType1, class MatrixType1, class ContainerType2 >
176 unsigned solve( MatrixType0&& A, ContainerType0& x, const ContainerType1& b, MatrixType1&& P, const ContainerType2& W, double eps = 1e-12, double nrmb_correction = 1, int test_frequency = 1);
177 private:
178 // !! Calling this "norm" would shadow std::norm in NORM
179 template<class ContainerType1, class ContainerType2>
180 auto nrm( const ContainerType1& w, const ContainerType2& x)
181 {
182 using value_type_x = dg::get_value_type<ContainerType2>;
183 constexpr bool is_complex = dg::is_scalar_v<value_type_x, dg::ComplexTag>;
184 if constexpr (is_complex)
185 return sqrt( blas1::vdot( detail::NORM(), w, x));
186 else
187 return sqrt( blas2::dot( w, x));
188 }
189 template<class ContainerType0, class ContainerType1, class ContainerType2>
190 auto dot( const ContainerType0& x0, const ContainerType1& w, const ContainerType2& x1)
191 {
192 using value_type_x1 = dg::get_value_type<ContainerType2>;
193 constexpr bool is_complex = dg::is_scalar_v<value_type_x1, dg::ComplexTag>;
194 if constexpr (not is_complex or complex_mode == dg::complex_symmetric)
195 return blas2::dot( x0, w, x1); // this returns value_type
196 else // For Hermitian matrices all dot products in CG are real
197 return blas1::vdot( detail::DOT(), x0, w, x1); // this returns floating point
198 }
199 ContainerType m_r, m_p, m_ap;
200 unsigned m_max_iter;
201 bool m_verbose = false, m_throw_on_fail = true, m_cocg = false;
202};
203
208template<class ContainerType>
210
212template< class ContainerType, ComplexMode mode>
213template< class Matrix, class ContainerType0, class ContainerType1, class Preconditioner, class ContainerType2>
214unsigned PCG< ContainerType, mode>::solve( Matrix&& A, ContainerType0& x, const ContainerType1& b, Preconditioner&& P, const ContainerType2& W, double eps, double nrmb_correction, int save_on_dots )
215{
216 // self-adjoint: apply PCG algorithm to (P 1/W) (W A) x = (P 1/W) (W b) : P' A' x = P' b'
217 // This effectively just replaces all scalar products with the weighted one
218 auto nrmb = nrm( W, b), nrmr(nrmb);
219 double tol = eps*(nrmb + nrmb_correction);
220#ifdef MPI_VERSION
221 int rank;
222 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
223#endif //MPI
224 if( m_verbose)
225 {
226 DG_RANK0 std::cout << "# Norm of W b "<<nrmb <<"\n";
227 DG_RANK0 std::cout << "# Residual errors: \n";
228 }
229 if( nrmb == 0)
230 {
232 return 0;
233 }
234 blas2::symv( std::forward<Matrix>(A), x, m_r);
235 blas1::axpby( 1., b, -1., m_r);
236 nrmr = nrm( W, m_r);
237
238 if( nrmr < tol) //if x happens to be the solution
239 return 0;
240 blas2::symv( std::forward<Preconditioner>(P), m_r, m_p );
241 auto dotzr_old = dot( m_p, W, m_r), alpha(dotzr_old), dotzr_new(dotzr_old);
242 for( unsigned i=1; i<m_max_iter; i++)
243 {
244 blas2::symv( std::forward<Matrix>(A), m_p, m_ap);
245 alpha = dotzr_old/dot( m_p, W, m_ap);
246 blas1::axpby( alpha, m_p, 1., x);
247 blas1::axpby( -alpha, m_ap, 1., m_r);
248 if( 0 == i%save_on_dots )
249 {
250 nrmr = nrm( W, m_r);
251 if( m_verbose)
252 {
253 DG_RANK0 std::cout << "# Absolute r*W*r "<<nrmr <<"\t ";
254 DG_RANK0 std::cout << "# < Critical "<<tol <<"\t ";
255 DG_RANK0 std::cout << "# (Relative "<<nrmr/nrmb << ")\n";
256 }
257 if( nrmr < tol)
258 return i;
259 }
260 blas2::symv(std::forward<Preconditioner>(P),m_r,m_ap);
261 dotzr_new = dot( m_ap, W, m_r);
262 blas1::axpby(1., m_ap, dotzr_new/dotzr_old, m_p );
263 dotzr_old=dotzr_new;
264 }
265 if( m_throw_on_fail)
266 {
267 throw dg::Fail( tol, Message(_ping_)
268 <<"After "<<m_max_iter<<" PCG iterations with rtol "<<eps<<" and atol "<<eps*nrmb_correction );
269 }
270 return m_max_iter;
271}
273
274} //namespace dg
275
276
277
278#endif //_DG_PCG_
small class holding a stringstream
Definition exceptions.h:29
Preconditioned conjugate gradient method to solve .
Definition pcg.h:105
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition pcg.h:128
unsigned solve(MatrixType0 &&A, ContainerType0 &x, const ContainerType1 &b, MatrixType1 &&P, const ContainerType2 &W, double eps=1e-12, double nrmb_correction=1, int test_frequency=1)
Solve using a preconditioned conjugate gradient method.
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition pcg.h:108
PCG()=default
Allocate nothing, Call construct method before usage.
ContainerType container_type
Definition pcg.h:107
void set_verbose(bool verbose)
Set or unset debugging output during iterations.
Definition pcg.h:132
void set_throw_on_fail(bool throw_on_fail)
Set or unset a throw on failure-to-converge.
Definition pcg.h:136
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition pcg.h:142
PCG(const ContainerType &copyable, unsigned max_iterations)
Allocate memory for the pcg method.
Definition pcg.h:118
unsigned get_max() const
Get the current maximum number of iterations.
Definition pcg.h:125
void set_max(unsigned new_max)
Set the maximum number of iterations.
Definition pcg.h:122
#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 vdot(Functor f, const ContainerType &x, const ContainerTypes &...xs) -> std::invoke_result_t< Functor, dg::get_value_type< ContainerType >, dg::get_value_type< ContainerTypes >... >
Extended Precision transform reduce
Definition blas1.h:90
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:331
@ x
x direction
constexpr bool is_scalar_v
Utility typedef.
Definition predicate.h:72
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition tensor_traits.h:45
ComplexMode
Determine algorithm for complex matrices.
Definition pcg.h:51
@ complex_symmetric
choose COCG algorithm
Definition pcg.h:52
@ complex_hermitian
choose Hermitian algorithm
Definition pcg.h:53
#define DG_DEVICE
Expands to __host__ __device__ if compiled with nvcc else is empty.
Definition dg_doc.h:378
const double alpha
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
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:152