Extension: Matrix functions
#include "dg/matrix/matrix.h"
Loading...
Searching...
No Matches
tridiaginv.h
Go to the documentation of this file.
1#pragma once
2
3#include <boost/math/special_functions.hpp> // has to be included before lapack in certain versions
4#include "dg/algorithm.h"
5
6#include "functors.h"
11namespace dg{
12namespace mat{
14namespace lapack
15{
16// MW: Update 27.5.2025
17// Unfortunately, the CMake support for LAPACKE is rather not straightforward
18// while LAPACK is supported out of the box with find_package( LAPACK)
19// so we rather call the fortran functions from C directly ourselves.
20//
21// This is how you add new routines:
22// 1. Go find relevant Fortran routine ( usually there are separate routine for
23// each value type; single, double ,complex )
24// FORTRAN https://www.netlib.org/lapack/explore-html/index.html
25//
26// 2. Call the fortran function from C packaged in a nice C++ interface!
27// We here follow
28// https://scicomp.stackexchange.com/questions/26395/how-to-start-using-lapack-in-c
29// 2.1 Add the extern "C" binding below, where all parameters are pointers
30// 2.2 When matrices are involved note that the Fortran ordering is "column
31// major", which is the transpose of how e.g. our SquareMatrix is ordered)
32// 2.3. Replace all arrays with a ContainerType in our interface
33// 2.4. Use C++-17 if constexpr to dispatch value type
34//
35extern "C" {
36extern void dstev_(char*,int*,double*,double*,double*,int*,double*,int*);
37extern void sstev_(char*,int*,float*,float*,float*,int*,float*,int*);
38extern void dsygv_(int*,char*,char*,int*,double*,int*,double*,int*,double*,double*,int*,int*);
39extern void ssygv_(int*,char*,char*,int*,float*,int*,float*,int*,float*,float*,int*,int*);
40}
41// Compute Eigenvalues and, optionally, Eigenvectors of a real symmetric tridiagonal matrix A
42template<class ContainerType0, class ContainerType1, class ContainerType2, class ContainerType3>
43void stev(
44 char job, // 'N' Compute Eigenvalues only, 'V' Compute Eigenvalues and Eigenvectors
45 ContainerType0& D, // diagonal of T on input, Eigenvalues (in ascending order) on output
46 ContainerType1& E, // subdiagonal of T on input |size D.size()-1 ; in E[0] - E[D.size()-2]|; destroyed on output
47 ContainerType2& Z, // IF job = 'V' && column major then the i-th column contains i-th EV, if job = 'N' not referenced
48 ContainerType3& work // If job = 'V' needs size max( 1, 2*D.size() - 2), else not referenced
49 )
50{
52 static_assert( std::is_same_v<value_type, double> or std::is_same_v<value_type, float>,
53 "Value type must be either float or double");
54 static_assert( std::is_same_v<dg::get_value_type<ContainerType1>, value_type> &&
55 std::is_same_v<dg::get_value_type<ContainerType2>, value_type> &&
56 std::is_same_v<dg::get_value_type<ContainerType3>, value_type>,
57 "All Vectors must have same value type");
58 static_assert( std::is_same_v<dg::get_execution_policy<ContainerType0>, dg::SerialTag> &&
59 std::is_same_v<dg::get_execution_policy<ContainerType1>, dg::SerialTag> &&
60 std::is_same_v<dg::get_execution_policy<ContainerType2>, dg::SerialTag> &&
61 std::is_same_v<dg::get_execution_policy<ContainerType3>, dg::SerialTag>,
62 "All Vectors must have serial execution policy");
63
64 // job = 'N' Compute Eigenvalues only
65 // job = 'V' Compute Eigenvalues and Eigenvectors
66 int N = D.size();
67 value_type * D_ptr = thrust::raw_pointer_cast( &D[0]);
68 value_type * E_ptr = thrust::raw_pointer_cast( &E[0]);
69 value_type * Z_ptr = nullptr;
70 int ldz = N;
71 value_type * work_ptr = nullptr;
72 if( job == 'V')
73 {
74 Z_ptr = thrust::raw_pointer_cast( &Z[0]);
75 work_ptr = thrust::raw_pointer_cast( &work[0]);
76 }
77
78 int info;
79 if constexpr ( std::is_same_v<value_type, double>)
80 dstev_( &job, &N, D_ptr, E_ptr, Z_ptr, &ldz, work_ptr, &info);
81 else if constexpr ( std::is_same_v<value_type, float>)
82 sstev_( &job, &N, D_ptr, E_ptr, Z_ptr, ldz, work_ptr, &info);
83 if( info != 0)
84 {
85 throw dg::Error( dg::Message(_ping_) << "stev failed with error code "<<info<<"\n");
86 }
87}
88
89
90// Look for dsygv on Lapack docu!
91// Compute Eigenvalues and, optionally, Eigenvectors of a real symmetric matrix system A x = lambda B x
92template<class ContainerType0, class ContainerType1, class ContainerType2, class ContainerType3>
93void sygv(
94 int itype, // 1: A*x = (\Lambda)*B*x, 2: A*B*x = (\Lambda)*x, 3: B*A*x = (\Lambda)*x
95 char jobz, // 'N' Compute Eigenvalues only, 'V' Compute Eigenvalues and Eigenvectors
96 char uplo, // 'U' Upper triangles of A and B are stored; 'L' Lower triangles of A and B
97 int N,
98 ContainerType0& A, // matrix A [LDA rows, N cols], contains Eigenvecs on output if requested
99 int lda,
100 ContainerType1& B, // matrix B [LDB rows, N cols], destroyed on output
101 int ldb,
102 ContainerType2& W, // [out] Eigenvalues in ascending order
103 ContainerType3& work // Workspace Size 3*N-1
104 )
105{
107 static_assert( std::is_same_v<value_type, double> or std::is_same_v<value_type, float>,
108 "Value type must be either float or double");
109 static_assert( std::is_same_v<dg::get_value_type<ContainerType1>, value_type> &&
110 std::is_same_v<dg::get_value_type<ContainerType2>, value_type> &&
111 std::is_same_v<dg::get_value_type<ContainerType3>, value_type>,
112 "All Vectors must have same value type");
113 static_assert( std::is_same_v<dg::get_execution_policy<ContainerType0>, dg::SerialTag> &&
114 std::is_same_v<dg::get_execution_policy<ContainerType1>, dg::SerialTag> &&
115 std::is_same_v<dg::get_execution_policy<ContainerType2>, dg::SerialTag> &&
116 std::is_same_v<dg::get_execution_policy<ContainerType3>, dg::SerialTag>,
117 "All Vectors must have serial execution policy");
118
119 // jobz = 'N' Compute Eigenvalues only
120 // jobz = 'V' Compute Eigenvalues and Eigenvectors
121 value_type * A_ptr = thrust::raw_pointer_cast( &A[0]);
122 value_type * B_ptr = thrust::raw_pointer_cast( &B[0]);
123 value_type * W_ptr = thrust::raw_pointer_cast( &W[0]);
124 value_type * work_ptr = thrust::raw_pointer_cast( &work[0]);
125 int work_size = (int)work.size();
126
127 int info;
128 if constexpr ( std::is_same_v<value_type, double>)
129 dsygv_( &itype, &jobz, &uplo, &N, A_ptr, &lda, B_ptr, &ldb, W_ptr, work_ptr, &work_size, &info);
130 else if constexpr ( std::is_same_v<value_type, float>)
131 ssygv_( &itype, &jobz, &uplo, &N, A_ptr, &lda, B_ptr, &ldb, W_ptr, work_ptr, &work.size, &info);
132 if( info != 0)
133 {
134 throw dg::Error( dg::Message(_ping_) << "sygv failed with error code "<<info<<"\n");
135 }
136}
137
138
139
140
141}
143
146
158template<class value_type>
159value_type compute_Tinv_m1( const dg::TriDiagonal<thrust::host_vector<value_type>>
160 & T, unsigned size)
161{
162 // P = Plus diagonal
163 // O = zerO diagonal
164 // M = Minus diagonal
165 value_type ci = T.P[0]/T.O[0], ciold = 0.;
166 value_type di = 1./T.O[0], diold = 0.;
167 for( unsigned i=1; i<size; i++)
168 {
169 ciold = ci, diold = di;
170 ci = T.P[i]/ ( T.O[i]-T.M[i]*ciold);
171 di = -T.M[i]*diold/(T.O[i]-T.M[i]*ciold);
172 }
173 return di;
174}
187template<class value_type>
188void compute_Tinv_y( const dg::TriDiagonal<thrust::host_vector<value_type>>
189 & T,
190 thrust::host_vector<value_type>& x,
191 const thrust::host_vector<value_type>& y, value_type a = 1.,
192 value_type d = 0.)
193{
194 unsigned size = y.size();
195 x.resize(size);
196 thrust::host_vector<value_type> ci(size), di(size);
197 ci[0] = a*T.P[0]/( a*T.O[0] + d);
198 di[0] = y[0]/( a*T.O[0] + d);
199 for( unsigned i=1; i<size; i++)
200 {
201 ci[i] = a*T.P[i]/ ( a*T.O[i] + d -a*T.M[i]*ci[i-1]);
202 di[i] = (y[i]-a*T.M[i]*di[i-1])/(a*T.O[i] + d
203 -a*T.M[i]*ci[i-1]);
204 }
205 x[size-1] = di[size-1];
206 for( int i=size-2; i>=0; i--)
207 x[i] = di[i] - ci[i]*x[i+1];
208}
209
210
220template< class real_type>
222{
223 public:
224 using value_type = real_type;
232 TridiagInvHMGTI(const thrust::host_vector<real_type>& copyable)
233 {
234 m_size = copyable.size();
235 m_alphas.assign(m_size+1,0.);
236 m_betas.assign(m_size+1,0.);
237 }
243 TridiagInvHMGTI(unsigned size)
244 {
245 m_size = size;
246 m_alphas.assign(m_size+1,0.);
247 m_betas.assign(m_size+1,0.);
248 }
254 void resize(unsigned new_size) {
255 m_size = new_size;
256 m_alphas.resize(m_size+1,0.);
257 m_betas.resize(m_size+1,0.);
258 }
266 void operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T, dg::SquareMatrix<real_type>& Tinv)
267 {
268 this->operator()(
269 T.O, // 0 diagonal
270 T.P, // +1 diagonal
271 T.M, // -1 diagonal
272 Tinv);
273 }
280 dg::SquareMatrix<real_type> operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T)
281 {
283 this->operator()( T, Tinv);
284 return Tinv;
285 }
296 template<class ContainerType0, class ContainerType1, class ContainerType2>
297 void operator()(const ContainerType0& a, const ContainerType1& b,
298 const ContainerType2& c, dg::SquareMatrix<real_type>& Tinv)
299 {
300 unsigned ss = m_size;
301 Tinv.resize(ss);
302 if( ss == 1)
303 {
304 Tinv(0,0) = 1./b[0];
305 return;
306 }
307 //fill alphas
308 m_alphas[0]=1.0;
309 m_alphas[1]=a[0];
310 for( unsigned i = 2; i<ss+1; i++)
311 {
312 m_alphas[i] = a[i-1]*m_alphas[i-1] - c[i-1]*b[i-2]*m_alphas[i-2];
313 if (m_alphas[i] ==0 && i<ss) {
314 throw dg::Error( dg::Message(_ping_) << "# Failure in alpha["<<i<<"] !");
315 }
316 }
317 if (m_alphas[ss] ==0)
318 throw dg::Error( dg::Message(_ping_) << "# No Inverse of tridiagonal matrix exists !");
319
320 //fill betas
321 m_betas[ss]=1.0;
322 m_betas[ss-1]=a[ss-1];
323 m_betas[0] = m_alphas[ss];
324 for( int i = ss-2; i>0; i--)
325 {
326 m_betas[i] = a[i]*m_betas[i+1] - c[i+1]*b[i]*m_betas[i+2];
327 if (m_betas[i] ==0)
328 {
329 throw dg::Error( dg::Message(_ping_) << "# Failure in beta["<<i<<"] !");
330 }
331 }
332 //Diagonal entries
333 Tinv(0, 0) = 1.0/(a[0]-c[1]*b[0]*m_betas[2]/m_betas[1]);
334 Tinv(ss-1, ss-1) = 1.0/(a[ss-1] -
335 c[ss-1]*b[ss-2]*m_alphas[ss-2]/m_alphas[ss-1]);
336 for( unsigned i=1; i<ss-1; i++)
337 {
338 Tinv( i,i) =
339 1.0/(a[i]-c[i]*b[i-1]*m_alphas[i-1]/m_alphas[i]
340 -c[i+1]*b[i]*m_betas[i+2]/m_betas[i+1]);
341 }
342 //Off-diagonal entries
343 for( unsigned i=0; i<ss; i++)
344 {
345 for( unsigned j=0; j<ss; j++)
346 {
347 if (i<j) {
348 Tinv(i, j) =
349 sign(j-i)*std::accumulate(std::next(b.begin(),i),
350 std::next(b.begin(),j), 1.,
351 std::multiplies<value_type>())*
352 m_alphas[i]/m_alphas[j]*Tinv(j,j);
353 }
354 else if (i>j)
355 {
356 Tinv(i, j) =
357 sign(i-j)*std::accumulate(std::next(c.begin(),j+1),
358 std::next(c.begin(),i+1), 1.,
359 std::multiplies<value_type>())*
360 m_betas[i+1]/m_betas[j+1]*Tinv(j,j);
361 }
362 }
363 }
364 }
365 private:
367 int sign(unsigned i)
368 {
369 if (i%2==0) return 1;
370 else return -1;
371 }
372 thrust::host_vector<real_type> m_alphas, m_betas;
373 unsigned m_size;
374};
375
376
385template< class real_type>
387{
388 public:
389 using value_type = real_type;
397 TridiagInvDF(const thrust::host_vector<real_type>& copyable)
398 {
399 m_size = copyable.size();
400 m_phi.assign(m_size,0.);
401 m_theta.assign(m_size,0.);
402 }
408 TridiagInvDF(unsigned size)
409 {
410 m_size = size;
411 m_phi.assign(m_size,0.);
412 m_theta.assign(m_size,0.);
413 }
419 void resize(unsigned new_size) {
420 m_size = new_size;
421 m_phi.resize(m_size,0.);
422 m_theta.resize(m_size,0.);
423 }
431 void operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T, dg::SquareMatrix<real_type>& Tinv)
432 {
433 this->operator()(
434 T.O, // 0 diagonal
435 T.P, // +1 diagonal
436 T.M, // -1 diagonal
437 Tinv);
438 }
445 dg::SquareMatrix<real_type> operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T)
446 {
448 this->operator()( T, Tinv);
449 return Tinv;
450 }
461 template<class ContainerType0, class ContainerType1, class ContainerType2>
462 void operator()(const ContainerType0& a, const ContainerType1& b,
463 const ContainerType2& c, dg::SquareMatrix<real_type>& Tinv)
464 {
465 Tinv.resize(m_size);
466 value_type helper = 0.0;
467 //fill phi values
468 m_phi[0] = - b[0]/a[0];
469 for( unsigned i = 1; i<m_size; i++)
470 {
471 helper = m_phi[i-1]* c[i] + a[i];
472 if (helper==0) throw dg::Error( dg::Message(_ping_)<< "Failure: Division by zero\n");
473 else m_phi[i] = -b[i]/helper;
474 }
475// m_phi[m_size] = 0.0;
476
477 //fill theta values
478 if (m_size == 1) m_theta[m_size-1] = 0.0;
479 else
480 {
481 m_theta[m_size-1] = - c[m_size-1]/a[m_size-1];
482 for( int i = m_size-2; i>=0; i--)
483 {
484 helper = m_theta[i+1]*b[i] + a[i];
485 if (helper==0) throw dg::Error( dg::Message(_ping_)<< "Failure: Division by zero\n");
486 else m_theta[i] = -c[i]/helper;
487 }
488 }
489// m_theta[0] = 0.0;
490 //Diagonal entries
491 helper = a[0] + b[0]* m_theta[1];
492 if (helper==0) throw dg::Error( dg::Message(_ping_)<< "Failure: No inverse exists\n");
493 else Tinv(0,0) = 1.0/helper;
494
495 if (m_size == 1) helper = a[m_size-1];
496 else helper = a[m_size-1] + c[m_size-1]*m_phi[m_size-2];
497
498 if (helper==0) throw dg::Error( dg::Message(_ping_)<< "Failure: No inverse exists\n");
499 else Tinv( m_size -1 , m_size - 1) = 1.0/helper;
500
501 for( unsigned i=1; i<m_size-1; i++)
502 {
503 helper = a[i] + c[i]*m_phi[i-1] + b[i]* m_theta[i+1];
504 if (helper==0) throw dg::Error( dg::Message(_ping_)<< "Failure: No inverse exists\n");
505 else Tinv(i,i) = 1.0/helper;
506 }
507 //Off-diagonal entries
508 for( unsigned j=0; j<m_size-1; j++) //row index
509 {
510 for (unsigned i=j+1; i<m_size; i++)
511 {
512 Tinv(i,j) = m_theta[i]*Tinv(i-1, j);
513 }
514 }
515 for( unsigned j=1; j<m_size; j++) //row index
516 {
517 for (int i=j-1; i>=0; i--)
518 {
519 Tinv(i,j) = m_phi[i]*Tinv(i+1,j);
520 }
521 }
522 }
523 private:
524 thrust::host_vector<real_type> m_phi, m_theta;
525 unsigned m_size;
526};
527
537template< class real_type>
539{
540 public:
541 using value_type = real_type;
549 TridiagInvD(const thrust::host_vector<real_type>& copyable)
550 {
551 m_size = copyable.size();
552 m_phi.assign(m_size+1,0.);
553 m_theta.assign(m_size+1,0.);
554 }
560 TridiagInvD(unsigned size)
561 {
562 m_size = size;
563 m_phi.assign(m_size+1,0.);
564 m_theta.assign(m_size+1,0.);
565 }
571 void resize(unsigned new_size) {
572 m_size = new_size;
573 m_phi.resize(m_size+1,0.);
574 m_theta.resize(m_size+1,0.);
575 }
583 void operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T, dg::SquareMatrix<real_type>& Tinv)
584 {
585 this->operator()(
586 T.O, // 0 diagonal
587 T.P, // +1 diagonal
588 T.M, // -1 diagonal
589 Tinv);
590 }
597 dg::SquareMatrix<real_type> operator()(const dg::TriDiagonal<thrust::host_vector<real_type>>& T)
598 {
600 this->operator()( T, Tinv);
601 return Tinv;
602 }
613 template<class ContainerType0, class ContainerType1, class ContainerType2>
614 void operator()(const ContainerType0& a, const ContainerType1& b,
615 const ContainerType2& c, dg::SquareMatrix<real_type>& Tinv)
616 {
617 Tinv.resize( m_size);
618 unsigned is=0;
619 for( unsigned i = 0; i<m_size+1; i++)
620 {
621 is = m_size - i;
622 if (i==0)
623 {
624 m_theta[0] = 1.;
625 m_phi[is] = 1.;
626 }
627 else if (i==1)
628 {
629 m_theta[1] = a[0];
630 m_phi[is] = a[is];
631 }
632 else
633 {
634 m_theta[i] = a[i-1] * m_theta[i-1] - b[i-2] * c[i-1] * m_theta[i-2];
635 m_phi[is] = a[is] * m_phi[is+1] - b[is] * c[is+1] * m_phi[is+2];
636 }
637 }
638
639 //Compute inverse tridiagonal matrix elements
640 for( unsigned i=0; i<m_size; i++) //row index
641 {
642 for( unsigned j=0; j<m_size; j++) //column index
643 {
644 if (i<j) {
645 Tinv(i,j) =
646 std::accumulate(std::next(b.begin(),i),
647 std::next(b.begin(),j), 1.,
648 std::multiplies<value_type>())*sign(i+j) *
649 m_theta[i] * m_phi[j+1]/m_theta[m_size];
650 }
651 else if (i==j)
652 {
653 Tinv(i,j) = m_theta[i] * m_phi[i+1]/m_theta[m_size];
654 }
655 else // if (i>j)
656 {
657 Tinv(i,j) =
658 std::accumulate(std::next(c.begin(),j+1),
659 std::next(c.begin(),i+1), 1.,
660 std::multiplies<value_type>())*sign(i+j) *
661 m_theta[j] * m_phi[i+1]/m_theta[m_size];
662 }
663 }
664 }
665 }
666 private:
668 int sign(unsigned i)
669 {
670 if (i%2==0) return 1;
671 else return -1;
672 }
673 thrust::host_vector<real_type> m_phi, m_theta;
674 unsigned m_size;
675};
676
688template<class value_type>
689void invert(const dg::TriDiagonal<thrust::host_vector<value_type>>& T,
691{
692 TridiagInvDF<value_type>( T.O.size())(T, Tinv);
693}
705template<class value_type>
707 const dg::TriDiagonal<thrust::host_vector<value_type>>& T)
708{
709 return TridiagInvDF<value_type>( T.O.size())(T);
710}
711
726template<class value_type>
727std::array<value_type, 2> compute_extreme_EV( const dg::TriDiagonal<thrust::host_vector<value_type>>& T)
728{
729 // We use P as "subdiagonal" because it is symmetric and the first element must be on 0 index
730 thrust::host_vector<value_type> evals( T.O), subdiagonal( T.P), Z, work;
731 lapack::stev('N', evals, subdiagonal, Z, work);
732 return std::array<value_type, 2>{evals[0], evals[evals.size()-1]};
733}
734
735
737
738} // namespace mat
739} // namespace dg
void resize(unsigned m, T val=T())
USE THIS ONE Compute the inverse of a general tridiagonal matrix. The algorithm does not rely on the ...
Definition tridiaginv.h:387
void resize(unsigned new_size)
Resize inverse tridiagonal matrix and helper vectors.
Definition tridiaginv.h:419
TridiagInvDF(unsigned size)
Construct from size of vector.
Definition tridiaginv.h:408
void operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:431
dg::SquareMatrix< real_type > operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:445
TridiagInvDF(const thrust::host_vector< real_type > &copyable)
Construct from vector.
Definition tridiaginv.h:397
TridiagInvDF()
Allocate nothing, Call construct method before usage.
Definition tridiaginv.h:391
real_type value_type
Definition tridiaginv.h:389
void operator()(const ContainerType0 &a, const ContainerType1 &b, const ContainerType2 &c, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix with diagonal vectors a,b,c.
Definition tridiaginv.h:462
Compute the inverse of a general tridiagonal matrix.
Definition tridiaginv.h:539
void operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:583
void resize(unsigned new_size)
Resize inverse tridiagonal matrix and helper vectors.
Definition tridiaginv.h:571
real_type value_type
Definition tridiaginv.h:541
TridiagInvD(unsigned size)
Construct from size of vector.
Definition tridiaginv.h:560
void operator()(const ContainerType0 &a, const ContainerType1 &b, const ContainerType2 &c, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix with diagonal vectors a,b,c.
Definition tridiaginv.h:614
dg::SquareMatrix< real_type > operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:597
TridiagInvD(const thrust::host_vector< real_type > &copyable)
Construct from vector.
Definition tridiaginv.h:549
TridiagInvD()
Allocate nothing, Call construct method before usage.
Definition tridiaginv.h:543
Compute the inverse of a general tridiagonal matrix.
Definition tridiaginv.h:222
TridiagInvHMGTI(const thrust::host_vector< real_type > &copyable)
Construct from vector.
Definition tridiaginv.h:232
TridiagInvHMGTI(unsigned size)
Construct from size of vector.
Definition tridiaginv.h:243
void operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:266
void operator()(const ContainerType0 &a, const ContainerType1 &b, const ContainerType2 &c, dg::SquareMatrix< real_type > &Tinv)
Compute the inverse of a tridiagonal matrix with diagonal vectors a,b,c.
Definition tridiaginv.h:297
dg::SquareMatrix< real_type > operator()(const dg::TriDiagonal< thrust::host_vector< real_type > > &T)
Compute the inverse of a tridiagonal matrix T.
Definition tridiaginv.h:280
real_type value_type
Definition tridiaginv.h:224
TridiagInvHMGTI()
Allocate nothing, Call construct method before usage.
Definition tridiaginv.h:226
void resize(unsigned new_size)
Resize inverse tridiagonal matrix and helper vectors.
Definition tridiaginv.h:254
#define _ping_
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
std::array< value_type, 2 > compute_extreme_EV(const dg::TriDiagonal< thrust::host_vector< value_type > > &T)
Compute extreme Eigenvalues of a symmetric tridiangular matrix.
Definition tridiaginv.h:727
void compute_Tinv_y(const dg::TriDiagonal< thrust::host_vector< value_type > > &T, thrust::host_vector< value_type > &x, const thrust::host_vector< value_type > &y, value_type a=1., value_type d=0.)
Computes the value of via Thomas algorithm.
Definition tridiaginv.h:188
value_type compute_Tinv_m1(const dg::TriDiagonal< thrust::host_vector< value_type > > &T, unsigned size)
Computes the value of via a Thomas algorithm.
Definition tridiaginv.h:159
void invert(const dg::TriDiagonal< thrust::host_vector< value_type > > &T, dg::SquareMatrix< value_type > &Tinv)
Invert a tridiagonal matrix.
Definition tridiaginv.h:689
Functions for optimizing Contours.
double value_type
Definition tridiaginv_b.cpp:6