# Modifying a tridiagonal matrix

**URL:** https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131
**Category:** New to Julia
**Tags:** question, syntax
**Created:** [April 5, 2023, 7:33pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131 "2023-04-05T19:33:13Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![KZ-Spectra](https://avatars.discourse-cdn.com/v4/letter/k/2acd7d/32.png) [@KZ-Spectra](https://discourse.julialang.org/u/KZ-Spectra)
#### Post date: [April 5, 2023, 7:33pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131/1 "2023-04-05T19:33:13Z")

</div>

```julia
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](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.Tridiagonal) it seems that `Tridiagonal` is a Type itself!

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [April 5, 2023, 7:39pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131/2 "2023-04-05T19:39:50Z")

</div>

> [@KZ-Spectra](#):
>
> Why is such an error thrown? What can I do to perform the operator I want?

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

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [April 5, 2023, 8:27pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131/3 "2023-04-05T20:27:04Z")

</div>

Perhaps a `Circulant` matrix, or something similar? Using `ToeplitzMatrices.jl`:

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

```

---

<div class="post-metadata">

### Author: ![KZ-Spectra](https://avatars.discourse-cdn.com/v4/letter/k/2acd7d/32.png) [@KZ-Spectra](https://discourse.julialang.org/u/KZ-Spectra)
#### Post date: [April 5, 2023, 9:17pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131/5 "2023-04-05T21:17:37Z")

</div>

We get condensed syntax which is nice, but what is the benefit of using the `Circulant` matrix versus the following?

```julia
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;

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 5, 2023, 9:54pm UTC](https://discourse.julialang.org/t/modifying-a-tridiagonal-matrix/97131/6 "2023-04-05T21:54:30Z")

</div>

A `Circulant`-typed matrix is likely to take advantage of the [structural properties](https://en.wikipedia.org/wiki/Circulant_matrix) 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.
