Extension: Matrix functions
#include "dg/matrix/matrix.h"
Loading...
Searching...
No Matches
dg::mat::UniversalLanczos< ContainerType > Class Template Reference

Tridiagonalize \(A\) and approximate \(f(A)b \approx |b|_W V f(T) e_1\) via Lanczos algorithm. A is self-adjoint in the weights \( W\). More...

Public Types

using value_type = get_value_type<ContainerType>
 

Public Member Functions

 UniversalLanczos ()
 Allocate nothing, Call construct method before usage.
 
 UniversalLanczos (const ContainerType &copyable, unsigned max_iterations)
 Allocate memory for the method.
 
template<class ... Params>
void construct (Params &&...ps)
 Perfect forward parameters to one of the constructors.
 
void set_max (unsigned new_max)
 Set the maximum number of iterations.
 
unsigned get_max () const
 Get the current maximum number of iterations.
 
void set_verbose (bool verbose)
 Set or unset debugging output during iterations.
 
double get_bnorm () const
 Norm of b from last call to operator()
 
unsigned get_iter () const
 Get the number of iterations in the last call to tridiag or solve (same as T.num_rows)
 
template<class MatrixType , class ContainerType0 , class ContainerType1 , class ContainerType2 , class FuncTe1 >
unsigned solve (ContainerType0 &x, FuncTe1 f, MatrixType &&A, const ContainerType1 &b, const ContainerType2 &weights, double eps, double nrmb_correction=1., std::string error_norm="universal", double res_fac=1., unsigned q=1)
 \( x = f(A)b \approx ||b||_W V f(T) e_1 \) via Lanczos and matrix function computation. A is self-adjoint in the weights \( W\).
 
template<class MatrixType , class ContainerType0 , class ContainerType1 >
const dg::TriDiagonal< thrust::host_vector< double > > & tridiag (MatrixType &&A, const ContainerType0 &b, const ContainerType1 &weights, double eps=1e-4, double nrmb_correction=1., std::string error_norm="compute_extreme_EV", double res_fac=1., unsigned q=1)
 Tridiagonalization of A using Lanczos method with \( f(x) = x^{-1} \).
 
template<class MatrixType , class ContainerType0 , class ContainerType1 , class ContainerType2 >
void normMbVy (MatrixType &&A, const dg::TriDiagonal< thrust::host_vector< double > > &T, const ContainerType0 &y, ContainerType1 &x, const ContainerType2 &b, double bnorm)
 compute \( x = |b|_W V y \) from a given tridiagonal matrix T and in-place re-computation of V
 
template<class UnaryOp , class MatrixType , class ContainerType1 , class ContainerType2 >
const dg::TriDiagonal< thrust::host_vector< double > > & tridiag (UnaryOp f, MatrixType &&A, const ContainerType1 &b, const ContainerType2 &weights, double eps, double nrmb_correction, std::string error_norm="residual", double res_fac=1., unsigned q=1)
 Tridiagonalization of A using Lanczos method.
 

Detailed Description

template<class ContainerType>
class dg::mat::UniversalLanczos< ContainerType >

Tridiagonalize \(A\) and approximate \(f(A)b \approx |b|_W V f(T) e_1\) via Lanczos algorithm. A is self-adjoint in the weights \( W\).

The M-Lanczos method is based on the paper Novel Numerical Methods for Solving the Time-Space Fractional Diffusion Equation in Two Dimensions by Q. Yang et al, but adopts a more efficient implementation similar to that in the PCG method. Further also the conventional Lanczos method can be found there and also in text books such as Iteratvie Methods for Sparse Linear Systems 2nd edition by Yousef Saad.

The Lanczos algorithm's main purpose is to find (approximate) Eigenvalues and Eigenvectors of a symmetric definite matrix. It does so by computing Eigenvalues of the (symmetric) tridiagonal matrix \( T\) (the "Ritz" or "Rayleigh-Ritz" values) that the Lanczos algorithm produces. The extreme values i.e. the maximum and minimum Eigenvalue of \( T\) converge fairly quickly to the extreme Eigenvalues of \(A\).

