Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
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
53template< class ContainerType>
55{
56 public:
57 using container_type = ContainerType;
60 ChebyshevIteration() = default;
62 ChebyshevIteration( const ContainerType& copyable):
63 m_ax(copyable), m_z( m_ax), m_xm1(m_ax){}
66 const ContainerType& copyable()const{ return m_ax;}
67
73 void construct( const ContainerType& copyable) {
74 m_xm1 = m_z = m_ax = copyable;
75 }
97 template< class MatrixType, class ContainerType0, class ContainerType1>
98 void solve( MatrixType&& A, ContainerType0& x, const ContainerType1& b,
99 value_type min_ev, value_type max_ev, unsigned num_iter, bool x_is_zero = false)
100 {
101 if( num_iter == 0)
102 return;
103 assert ( min_ev < max_ev);
104 value_type theta = (min_ev+max_ev)/2., delta = (max_ev-min_ev)/2.;
105 value_type rhokm1 = delta/theta, rhok=0;
106 if( !x_is_zero)
107 {
108 dg::blas1::copy( x, m_xm1); //x_{k-1}
109 dg::blas2::symv( std::forward<MatrixType>(A), x, m_ax);
110 dg::blas1::axpbypgz( 1./theta, b, -1./theta, m_ax, 1., x); //x_1
111 }
112 else
113 {
114 dg::blas1::copy( 0., m_xm1); //x_{k-1}
115 dg::blas1::axpby( 1./theta, b, 0., x); //x_1
116 }
117 for ( unsigned k=1; k<num_iter; k++)
118 {
119 rhok = 1./(2.*theta/delta - rhokm1);
120 dg::blas2::symv( std::forward<MatrixType>(A), x, m_ax);
122 1.+rhok*rhokm1, x,
123 -rhok*rhokm1, m_xm1,
124 2.*rhok/delta, b,
125 -2.*rhok/delta, m_ax
126 );
127 using std::swap;
128 swap( x, m_xm1);
129 rhokm1 = rhok;
130 }
131 }
154 template< class MatrixType0, class MatrixType1, class ContainerType0, class ContainerType1>
155 void solve( MatrixType0&& A, ContainerType0& x, const ContainerType1& b,
156 MatrixType1&& P, value_type min_ev, value_type max_ev, unsigned num_iter,
157 bool x_is_zero = false)
158 {
159 if( num_iter == 0)
160 return;
161 assert ( min_ev < max_ev);
162 value_type theta = (min_ev+max_ev)/2., delta = (max_ev-min_ev)/2.;
163 value_type rhokm1 = delta/theta, rhok=0;
164 if( !x_is_zero)
165 {
166 dg::blas1::copy( x, m_xm1); //x_{k-1}
167 dg::blas2::symv( std::forward<MatrixType0>(A), x, m_ax);
168 dg::blas1::axpby( 1., b, -1., m_ax); //r_0
169 dg::blas2::symv( std::forward<MatrixType1>(P), m_ax, m_z);
170 dg::blas1::axpby( 1./theta, m_z, 1., x); //x_{k-1}
171 }
172 else
173 {
174 dg::blas2::symv( std::forward<MatrixType1>(P), b, x);
175 if( num_iter == 1) return;
176 dg::blas1::scal( m_xm1, 0.);
177 dg::blas1::scal( x, 1./theta);
178 }
179 for ( unsigned k=1; k<num_iter; k++)
180 {
181 rhok = 1./(2.*theta/delta - rhokm1);
182 dg::blas2::symv( std::forward<MatrixType0>(A), x, m_ax);
183 dg::blas1::axpby( 1., b, -1., m_ax); //r_k
184 dg::blas2::symv( P, m_ax, m_z);
186 1.+rhok*rhokm1, x,
187 2.*rhok/delta, m_z,
188 -rhok*rhokm1, m_xm1
189 );
190 using std::swap;
191 swap( x, m_xm1);
192 rhokm1 = rhok;
193 }
194 }
195 private:
196 ContainerType m_ax, m_z, m_xm1;
197};
198
219template<class Matrix, class ContainerType>
221{
222 using container_type = ContainerType;
233 ChebyshevPreconditioner( Matrix op, const ContainerType& copyable, value_type ev_min,
234 value_type ev_max, unsigned degree):
235 m_op(op), m_ch( copyable),
236 m_ev_min(ev_min), m_ev_max(ev_max), m_degree(degree){}
237
238 template<class ContainerType0, class ContainerType1>
239 void symv( const ContainerType0& x, ContainerType1& y)
240 {
241 //m_ch.solve( m_op, y, x, m_op.precond(), m_ev_min, m_ev_max, m_degree+1, true);
242 m_ch.solve( m_op, y, x, m_ev_min, m_ev_max, m_degree+1, true);
243 }
244 private:
245 Matrix m_op;
247 value_type m_ev_min, m_ev_max;
248 unsigned m_degree;
249};
250
264template<class Matrix, class ContainerType>
266{
267 using container_type = ContainerType;
280 ModifiedChebyshevPreconditioner( Matrix op, const ContainerType& copyable, value_type ev_min,
281 value_type ev_max, unsigned degree):
282 m_op(op), m_ax(copyable), m_z1(m_ax), m_z2(m_ax),
283 m_ev_min(ev_min), m_ev_max(ev_max), m_degree(degree){}
284
285 template<class ContainerType0, class ContainerType1>
286 void symv( const ContainerType0& x, ContainerType1& y)
287 {
288 value_type theta = (m_ev_min+m_ev_max)/2., delta = (m_ev_max-m_ev_min)/2.;
289 value_type c_k = 1./sqrt(m_ev_min*m_ev_max);
290 dg::blas1::axpby( c_k/2., x, 0., y);
291 if( m_degree == 0) return;
292 dg::blas2::symv( m_op, x, m_ax);
293 dg::blas1::axpby( 1./delta, m_ax, -theta/delta, x, m_z1); //T_{k-1} x
294 c_k *= (sqrt( m_ev_min/m_ev_max) - 1.)/(sqrt(m_ev_min/m_ev_max)+1);
295 dg::blas1::axpby( c_k, m_z1, 1., y);
296 if( m_degree == 1) return;
297 dg::blas1::copy( x, m_z2); //T_{k-2} x
298 for( unsigned i=1; i<m_degree; i++)
299 {
300 dg::blas2::symv( m_op, m_z1, m_ax);
301 dg::blas1::axpby( 1./delta, m_ax, -theta/delta, m_z1, m_ax); //Z T_{k-1}
302 dg::blas1::axpby( 2., m_ax, -1., m_z2, m_z2); //T_k
303 c_k *= (sqrt( m_ev_min/m_ev_max) - 1.)/(sqrt(m_ev_min/m_ev_max)+1);
304 dg::blas1::axpby( c_k, m_z2, 1., y);
305 using std::swap;
306 swap(m_z1,m_z2);
307 }
308 }
309 private:
310 Matrix m_op;
311 ContainerType m_ax, m_z1, m_z2;
312 value_type m_ev_min, m_ev_max;
313 unsigned m_degree;
314};
315
333template<class Matrix, class InnerPreconditioner, class ContainerType>
335{
336 using container_type = ContainerType;
347 LeastSquaresPreconditioner( Matrix op, InnerPreconditioner P, const ContainerType& copyable, value_type ev_max, unsigned degree):
348 m_op(op), m_p(P), m_z(copyable),
349 m_ev_max( ev_max), m_degree(degree){
350 m_c = coeffs(degree);
351 }
354 const ContainerType& copyable()const{ return m_z;}
355
356 template<class ContainerType0, class ContainerType1>
357 void symv( const ContainerType0& x, ContainerType1& y)
358 {
359 //Horner scheme
360 dg::blas1::axpby( m_c[m_degree],x, 0., m_z);
361 for( int i=m_degree-1; i>=0; i--)
362 {
363 //dg::blas1::copy( m_z, y);
364 dg::blas2::symv( m_p, m_z, y);
365 dg::blas2::symv( m_op, y, m_z);
366 dg::blas1::axpby( m_c[i], x, +4./m_ev_max, m_z);
367 }
368 //dg::blas1::copy( m_z, y);
369 dg::blas2::symv( m_p, m_z, y);
370 }
371 private:
372 std::vector<value_type> coeffs( unsigned degree){
373 switch( degree){
374 case 0: return {1.};
375 case 1: return {5., -1.};
376 case 2: return { 14., -7., 1.};
377 case 3: return {30., -27., 9., -1.};
378 case 4: return {55., -77., 44., -11., 1.};
379 case 5: return {91., -182., 156., -65., 13., -1. };
380 case 6: return {140., -378., 450., -275., 90., -15., 1. };
381 case 7: return {204., -714.,1122., -935., 442., -119., 17., -1.};
382 case 8: return {285.,-1254., 2508., -2717., 1729., -665., 152., -19., 1.};
383 case 9: return {385., -2079., 5148.,-7007.,5733.,-2940.,952.,-189.,21.,-1.};
384 default:
385 if (degree > 10)
386 std::cerr << "WARNING: LeastSquares Case "<<degree<<" not implemented. Taking 10 instead!\n";
387 return {506., -3289., 9867.,-16445.,16744.,-10948.,4692.,-1311.,230.,-23.,1. };
388 };
389 }
390 std::vector<value_type> m_c;
391 Matrix m_op;
392 InnerPreconditioner m_p;
393 ContainerType m_z;
394 value_type m_ev_max;
395 unsigned m_degree;
396};
397
399template<class M, class V>
400struct TensorTraits<ChebyshevPreconditioner<M,V>>
401{
403 using tensor_category = SelfMadeMatrixTag;
404};
405template<class M, class V>
406struct TensorTraits<ModifiedChebyshevPreconditioner<M,V>>
407{
409 using tensor_category = SelfMadeMatrixTag;
410};
411template<class M, class P, class V>
412struct TensorTraits<LeastSquaresPreconditioner<M,P,V>>
413{
415 using tensor_category = SelfMadeMatrixTag;
416};
417
419
420//template<class Matrix, class Container>
421//struct WrapperSpectralShift
422//{
423// WrapperSpectralShift( Matrix& op, value_type ev_max):
424// m_op(op), m_ev_max(ev_max){}
425// template<class ContainerType0, class ContainerType1>
426// void symv( const ContainerType0& x, ContainerType1& y)
427// {
428// dg::blas1::axpby( m_ev_max, x, 0., y);
429// dg::blas2::symv( -1., m_op, x, 1., y);
430// }
431//
432// private:
433// Matrix& m_op;
434// value_type m_ev_max;
435//
436//};
437//template<class M, class V>
438//struct TensorTraits<detail::WrapperSpectralShift<M,V>>
439//{
440// using value_type = get_value_type<V>;
441// using tensor_category = SelfMadeMatrixTag;
442//};
443
444} //namespace dg
445
446#endif // _DG_CHEB_
Preconditioned Chebyshev iteration for solving .
Definition chebyshev.h:55
get_value_type< ContainerType > value_type
Definition chebyshev.h:58
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition chebyshev.h:66
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:155
ChebyshevIteration(const ContainerType &copyable)
Allocate memory for the pcg method.
Definition chebyshev.h:62
ContainerType container_type
Definition chebyshev.h:57
ChebyshevIteration()=default
Allocate nothing, Call construct method before usage.
void construct(const ContainerType &copyable)
Allocate memory for the pcg method.
Definition chebyshev.h:73
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:98
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition blas1.h:243
void axpbypgz(value_type alpha, const ContainerType1 &x, value_type1 beta, const ContainerType2 &y, value_type2 gamma, ContainerType &z)
Definition blas1.h:337
void axpby(value_type alpha, const ContainerType1 &x, value_type1 beta, ContainerType &y)
Definition blas1.h:306
void evaluate(ContainerType &y, BinarySubroutine f, Functor g, const ContainerType0 &x0, const ContainerTypes &...xs)
Definition blas1.h:612
void scal(ContainerType &x, value_type alpha)
Definition blas1.h:263
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
Definition blas2.h:331
@ y
y direction
@ x
x direction
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition tensor_traits.h:45
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Chebyshev Polynomial Preconditioner .
Definition chebyshev.h:221
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:233
ContainerType container_type
Definition chebyshev.h:222
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition chebyshev.h:239
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition chebyshev.h:223
Ell Sparse Block Matrix format.
Definition sparseblockmat.h:46
Least Squares Polynomial Preconditioner .
Definition chebyshev.h:335
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition chebyshev.h:354
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition chebyshev.h:337
ContainerType container_type
Definition chebyshev.h:336
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition chebyshev.h:357
LeastSquaresPreconditioner(Matrix op, InnerPreconditioner P, const ContainerType &copyable, value_type ev_max, unsigned degree)
Construct k-th Least Squares Polynomial.
Definition chebyshev.h:347
Approximate inverse Chebyshev Polynomial Preconditioner .
Definition chebyshev.h:266
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition chebyshev.h:286
ContainerType container_type
Definition chebyshev.h:267
get_value_type< ContainerType > value_type
value type of the ContainerType class
Definition chebyshev.h:268
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:280
Definition subroutines.h:124
NotATensorTag tensor_category
Definition tensor_traits.h:40
Definition subroutines.h:22
double value_type