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.
compute_Mder
: Computes a given derivative of the matrix function $M(λ)$.compute_Mlincomb
(orcompute_Mlincomb!
, with same documentation): Computes a linear combination of derivatives $M(λ)$compute_MM
: Computes the block residual.
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.
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
NonlinearEigenproblems.NEPCore.compute_Mder
— Function.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
NonlinearEigenproblems.NEPCore.compute_Mlincomb
— Function.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.
NonlinearEigenproblems.NEPCore.compute_MM
— Function.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
NonlinearEigenproblems.NEPTypes.Mder_NEP
— Function.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 der
th 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_Mlincomb
functions 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)