Note
We have several stopping criteria. The residual criterion stops when \( \tau ||r_i||_W = \tau ||\vec b||_W \beta_i (T^{-1})_{1m} \leq \epsilon_{rel} ||\vec b||_W + \epsilon_{aps} \) where \( \tau \) is a residual factor accounting for the condition of various matrix functions
The universal stopping criterion is based on the paper Estimating the error in matrix function approximations by Q. Eshghi, N. and Reichel L., The iteration stops when

\[ ||\vec{e}_{f,m}||_W = ||\vec{b}||_W ||\left(\check{T} - f(\bar{T})\right)\vec{e}_1||_2 \leq \epsilon_{rel} ||\vec{b}||_W ||f(T)\vec e_1||_2 + \epsilon_{abs} \]

with

\[ \bar{T} = \begin{pmatrix} T & \beta_m \vec{e}_m & & \\ \beta_m \vec{e}_m^T & \alpha_{m-1} & \beta_{m-2} & \\ & \beta_{m-2} & \alpha_{m-2} & \beta_{m-1-q} \\ & & \beta_{n-1-q} & \alpha_{n-q} \end{pmatrix} \]

\[ \check{T} = \begin{pmatrix} f(T) & 0 \\ 0 & 0 \end{pmatrix} \]

The "compute_extreme_EV" and "compute_max_EV" stopping criteria are based on tracking the convergence progress of \(\lambda^T_\min\) and \( \lambda^T_\max\) of the tridiagonal matrix \( T\).

\[ |\lambda^T_{\min, 10(i-1)} - \lambda^T_{\min , 10i}| < 10(\epsilon\lambda_\min + 10^{-12}\lambda_\max)\\ |\lambda^T_{\max, 10(i-1)} - \lambda^T_{\max , 10i}| < 10\epsilon\lambda_\max \]

We test convergence only every 10th iteration for various reasons
  • The Eigenvalue decomposition of \( T\) may become performance relevant for very large \( i\). Testing only every 10th iterations amortises the cost
  • Lanczos is at risk of misconvergence which means the algorithm may "converge" to a \(\lambda^T\) that is not an extreme Eigenvalue because for several iterations no larger/smaller Eigenvalue appears (this happens not infrequently). Testing only every 10th iteration decreases this risk such that we do not see it in practise (but it does not vanish entirely)
Also here note that theoretically the minimum and maximum Eigenvalue should converge at the same rate, however the error constant for the minimum Eigenvalue is much worse (by the condition number \(\kappa\) of the matrix!). This is because all Eigenvalues that are found by \( T\) lie within the spectrum of \(A\), i.e.

\[ \lambda^A_\min < \lambda^T_\min < \lambda^T_\max < \lambda^T_\max \\ \frac{\lambda^A_\max - \lambda^T_\max }{\lambda^A_\max} < 1 \\ \frac{\lambda^T_\min - \lambda^A_\min}{\lambda^A_\min} = \kappa\frac{\lambda^T_\min - \lambda^A_\min}{\lambda^A_\max} < \kappa \]

