|
| 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