Thank you very much for the example. I have been working on it and I now have a working implementation:
using ClassicalOrthogonalPolynomials, LinearAlgebra, Julianim
n = 20
T = chebyshevt(0.25 .. 1)
r = axes(T, 1)
D = ComplexF64.(T \ diff(T))[1:n, 1:n]
Dτ = D[1:n-2, 1:n]
Bop = ComplexF64.(T \ ((1 ./ r) .* T))[1:n, 1:n]
Bopτ = Bop[1:n-2, 1:n]
Iₙ = Matrix{ComplexF64}(I, n, n)
Iτ = [Matrix{ComplexF64}(I, n - 2, n - 2) zeros(ComplexF64, n - 2, 2)]
Z = zeros(ComplexF64, n, n)
Zτ = zeros(ComplexF64, n - 2, n)
z0 = zeros(ComplexF64, 1, n)
eσ = ComplexF64.(T[σ, 1:n])
e₁ = ComplexF64.(T[1, 1:n])
a = -im * 10.0
c = im * 2 * Bop
cτ = im * 2 * Bopτ
d = 0.3
# Boundary conditions by removing equations from last block
A = [
eσ' z0 z0 z0;
e₁' z0 z0 z0;
a*Iₙ Z Z D;
Z a*Iₙ Z c;
Z Z a*Iₙ Z;
Dτ+Bopτ cτ Zτ a*Iτ
]
M = [
z0 z0 z0 z0;
z0 z0 z0 z0;
d*Iₙ Z Z Z;
Z d*Iₙ Z Z;
Z Z d*Iₙ Iₙ;
Zτ Zτ Iτ d*Iτ
]
# Boundary conditions by removing equations from first block
# A = [
# eσ' z0 z0 z0;
# e₁' z0 z0 z0;
# a*Iτ Zτ Zτ Dτ;
# Z a*Iₙ Z c;
# Z Z a*Iₙ Z;
# D+Bop c Z a*Iₙ
# ]
# M = [
# z0 z0 z0 z0;
# z0 z0 z0 z0;
# d*Iτ Zτ Zτ Zτ;
# Z d*Iₙ Z Z;
# Z Z d*Iₙ Iₙ;
# Z Z Iₙ d*Iₙ
# ]
λ, x̂ = eigen(A, M)
k̃ₓ = im .* λ
Do you have any intuition for how the boundary conditions should be handled in a case like this?
I am asking because, if I impose the two BCs after removing equations from the last block, some spurious modes with purely real eigenvalues disappear. However, if I do the analogous thing after removing equations from the first block, those spurious modes appear again.
This is probably something specific to my problem, and I will think more carefully about it. Still, I was wondering whether there is any general rationale for how to insert boundary conditions in these coefficient based discretizations, where some equations have to be dropped in order to obtain a square system.