THIS METHOD DOES NOT WORK (but is still instructive: On estimating the largest Eigenvalue with the Lanczos algorithm by B. N. Parlett, H. Simon and L. M. Stringer The proposed stopping criterion consists of checking if the found (approximate) Eigenvector is indeed an Eigenvector of \(A\). Suppose we find

\[ T_m s = \lambda s \]

Then, we accept the corresponding vector \( y = V_m s\) as an Eigenvector of \( A\) if

\[ || Ay - \lambda y ||_W \leq \epsilon || y||_W \]

Since the \( V_m\) are normalised we esimate \( || y||_W > 0.9\) and we have \( A y= A V_m s = V_m T_m s + \beta_m \vec v_{m+1} \vec e_m^T s = \lambda V_m s + \beta_m \vec v_{m+1} s_m\) where \( s_m\) is the last component of \(s\). Thus, we have \( A y - \lambda y = \beta_m \vec v_{m+1} s_m \) and therefore

\[ \beta_m s_m \leq 0.9 \epsilon \]

Unfortunately in practise \( \beta_m s_m \) is rather large and the convergence is extremely slow. Even if the Eigenvalues converge rather quickly, the Eigenvectors do not!

The common Lanczos method (and M-Lanczos) method are prone to loss of orthogonality for finite precision.

Template Parameters
ContainerTypeAny class for which a specialization of TensorTraits exists and which fulfills the requirements of the there defined data and execution policies derived from AnyVectorTag and AnyPolicyTag. Among others
  • dg::HVec (serial), dg::DVec (cuda / omp), dg::MHVec (mpi + serial) or dg::MDVec (mpi + cuda / omp)
  • std::vector<dg::DVec> (vector of shared device vectors), std::array<double, 4> (array of 4 doubles) or std::map < std::string, dg::DVec> ( a map of named vectors)
  • double (scalar) and other primitive types ...
If there are several ContainerTypes in the argument list, then TensorTraits must exist for all of them
See also
See The dg dispatch system for a detailed explanation of our type dispatch system

Member Typedef Documentation

◆ value_type

template<class ContainerType >
using dg::mat::UniversalLanczos< ContainerType >::value_type = get_value_type<ContainerType>

value type of the ContainerType class

Constructor & Destructor Documentation

◆ UniversalLanczos() [1/2]

template<class ContainerType >
dg::mat::UniversalLanczos< ContainerType >::UniversalLanczos ( )
inline

Allocate nothing, Call construct method before usage.

◆ UniversalLanczos() [2/2]

template<class ContainerType >
dg::mat::UniversalLanczos< ContainerType >::UniversalLanczos ( const ContainerType & copyable,
unsigned max_iterations )
inline

Allocate memory for the method.

Parameters
copyableA ContainerType must be copy-constructible from this
max_iterationsMaximum number of iterations to be used

Member Function Documentation

◆ construct()

template<class ContainerType >
template<class ... Params>
void dg::mat::UniversalLanczos< ContainerType >::construct ( Params &&... ps)
inline

Perfect forward parameters to one of the constructors.

Template Parameters
Paramsdeduced by the compiler
Parameters
psparameters forwarded to constructors

◆ get_bnorm()

template<class ContainerType >
double dg::mat::UniversalLanczos< ContainerType >::get_bnorm ( ) const
inline

Norm of b from last call to operator()

Returns
bnorm

◆ get_iter()

template<class ContainerType >
unsigned dg::mat::UniversalLanczos< ContainerType >::get_iter ( ) const
inline

Get the number of iterations in the last call to tridiag or solve (same as T.num_rows)

Returns
the number of iterations in the last call to tridiag or solve

◆ get_max()

template<class ContainerType >
unsigned dg::mat::UniversalLanczos< ContainerType >::get_max ( ) const
inline

Get the current maximum number of iterations.

Returns
the current maximum

◆ normMbVy()

template<class ContainerType >
template<class MatrixType , class ContainerType0 , class ContainerType1 , class ContainerType2 >
void dg::mat::UniversalLanczos< ContainerType >::normMbVy ( MatrixType && A,
const dg::TriDiagonal< thrust::host_vector< double > > & T,
const ContainerType0 & y,
ContainerType1 & x,
const ContainerType2 & b,
double bnorm )
inline

compute \( x = |b|_W V y \) from a given tridiagonal matrix T and in-place re-computation of V

We avoid explicit storage of the large matrix V

Parameters
AA self-adjoint positive definit matrix
TTridiagonal matrix
ya (host) vector e.g y= T e_1 or y= f(T) e_1, must have size of T.num_rows
xThe result vector (output)
bContains the initial value of lanczos method
bnormthe norm of b in weights, get_bnorm()

◆ set_max()

template<class ContainerType >
void dg::mat::UniversalLanczos< ContainerType >::set_max ( unsigned new_max)
inline

Set the maximum number of iterations.

Parameters
new_maxNew maximum number

◆ set_verbose()

template<class ContainerType >
void dg::mat::UniversalLanczos< ContainerType >::set_verbose ( bool verbose)
inline

Set or unset debugging output during iterations.

Parameters
verboseIf true, additional output will be written to std::cout during solution

◆ solve()

template<class ContainerType >
template<class MatrixType , class ContainerType0 , class ContainerType1 , class ContainerType2 , class FuncTe1 >
unsigned dg::mat::UniversalLanczos< ContainerType >::solve ( ContainerType0 & x,
FuncTe1 f,
MatrixType && A,
const ContainerType1 & b,
const ContainerType2 & weights,
double eps,
double nrmb_correction = 1.,
std::string error_norm = "universal",
double res_fac = 1.,
unsigned q = 1 )
inline

\( x = f(A)b \approx ||b||_W V f(T) e_1 \) via Lanczos and matrix function computation. A is self-adjoint in the weights \( W\).

Tridiagonalize \(A\) using Lanczos algorithm with a residual or universal stopping criterion

Parameters
xoutput vector
fthe matrix function that is called like yH = f( T) where T is the tridiagonal matrix and returns the result of \( f(T)\vec e_1\) (for example dg::mat::make_FuncEigen_Te1( dg::SQRT<double>()) )
See also
Matrix-functions
Parameters
AA self-adjoint, positive definit matrix
bThe initial vector that starts orthogonalization.
Attention
If tridiagonalisation is used to determine Eigenvalues, b should be initialised with random values to make misconvergence and breakdown due to beta = 0 less likely.
Parameters
weightsWeights that define the scalar product in which A is self-adjoint and in which the error norm is computed.
epsrelative accuracy of residual
nrmb_correctionthe absolute error C in units of eps to be respected (ignored for "compute_*_EV" error norms)
error_normEither "residual" or "universal" or "compute_extreme_EV" or "compute_max_EV". In the latter two cases the iteration terminates if the extreme ( = maximum and minimum) /maximum Eigenvalue(s) of the tridiagonal matrix converge i.e. \( | \lambda_{\max, i} - \lambda_{\max, i-1}|< \epsilon \lambda_{\max,i}\) (analogous for minimum). In the Eigenvalue cases nrmb_correction, res_fac and q are ignored. In the Eigenvalue case the algorithm trows if breakdown occurs. The error conditions is checked every iteration for the first 10 iterations and then only every 10th iteration.
res_facfactor \( \tau\) in the "universal" and "resisdual" error_norm that is multiplied to the norm of the residual. Used to account for specific matrix function and operator in the convergence criterium
qThe q-number in the "universal" error_norm (ignored otherwise)
See also
https://www.jstor.org/stable/2007471?seq=1
Returns
number of iterations of M-Lanczos routine

◆ tridiag() [1/2]

template<class ContainerType >
template<class MatrixType , class ContainerType0 , class ContainerType1 >
const dg::TriDiagonal< thrust::host_vector< double > > & dg::mat::UniversalLanczos< ContainerType >::tridiag ( MatrixType && A,
const ContainerType0 & b,
const ContainerType1 & weights,
double eps = 1e-4,
double nrmb_correction = 1.,
std::string error_norm = "compute_extreme_EV",
double res_fac = 1.,
unsigned q = 1 )
inline

Tridiagonalization of A using Lanczos method with \( f(x) = x^{-1} \).

Note
Just calls the general tridiag method with the function \( f(x) = x^{-1}\). Useful if one wants to compute the extreme Eigenvalues of \(A\)
The maximum Eigenvalue converges much faster than the minimum Eigenvalue.
dg::mat::UniversalLanczos lanczos( A.weights(), 2000);
auto T = lanczos.tridiag( A, rnd, A.weights());
// EV[0] is the minimum, EV[1] the maximum Eigenvalue
Tridiagonalize and approximate via Lanczos algorithm. A is self-adjoint in the weights .
Definition lanczos.h:154
auto evaluate(Functor &&f, const Topology &g)
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
dg::DVec Container
Definition lanczos_b.cpp:19
Note
The Eigenvalues of \( T\) are called the Rayleigh-Ritz values
Parameters
AA self-adjoint, positive definit matrix
bThe initial vector that starts orthogonalization.
Attention
If tridiagonalisation is used to determine Eigenvalues, b should be initialised with random values to make misconvergence and breakdown due to beta = 0 less likely.
Parameters
weightsWeights that define the scalar product in which A is self-adjoint and in which the error norm is computed.
epsrelative accuracy of residual
nrmb_correctionthe absolute error C in units of eps to be respected (ignored for "compute_*_EV" error norms)
error_normEither "residual" or "universal" or "compute_extreme_EV" or "compute_max_EV". In the latter two cases the iteration terminates if the extreme ( = maximum and minimum) /maximum Eigenvalue(s) of the tridiagonal matrix converge i.e. \( | \lambda_{\max, i} - \lambda_{\max, i-1}|< \epsilon \lambda_{\max,i}\) (analogous for minimum). In the Eigenvalue cases nrmb_correction, res_fac and q are ignored. In the Eigenvalue case the algorithm trows if breakdown occurs. The error conditions is checked every iteration for the first 10 iterations and then only every 10th iteration.
res_facfactor \( \tau\) in the "universal" and "resisdual" error_norm that is multiplied to the norm of the residual. Used to account for specific matrix function and operator in the convergence criterium
qThe q-number in the "universal" error_norm (ignored otherwise)
See also
https://www.jstor.org/stable/2007471?seq=1
Returns
returns the tridiagonal matrix T. Note that \( T = (MV)^T A V \). The number of iterations is given by T.num_rows

◆ tridiag() [2/2]

template<class ContainerType >
template<class UnaryOp , class MatrixType , class ContainerType1 , class ContainerType2 >
const dg::TriDiagonal< thrust::host_vector< double > > & dg::mat::UniversalLanczos< ContainerType >::tridiag ( UnaryOp f,
MatrixType && A,
const ContainerType1 & b,
const ContainerType2 & weights,
double eps,
double nrmb_correction,
std::string error_norm = "residual",
double res_fac = 1.,
unsigned q = 1 )
inline

Tridiagonalization of A using Lanczos method.

Tridiagonalize \(A\) using Lanczos algorithm with a residual or universal stopping criterion on the function \( f(x) \)

Parameters
fUnary function (ignored if error_norm is not "universal")
Parameters
AA self-adjoint, positive definit matrix
bThe initial vector that starts orthogonalization.
Attention
If tridiagonalisation is used to determine Eigenvalues, b should be initialised with random values to make misconvergence and breakdown due to beta = 0 less likely.
Parameters
weightsWeights that define the scalar product in which A is self-adjoint and in which the error norm is computed.
epsrelative accuracy of residual
nrmb_correctionthe absolute error C in units of eps to be respected (ignored for "compute_*_EV" error norms)
error_normEither "residual" or "universal" or "compute_extreme_EV" or "compute_max_EV". In the latter two cases the iteration terminates if the extreme ( = maximum and minimum) /maximum Eigenvalue(s) of the tridiagonal matrix converge i.e. \( | \lambda_{\max, i} - \lambda_{\max, i-1}|< \epsilon \lambda_{\max,i}\) (analogous for minimum). In the Eigenvalue cases nrmb_correction, res_fac and q are ignored. In the Eigenvalue case the algorithm trows if breakdown occurs. The error conditions is checked every iteration for the first 10 iterations and then only every 10th iteration.
res_facfactor \( \tau\) in the "universal" and "resisdual" error_norm that is multiplied to the norm of the residual. Used to account for specific matrix function and operator in the convergence criterium
qThe q-number in the "universal" error_norm (ignored otherwise)
See also
https://www.jstor.org/stable/2007471?seq=1
Returns
returns the tridiagonal matrix T. Note that \( T = (MV)^T A V \). The number of iterations is given by T.num_rows

The documentation for this class was generated from the following file: