Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LinearAlgebra - inv() producing NaNs when called on a Tridiagonal #29630

Closed
MichaelDS opened this issue Oct 13, 2018 · 2 comments
Closed

LinearAlgebra - inv() producing NaNs when called on a Tridiagonal #29630

MichaelDS opened this issue Oct 13, 2018 · 2 comments
Labels
bug Indicates an unexpected problem or unintended behavior linear algebra Linear algebra

Comments

@MichaelDS
Copy link

I’m creating a 90x90 tridiagonal matrix using the function below, which I store in the variable A90. When I call inv(A90), I get a matrix of all NaNs, but if I call inv(Matrix(A90)), the inverse is successfully computed. Is this behavior expected?

using LinearAlgebra
function central_difference_discretization(N; dfunc = x -> 12x^2 - 2N^2,
                                           dufunc = x -> N^2 + 4N*x,
                                           dlfunc = x -> N^2 - 4N*x,
                                           bfunc = x -> 114ℯ^-x * (1 + 3x),
                                           b0 = 0, bf = 57/ℯ,
                                           x0 = 0, xf = 1)
    h = 1/N
    d, du, dl, b = map(dfunc, (x0+h):h:(xf-h)), map(dufunc, (x0+h):h:(xf-2h)), 
                   map(dlfunc, (x0+2h):h:(xf-h)), map(bfunc, (x0+h):h:(xf-h))
    b[1] -= dlfunc(x0)*b0     # subtract the boundary term 
    b[end] -= dufunc(xf)*bf   # subtract the boundary term 
    Tridiagonal(dl, d, du), b
end


A90, b90 = central_difference_discretization(90)

typeof(A90)  # Tridiagonal{Float64,Array{Float64,1}}

inv(A90)  # Produces a matrix of all NaNs
inv(Matrix(A90))  # Successfully computes the inverse

A80, b80 = central_difference_discretization(80)
inv(A80)  # Works fine on Tridiagonals smaller than 82x82

@tpapp suggested that it might be as issue related to conditioning and the Tridiagonal inversion method, which I suspect as well because my code generates an ill-conditioned matrix by design.

@RalphAS
Copy link

RalphAS commented Oct 14, 2018

This issue arises because the special-case method for inverting tridiagonals (inv_usmani) has no scaling protection. Using the factorization instead

lu(A90) \ Matrix(1.0I,size(A90))

gives a good result via a stable banded scheme (faster than working with a full matrix).

Furthermore, inv_usmani is currently type-unstable, so it takes much longer.

@andreasnoack
Copy link
Member

@RalphAS Thanks for identifying the problem. I think we should just remove inv_usmani and instead use the fallback which solves against the identity.

@andreasnoack andreasnoack added bug Indicates an unexpected problem or unintended behavior linear algebra Linear algebra labels Oct 16, 2018
andreasnoack added a commit that referenced this issue Oct 17, 2018
* Use a stable inverse for Tridiagonal and SymTridiagonal

Fixes #29630

* Fix ldlt in the complex case
KristofferC pushed a commit that referenced this issue Oct 19, 2018
* Use a stable inverse for Tridiagonal and SymTridiagonal

Fixes #29630

* Fix ldlt in the complex case

(cherry picked from commit 00bb4f2)
KristofferC pushed a commit that referenced this issue Feb 11, 2019
* Use a stable inverse for Tridiagonal and SymTridiagonal

Fixes #29630

* Fix ldlt in the complex case

(cherry picked from commit 00bb4f2)
KristofferC pushed a commit that referenced this issue Feb 20, 2020
* Use a stable inverse for Tridiagonal and SymTridiagonal

Fixes #29630

* Fix ldlt in the complex case

(cherry picked from commit 00bb4f2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior linear algebra Linear algebra
Projects
None yet
Development

No branches or pull requests

3 participants