Compute functions

Compute functions

The nonlinear eigenvalue problems in NEP-PACK are defined by the data stored in the corresponding NEP-class. The advised way NEP-solvers access the data is to do it through three main functions, which take the NEP-object as input.

The choice of these functions as the fundamental way to access a NEP is a balancing between what applications can provide and NEP-solvers need.

A user who needs a new class of NEPs (which is not available in among the standard types) is advised to use the helper functions Mder_NEP and/or Mder_Mlincomb_NEP rather than reimplementing the compute-functions, since the helper types are more user friendly. Implementation of your own NEP-type is only advised if needed for efficiency reasons.

Tip

Examples of usage of Mder_NEP and/or Mder_Mlincomb_NEP are available in tutorials on boundary element method, python, matlab, and fortran.

As a NEP-solver developer, compute_Mlincomb-calls are preferred over compute_Mder-calls, for the same reasons that algorithms that only require matrix vector products can be easier to use in a given application than an iterative algorithm using only matrix vector products. It is in general also more efficient although they produce the same result up to round-off errors:

julia> using BenchmarkTools;
julia> n=1000; p=10;
julia> nep=DEP([randn(n,n), randn(n,n)];
julia> V=randn(n,p);
julia> @btime compute_Mlincomb(nep,1.0,V);
  478.316 μs (19 allocations: 80.78 KiB)
julia> @btime for k=1:p; z[:]+=compute_Mder(nep,1.0,k)*V[:,k]; end
  78.510 ms (183 allocations: 465.71 MiB)

The compute_Mlincomb-function exist in two variants, where compute_Mlincomb! may modify the V-matrix, but in general require less memory allocations.

For a type where only compute_Mder is implemented, the compute_Mlincomb-functionality can be provided by delegating using the function compute_Mlincomb_from_Mder, such that methods which require compute_Mlincomb can be used.

Compute-functions documentation

compute_Mder(nep::NEP,λ::Number [,i::Integer=0])

Computes the ith derivative of nep evaluated in λ.

Example

This example shows that compute_Mder(nep,λ,1) gives the first derivative.

julia> nep=nep_gallery("dep0");
julia> ϵ=1e-5; λ=2.25;
julia> Aminus=compute_Mder(nep,λ-ϵ);
julia> Aplus=compute_Mder(nep,λ+ϵ);
julia> opnorm((Aplus-Aminus)/(2ϵ)-compute_Mder(nep,λ,1))
1.8783432885257602e-11
compute_Mlincomb(nep::NEP,λ::Number,V, a::Vector=ones(size(V,2)), startder=0)
compute_Mlincomb!(nep::NEP,λ::Number,V, a::Vector=ones(size(V,2)), startder=0)

Computes the linear combination of derivatives
$Σ_i a_i M^{(i)}(λ) v_i$ starting from derivative startder. The function compute_Mlincomb! does the same but may modify the V matrix/array.

Example

This example shows that compute_Mder gives a result consistent with compute_Mlincomb. Note that compute_Mlincomb is in general faster since no matrix needs to be constructed.

julia> nep=nep_gallery("dep0");
julia> v=ones(size(nep,1)); λ=-1+1im;
julia> norm(compute_Mder(nep,λ,1)*v-compute_Mlincomb(nep,λ,hcat(v,v),[0,1]))
0.0
compute_Mlincomb(nep::NEP,λ::Number,V,a::Array,startder::Integer)

Computes linear combination starting with derivative startder, i.e., $Σ_i a_i M^{(i+startder)}(λ) v_i$

The default implementation of this can be slow. Overload for specific NEP if you want efficiency, e.g., in augnewton, iar, and others.

compute_MM(nep::NEP,S,V)

Computes the sum $Σ_i M_i V f_i(S)$ for a NEP, where $S$ and $V$ are matrices, and the NEP satisfies $M(λ)=Σ_i M_i f_i(λ)$.

Example

This example shows that for diagonal S, the result of compute_MM can also be computed with compute_Mlincomb

julia> nep=nep_gallery("dep0");
julia> D=diagm(0 => [1,2])
2×2 Array{Int64,2}:
 1  0
 0  2
julia> V=ones(size(nep,1),2);
julia> W=compute_MM(nep,D,V);
julia> norm(W[:,1]-compute_Mlincomb(nep,D[1,1],V[:,1]))
0.0
julia> norm(W[:,2]-compute_Mlincomb(nep,D[2,2],V[:,2]))
4.440892098500626e-16

Reference

Properties of the quantity $Σ_i M_i V f_i(S)$ for non-polynomial nonlinear eigenvalue problems were extensively used in:

  • D. Kressner A block Newton method for nonlinear eigenvalue problems, Numer. Math., 114 (2) (2009), pp. 355-372
  • C. Effenberger, Robust solution methods for nonlinear eigenvalue problems, PhD thesis, 2013, EPF Lausanne

Type helpers

Mder_NEP(n,Mder_fun; maxder=max)

Creates a NEP from its compute_Mder function defined by the function handle Mder_fun. The Mder_fun(λ,der) takes two parameters a scalar λ::Number, derivative number der. The size n::Int must also be specified. The function Mder_fun(λ,der) should return the n x n matrix corresponding to the derth derivatve. If only a limited number of derivatives are available, maxder should be set, e.g., if not derivatives are implemented, set maxder=0. The function compute_Mlicomb is automatically available by (delegation) to compute_Mlincomb_from_Mder.

Note: This is a convenience function it is not recommended for high performance computations, since, e.g., it will not maintain type stability.

Example

The following example defines a linear eigenvalue problem A0+λA1 defined in an external function.

julia> using LinearAlgebra; # For the I function
julia> function my_Mder(s,der)
    A0=ones(Float64,3,3)-I; A0[1,1]=-1;
    A1=ones(Float64,3,3)*3; A1[2,3]=0;
    if (der==0)
       return A0+A1*s;
    elseif (der==1)
       return A1;
    else
       return zero(A0);
    end
end
julia> nep=Mder_NEP(3,my_Mder);
julia> (λ,v)=augnewton(nep,v=ones(3));
julia> norm(compute_Mder(nep,λ)*v)
5.551115123125783e-17
Mder_Mlincomb_NEP(n,Mder_fun, [maxder_Mder,] Mlincomb_fun, [maxder_Mlincomb])

Creates a NEP from its compute_Mder and compute_Mlincombfunctions defined by the function handles Mder_fun and Mlincomb_fun. The Mlincomb_fun(λ,X) takes two parameters a scalar λ::Number and a matrix X. The size n::Int must also be specified. The function Mlincomb_fun(λ,X) should return a vector corresponding of the linear combination of derivatives multiplied with the vectors in X. If only a limited number of derivatives are implemented, maxder_Mder or maxder_Mlincomb should be set, e.g., if not derivatives are implemented, set maxder=0.

See also Mder_NEP.

Note: This is a convenience function it is not recommended for high performance computations, since, e.g., it will not maintain type stability.

Example

The following example defines a linear eigenvalue problem A0+λA1 defined in an external function.

julia> using LinearAlgebra; # For the I function
julia> function my_Mder(s,der)
    A0=ones(Float64,3,3)-I; A0[1,1]=-1;
    A1=ones(Float64,3,3)*3; A1[2,3]=0;
    if (der==0)
       return A0+A1*s;
    elseif (der==1)
       return A1;
    else
       return zero(A0);
    end
end
julia> function my_Mlincomb(s,X) # Compute linear comb of derivatives
    A0=ones(Float64,3,3)-I; A0[1,1]=-1;
    A1=ones(Float64,3,3)*3; A1[2,3]=0;
    if (size(X,2) <= 1)
       return A0*X[:,1]+s*A1*X[:,1]
    else # This means: size(X,2) => 2
       return A0*X[:,1]+A1*(s*X[:,1]+X[:,2]);
    end
end
julia> nep=Mder_Mlincomb_NEP(3,my_Mder,my_Mlincomb);
julia> (λ,v)=augnewton(nep,v=[1.0; 2.3; 0.0])
julia> norm(compute_Mder(nep,λ)*v)
6.798699777552591e-17
compute_Mlincomb_from_Mder(nep::NEP,λ::Number,V,a)

The function computes Mlincomb by a call to compute_Mder. This function is slow since it requires the construction of the matrices. Usage normally by overloading in this way

    compute_Mlincomb(nep::MyNEP,λ::Number,V,a)=compute_Mlincomb_from_Mder(nep,λ,V,a)
compute_Mlincomb_from_MM(nep::NEP,λ::Number,V,a)

This function provides a compute_Mlincomb-function call by invoking a call to compute_MM. The underlying mathematical relationship is described in github issue #2 and #3.

The standard usage is by the following command:

compute_Mlincomb(nep::MyNEP,λ::Number,V,a)=compute_Mlincomb_from_MM(nep,λ,V,a)