|
| 1 | +""" |
| 2 | + tridiagonal_solver(a, b, c, d) |
| 3 | +
|
| 4 | +Tridiagonal solver |
| 5 | +
|
| 6 | +# Description |
| 7 | +
|
| 8 | +Converted into a R code from the original code of Gordon Bonan: Bonan, G. |
| 9 | +(2019). Climate Change and Terrestrial Ecosystem Modeling. Cambridge: |
| 10 | +Cambridge University Press. doi:10.1017/9781107339217 |
| 11 | +
|
| 12 | +Solve for U given the set of equations R * U = D, where U is a vector |
| 13 | +of length N, D is a vector of length N, and R is an N x N tridiagonal |
| 14 | +matrix defined by the vectors A, B, C each of length N. A(1) and |
| 15 | +C(N) are undefined and are not referenced. |
| 16 | +
|
| 17 | + |B(1) C(1) ... ... ... | |
| 18 | + |A(2) B(2) C(2) ... ... | |
| 19 | +R = | A(3) B(3) C(3) ... | |
| 20 | + | ... A(N-1) B(N-1) C(N-1)| |
| 21 | + | ... ... A(N) B(N) | |
| 22 | +
|
| 23 | +The system of equations is written as: |
| 24 | +
|
| 25 | + A_i * U_i-1 + B_i * U_i + C_i * U_i+1 = D_i |
| 26 | +
|
| 27 | +for i = 1 to N. The solution is found by rewriting the |
| 28 | +equations so that: |
| 29 | +
|
| 30 | + U_i = F_i - E_i * U_i+1 |
| 31 | +
|
| 32 | +# Return |
| 33 | +- `Solution: U` |
| 34 | +
|
| 35 | +# Example |
| 36 | +```julia |
| 37 | +tridiagonal_solver!(a, b, c, d, e, f, u; ibeg) |
| 38 | +``` |
| 39 | +""" |
| 40 | +function tridiagonal_solver!(a::V, b::V, c::V, d::V, e::V, f::V, u::V; |
| 41 | + ibeg::Int=1, N::Int=length(a)) where {T<:Real,V<:AbstractVector{T}} |
| 42 | + |
| 43 | + # e = fill(NaN, N - 1) |
| 44 | + e[ibeg] = c[ibeg] / b[ibeg] |
| 45 | + @inbounds for i in ibeg+1:(N-1) |
| 46 | + e[i] = c[i] / (b[i] - a[i] * e[i-1]) |
| 47 | + end |
| 48 | + |
| 49 | + # f = fill(NaN, N) |
| 50 | + f[ibeg] = d[ibeg] / b[ibeg] |
| 51 | + @inbounds for i in ibeg+1:(N) |
| 52 | + f[i] = (d[i] - a[i] * f[i-1]) / (b[i] - a[i] * e[i-1]) |
| 53 | + end |
| 54 | + |
| 55 | + # u = fill(NaN, N) |
| 56 | + u[N] = f[N] |
| 57 | + @inbounds for i in N-1:-1:ibeg |
| 58 | + u[i] = f[i] - e[i] * u[i+1] |
| 59 | + end |
| 60 | + return u |
| 61 | +end |
| 62 | + |
| 63 | +function tridiagonal_solver(a::V, b::V, c::V, d::V; |
| 64 | + ibeg::Int=1, N::Int=length(a)) where {T<:Real,V<:AbstractVector{T}} |
| 65 | + |
| 66 | + e = fill(NaN, N - 1) |
| 67 | + f = fill(NaN, N) |
| 68 | + u = fill(NaN, N) |
| 69 | + tridiagonal_solver!(a, b, c, d, e, f, u; ibeg, N) |
| 70 | + return u |
| 71 | +end |
| 72 | + |
| 73 | + |
| 74 | +export tridiagonal_solver, tridiagonal_solver! |
0 commit comments