Skip to content

Commit 4112724

Browse files
authored
Move eigs from ApproxFun (#458)
* Move eigs from ApproxFun * update docstring
1 parent 2f401fa commit 4112724

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ApproxFunBase"
22
uuid = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
3-
version = "0.8.19"
3+
version = "0.8.20"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

src/ApproxFunBase.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import LinearAlgebra: BlasInt, BlasFloat, norm, ldiv!, mul!, det, cross,
4343
qr, qr!, rank, isdiag, istril, istriu, issymmetric,
4444
Tridiagonal, diagm, diagm_container, factorize,
4545
nullspace, Hermitian, Symmetric, adjoint, transpose, char_uplo,
46-
axpy!
46+
axpy!, eigvals
4747

4848
import SparseArrays: blockdiag
4949

@@ -151,6 +151,7 @@ include("Operators/Operator.jl")
151151
include("Caching/caching.jl")
152152
include("PDE/PDE.jl")
153153
include("Spaces/Spaces.jl")
154+
include("eigen.jl")
154155
include("hacks.jl")
155156
include("testing.jl")
156157
include("specialfunctions.jl")

src/eigen.jl

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
export eigs
2+
3+
4+
eigvals(A::Operator,n::Integer;tolerance::Float64=100eps()) =
5+
eigs(A,n;tolerance=tolerance)[1]
6+
7+
"""
8+
λ, V = eigs(A::Operator, n::Integer; tolerance::Float64=100eps())
9+
10+
Compute the eigenvalues and eigenvectors of the operator `A`. This is done in the following way:
11+
12+
* Truncate `A` into an `n×n` matrix `A₁`.
13+
* Compute eigenvalues and eigenvectors of `A₁`.
14+
* Filter for those eigenvectors of `A₁` that are approximately eigenvectors
15+
of `A` as well. The `tolerance` argument controls, which eigenvectors of the approximation are kept.
16+
"""
17+
function eigs(A::Operator,n::Integer;tolerance::Float64=100eps())
18+
typ = eltype(A)
19+
20+
ds=domainspace(A)
21+
C = Conversion(ds,rangespace(A))
22+
23+
A1,C1 = zeros(typ,n,n),zeros(typ,n,n)
24+
A1[1:end,1:n] = A[1:n,1:n]
25+
C1[1:end,1:n] = C[1:n,1:n]
26+
27+
λ,V=eigen(A1,C1)
28+
29+
pruneeigs(λ,V,ds,tolerance)
30+
end
31+
32+
eigvals(Bcs::Operator,A::Operator,n::Integer;tolerance::Float64=100eps()) =
33+
eigs(Bcs,A,n;tolerance=tolerance)[1]
34+
35+
"""
36+
λ, V = eigs(BC::Operator, A::Operator, n::Integer; tolerance::Float64=100eps())
37+
38+
Compute `n` eigenvalues and eigenvectors of the operator `A`,
39+
subject to the boundary conditions `BC`.
40+
41+
# Examples
42+
```jldoctest
43+
julia> #= We compute the spectrum of the second derivative,
44+
subject to zero boundary conditions.
45+
We solve this eigenvalue problem in the Chebyshev basis =#
46+
47+
julia> S = Chebyshev();
48+
49+
julia> D = Derivative(S, 2);
50+
51+
julia> BC = Dirichlet(S);
52+
53+
julia> λ, v = ApproxFun.eigs(BC, D, 100);
54+
55+
julia> λ[1:10] ≈ [-(n*pi/2)^2 for n in 1:10] # compare with the analytical result
56+
true
57+
```
58+
"""
59+
function eigs(Bcs_in::Operator,A_in::Operator,n::Integer;tolerance::Float64=100eps())
60+
Bcs, A = promotedomainspace([Bcs_in, A_in])
61+
62+
nf = size(Bcs,1)
63+
@assert isfinite(nf)
64+
65+
typ = promote_type(eltype(Bcs),eltype(A))
66+
67+
ds=domainspace(A)
68+
C = Conversion(ds,rangespace(A))
69+
70+
A1,C1 = zeros(typ,n,n),zeros(typ,n,n)
71+
A1[1:nf,1:n] = Bcs[1:nf,1:n]
72+
A1[nf+1:end,1:n] = A[1:n-nf,1:n]
73+
C1[nf+1:end,1:n] = C[1:n-nf,1:n]
74+
75+
λ,V = eigen(A1,C1)
76+
77+
λ, V = pruneeigs(λ,V,ds,tolerance)
78+
p = sortperm(λ; lt=(x,y) -> isless(abs(x),abs(y)))
79+
λ[p], V[p]
80+
end
81+
82+
function pruneeigs(λ,V,ds,tolerance)
83+
retλ=eltype(λ)[]
84+
retV=VFun{typeof(ds),eltype(V)}[]
85+
n=length(λ)
86+
for k=1:n
87+
if slnorm(V,n-3:n,k)tolerance
88+
push!(retλ,λ[k])
89+
push!(retV,Fun(ds,V[:,k]))
90+
end
91+
end
92+
retλ,retV
93+
end

0 commit comments

Comments
 (0)