N₁=5
# Coefficient matrix of second-order centered-difference operator (δ²u)ₙ
M = Tridiagonal(fill(1,N₁-1), fill(-2,N₁), fill(1,N₁-1));
M[N₁,1] = 1; # Periodic boundary conditions
M[1,N₁] = 1;
results in the following error
ArgumentError: cannot set entry (5, 1) off the tridiagonal band to a nonzero value (1)
Why is such an error thrown? What can I do to perform the operator I want? That is, modifying the entries of the matrix.
Per Linear Algebra · The Julia Language it seems that Tridiagonal
is a Type itself!
That error occurs because the matrix would no longer be tri-diagonal. Tridiagonal
is a special matrix type that only stores tridiagonal matrices and does not handle any other sparsity pattern.
You need to use some other matrix type. e.g. you could use a dense matrix (just convert to Matrix
), but of course that throws away the sparsity. Or you could use a generic sparse matrix type from SparseArrays
. (I don’t think anyone has implemented a specialized library for periodic tridiagonal matrices in Julia?)
1 Like
Perhaps a Circulant
matrix, or something similar? Using ToeplitzMatrices.jl
:
julia> Circulant([-2,1,0,0,1])
5×5 Circulant{Int64, Vector{Int64}}:
-2 1 0 0 1
1 -2 1 0 0
0 1 -2 1 0
0 0 1 -2 1
1 0 0 1 -2
2 Likes
We get condensed syntax which is nice, but what is the benefit of using the Circulant
matrix versus the following?
M = spdiagm(-1 => fill(1,N₁-1),0 => fill(-2,N₁) ,1 => fill(1,N₁-1))
M[N₁,1] = 1; # Periodic boundary conditions
M[1,N₁] = 1;
A Circulant
-typed matrix is likely to take advantage of the structural properties it implies. For example, many operations (e.g. multiplication, inversion, and solves) with a Circulant
matrix are likely to exploit the FFT for better efficiency. A generic sparse matrix will not fully exploit this structure.
Multiplication will likely be faster with the sparse matrix (although would be better-yet via direct circular convolution). Most more-complicated operations (inverses, solves, determinant, etc.) will likely be faster with the circulant matrix. With a lot of work you could custom-make a SparseCirculant
type that exploits both structures, but for now I would settle for whichever single type is best-suited to what you’re trying to do.
2 Likes