Discontinuous Galerkin Library
#include "dg/algorithm.h"
chebyshev.h
Go to the documentation of this file.
1#ifndef _DG_CHEB_
2#define _DG_CHEB_
3
4#include <cmath>
5
6#include "blas.h"
7
12namespace dg
13{
14
55template< class ContainerType>
57{
58 public:
59 using container_type = ContainerType;
62 ChebyshevIteration() = default;
64 ChebyshevIteration( const ContainerType& copyable):
65 m_ax(copyable), m_z( m_ax), m_xm1(m_ax){}
68 const ContainerType& copyable()const{ return m_ax;}
69
75 void construct( const ContainerType& copyable) {
76 m_xm1 = m_z = m_ax = copyable;
77 }
100 template< class MatrixType, class ContainerType0, class ContainerType1>
101 void solve( MatrixType&& A, ContainerType0& x, const ContainerType1& b,
102 value_type min_ev, value_type max_ev, unsigned num_iter, bool x_is_zero = false)
103 {
104 if( num_iter == 0)
105 return;
106 assert ( min_ev < max_ev);
107 value_type theta = (min_ev+max_ev)/2., delta = (max_ev-min_ev)/2.;
108 value_type rhokm1 = delta/theta, rhok=0;
109 if( !x_is_zero)
110 {
111 dg::blas1::copy( x, m_xm1); //x_{k-1}
112 dg::blas2::symv( std::forward<MatrixType>(A), x, m_ax);
113 dg::blas1::axpbypgz( 1./theta, b, -1./theta, m_ax, 1., x); //x_1
114 }
115 else
116 {
117 dg::blas1::copy( 0., m_xm1); //x_{k-1}
118 dg::blas1::axpby( 1./theta, b, 0., x); //x_1
119 }
120 for ( unsigned k=1; k<num_iter; k++)
121 {
122 rhok = 1./(2.*theta/delta - rhokm1);
123 dg::blas2::symv( std::forward<MatrixType>(A), x, m_ax);
125 1.+rhok*rhokm1, x,
126 -rhok*rhokm1, m_xm1,
127 2.*rhok/delta, b,
128 -2.*rhok/delta, m_ax
129 );
130 using std::swap;
131 swap( x, m_xm1);
132 rhokm1 = rhok;
133 }
134 }
158 template< class MatrixType0, class MatrixType1, class ContainerType0, class ContainerType1>
159 void solve( MatrixType0&& A, ContainerType0& x, const ContainerType1& b,
160 MatrixType1&& P, value_type min_ev, value_type max_ev, unsigned num_iter,
161 bool x_is_zero = false)
162 {
163 if( num_iter == 0)
164 return;
165 assert ( min_ev < max_ev);
166 value_type theta = (min_ev+max_ev)/2., delta = (max_ev-min_ev)/2.;
167 value_type rhokm1 = delta/theta, rhok=0;
168 if( !x_is_zero)
169 {
170 dg::blas1::copy( x, m_xm1); //x_{k-1}
171 dg::blas2::symv( std::forward<MatrixType0>(A), x, m_ax);
172 dg::blas1::axpby( 1., b, -1., m_ax); //r_0
173 dg::blas2::symv( std::forward<MatrixType1>(P), m_ax, m_z);
174 dg::blas1::axpby( 1./theta, m_z, 1., x); //x_{k-1}
175 }
176 else
177 {
178 dg::blas2::symv( std::forward<MatrixType1>(P), b, x);
179 if( num_iter == 1) return;
180 dg::blas1::scal( m_xm1, 0.);
181 dg::blas1::scal( x, 1./theta);
182 }
183 for ( unsigned k=1; k<num_iter; k++)
184 {
185 rhok = 1./(2.*theta/delta - rhokm1);
186 dg::blas2::symv( std::forward<MatrixType0>(A), x, m_ax);
187 dg::blas1::axpby( 1., b, -1., m_ax); //r_k
188 dg::blas2::symv( P, m_ax, m_z);
190 1.+rhok*rhokm1, x,
191 2.*rhok/delta, m_z,
192 -rhok*rhokm1, m_xm1
193 );
194 using std::swap;
195 swap( x, m_xm1);
196 rhokm1 = rhok;
197 }
198 }
199 private:
200 ContainerType m_ax, m_z, m_xm1;
201};
202
223template<class Matrix, class ContainerType>
225{
226 using container_type = ContainerType;
238 ChebyshevPreconditioner( Matrix op, const ContainerType& copyable, value_type ev_min,
239 value_type ev_max, unsigned degree):
240 m_op(op), m_ch( copyable),
241 m_ev_min(ev_min), m_ev_max(ev_max), m_degree(degree){}
242
243 template<class ContainerType0, class ContainerType1>
244 void symv( const ContainerType0& x, ContainerType1& y)
245 {
246 //m_ch.solve( m_op, y, x, m_op.precond(), m_ev_min, m_ev_max, m_degree+1, true);
247 m_ch.solve( m_op, y, x, m_ev_min, m_ev_max, m_degree+1, true);
248 }
249 private:
250 Matrix m_op;
252 value_type m_ev_min, m_ev_max;
253 unsigned m_degree;
254};
255
269template<class Matrix, class ContainerType>
271{
272 using container_type = ContainerType;
286 ModifiedChebyshevPreconditioner( Matrix op, const ContainerType& copyable, value_type ev_min,
287 value_type ev_max, unsigned degree):
288 m_op(op), m_ax(copyable), m_z1(m_ax), m_z2(m_ax),
289 m_ev_min(ev_min), m_ev_max(ev_max), m_degree(degree){}
290
291 template<class ContainerType0, class ContainerType1>
292 void symv( const ContainerType0& x, ContainerType1& y)
293 {
294 value_type theta = (m_ev_min+m_ev_max)/2., delta = (m_ev_max-m_ev_min)/2.;
295 value_type c_k = 1./sqrt(m_ev_min*m_ev_max);
296 dg::blas1::axpby( c_k/2., x, 0., y);
297 if( m_degree == 0) return;
298 dg::blas2::symv( m_op, x, m_ax);
299 dg::blas1::axpby( 1./delta, m_ax, -theta/delta, x, m_z1); //T_{k-1} x
300 c_k *= (sqrt( m_ev_min/m_ev_max) - 1.)/(sqrt(m_ev_min/m_ev_max)+1);
301 dg::blas1::axpby( c_k, m_z1, 1., y);
302 if( m_degree == 1) return;
303 dg::blas1::copy( x, m_z2); //T_{k-2} x
304 for( unsigned i=1; i<m_degree; i++)
305 {
306 dg::blas2::symv( m_op, m_z1, m_ax);
307 dg::blas1::axpby( 1./delta, m_ax, -theta/delta, m_z1, m_ax); //Z T_{k-1}
308 dg::blas1::axpby( 2., m_ax, -1., m_z2, m_z2); //T_k
309 c_k *= (sqrt( m_ev_min/m_ev_max) - 1.)/(sqrt(m_ev_min/m_ev_max)+1);
310 dg::blas1::axpby( c_k, m_z2, 1., y);
311 using std::swap;
312 swap(m_z1,m_z2);
313 }
314 }
315 private:
316 Matrix m_op;
317 ContainerType m_ax, m_z1, m_z2;
318 value_type m_ev_min, m_ev_max;
319 unsigned m_degree;
320};
321
339template<class Matrix, class InnerPreconditioner, class ContainerType>
341{
342 using container_type = ContainerType;
353 LeastSquaresPreconditioner( Matrix op, InnerPreconditioner P, const ContainerType& copyable, value_type ev_max, unsigned degree):
354 m_op(op), m_p(P), m_z(copyable),
355 m_ev_max( ev_max), m_degree(degree){
356 m_c = coeffs(degree);
357 }
360 const ContainerType& copyable()const{ return m_z;}
361
362 template<class ContainerType0, class ContainerType1>
363 void symv( const ContainerType0& x, ContainerType1& y)
364 {
365 //Horner scheme
366 dg::blas1::axpby( m_c[m_degree],x, 0., m_z);
367 for( int i=m_degree-1; i>=0; i--)
368 {
369 //dg::blas1::copy( m_z, y);
370 dg::blas2::symv( m_p, m_z, y);
371 dg::blas2::symv( m_op, y, m_z);
372 dg::blas1::axpby( m_c[i], x, +4./m_ev_max, m_z);
373 }
374 //dg::blas1::copy( m_z, y);
375 dg::blas2::symv( m_p, m_z, y);
376 }
377 private:
378 std::vector<value_type> coeffs( unsigned degree){
379 switch( degree){
380 case 0: return {1.};
381 case 1: return {5., -1.};
382 case 2: return { 14., -7., 1.};
383 case 3: return {30., -27., 9., -1.};
384 case 4: return {55., -77., 44., -11., 1.};
385 case 5: return {91., -182., 156., -65., 13., -1. };
386 case 6: return {140., -378., 450., -275., 90., -15., 1. };
387 case 7: return {204., -714.,1122., -935., 442., -119., 17., -1.};
388 case 8: return {285.,-1254., 2508., -2717., 1729., -665., 152., -19., 1.};
389 case 9: return {385., -2079., 5148.,-7007.,5733.,-2940.,952.,-189.,21.,-1.};
390 default:
391 if (degree > 10)
392 std::cerr << "WARNING: LeastSquares Case "<<degree<<" not implemented. Taking 10 instead!\n";
393 return {506., -3289., 9867.,-16445.,16744.,-10948.,4692.,-1311.,230.,-23.,1. };
394 };
395 }
396 std::vector<value_type> m_c;
397 Matrix m_op;
398 InnerPreconditioner m_p;
399 ContainerType m_z;
400 value_type m_ev_max;
401 unsigned m_degree;
402};
403
405template<class M, class V>
406struct TensorTraits<ChebyshevPreconditioner<M,V>>
407{
408 using value_type = get_value_type<V>;
409 using tensor_category = SelfMadeMatrixTag;
410};
411template<class M, class V>
412struct TensorTraits<ModifiedChebyshevPreconditioner<M,V>>
413{
414 using value_type = get_value_type<V>;
415 using tensor_category = SelfMadeMatrixTag;
416};
417template<class M, class P, class V>
418struct TensorTraits<LeastSquaresPreconditioner<M,P,V>>
419{
420 using value_type = get_value_type<V>;
421 using tensor_category = SelfMadeMatrixTag;
422};
423
425
426//template<class Matrix, class Container>
427//struct WrapperSpectralShift
428//{
429// WrapperSpectralShift( Matrix& op, value_type ev_max):
430// m_op(op), m_ev_max(ev_max){}
431// template<class ContainerType0, class ContainerType1>
432// void symv( const ContainerType0& x, ContainerType1& y)
433// {
434// dg::blas1::axpby( m_ev_max, x, 0., y);
435// dg::blas2::symv( -1., m_op, x, 1., y);
436// }
437//
438// private:
439// Matrix& m_op;
440// value_type m_ev_max;
441//
442//};
443//template<class M, class V>
444//struct TensorTraits<detail::WrapperSpectralShift<M,V>>
445//{
446// using value_type = get_value_type<V>;
447// using tensor_category = SelfMadeMatrixTag;
448//};
449
450} //namespace dg
451
452#endif // _DG_CHEB_
Preconditioned Chebyshev iteration for solving .
Definition: chebyshev.h:57
get_value_type< ContainerType > value_type
Definition: chebyshev.h:60
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition: chebyshev.h:68
void solve(MatrixType0 &&A, ContainerType0 &x, const ContainerType1 &b, MatrixType1 &&P, value_type min_ev, value_type max_ev, unsigned num_iter, bool x_is_zero=false)
Solve the system using num_iter Preconditioned Chebyshev iteration.
Definition: chebyshev.h:159
ChebyshevIteration(const ContainerType &copyable)
Allocate memory for the pcg method.
Definition: chebyshev.h:64
ContainerType container_type
Definition: chebyshev.h:59
ChebyshevIteration()=default
Allocate nothing, Call construct method before usage.
void construct(const ContainerType &copyable)
Allocate memory for the pcg method.
Definition: chebyshev.h:75
void solve(MatrixType &&A, ContainerType0 &x, const ContainerType1 &b, value_type min_ev, value_type max_ev, unsigned num_iter, bool x_is_zero=false)
Solve the system using num_iter Chebyshev iteration.
Definition: chebyshev.h:101
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
void axpbypgz(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, const ContainerType2 &y, get_value_type< ContainerType > gamma, ContainerType &z)
Definition: blas1.h:265
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 evaluate(ContainerType &y, BinarySubroutine f, Functor g, const ContainerType0 &x0, const ContainerTypes &...xs)
Definition: blas1.h:556
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
Definition: blas2.h:287
@ y
y direction
@ x
x direction
Operator< real_type > delta(unsigned n)
Create the unit matrix.
Definition: operator.h:514
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...
Chebyshev Polynomial Preconditioner .
Definition: chebyshev.h:225
ChebyshevPreconditioner(Matrix op, const ContainerType &copyable, value_type ev_min, value_type ev_max, unsigned degree)
Construct the k-th Chebyshev Polynomial.
Definition: chebyshev.h:238
ContainerType container_type
Definition: chebyshev.h:226
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition: chebyshev.h:244
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition: chebyshev.h:227
Least Squares Polynomial Preconditioner .
Definition: chebyshev.h:341
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition: chebyshev.h:360
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition: chebyshev.h:343
ContainerType container_type
Definition: chebyshev.h:342
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition: chebyshev.h:363
LeastSquaresPreconditioner(Matrix op, InnerPreconditioner P, const ContainerType &copyable, value_type ev_max, unsigned degree)
Construct k-th Least Squares Polynomial.
Definition: chebyshev.h:353
Approximate inverse Chebyshev Polynomial Preconditioner .
Definition: chebyshev.h:271
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition: chebyshev.h:292
ContainerType container_type
Definition: chebyshev.h:272
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition: chebyshev.h:273
ModifiedChebyshevPreconditioner(Matrix op, const ContainerType &copyable, value_type ev_min, value_type ev_max, unsigned degree)
Construct the k-th Chebyshev Polynomial approximate.
Definition: chebyshev.h:286
Definition: subroutines.h:108
NotATensorTag tensor_category
Definition: tensor_traits.h:33
void value_type
Definition: tensor_traits.h:32
Definition: subroutines.h:22