Search code examples
pythonnumpyscipylinear-algebrasparse-matrix

How to put one entry across an entire diagonal for a sparse matrix in Python


I am seeking to construct a matrix of which I will calculate the inverse. This will be used in an implicit method for solving a nonlinear parabolic PDE. My current calculations are, which will become obvious to why, giving me a singular (no possible inverse) matrix. For context, in reality the matrix will be of dimension 30 by 30 but in these examples I am using smaller matrices for testing purposes.

Say I want to create a large square sparse matrix. Using spdiags only allows you to input members of the main, lower and upper diagonals individually. So how to you make it so that each diagonal has one value for all its entries?

Example Code:

import numpy as np 
from scipy.sparse import spdiags
from numpy.linalg import inv 

updiag = -0.25
diag = 0.5
lowdiag = -0.25
        
Jdata = np.array([[diag], [lowdiag], [updiag]])
Diags = [0, -1, 1]
J = spdiags(Jdata, Diags, 3, 3).toarray() 
print(J)
inverseJ = inv(J)
print(inverseJ)

This would produce an 3 x 3 matrix but only with the first entry of each diagonal given. I wondered about using np.fill_diagonal but that would require a matrix first and only does the main diagonal. Am I misunderstanding something?


Solution

  • The first argument of spdiags is a matrix of values to be used as the diagonals. You can use it this way:

    Jdata = np.array([3 * [diag], 3 * [lowdiag], 3 * [updiag]])
    Diags = [0, -1, 1]
    J = spdiags(Jdata, Diags, 3, 3).toarray() 
    print(J)
    # [[ 0.5  -0.25  0.  ]
    #  [-0.25  0.5  -0.25]
    #  [ 0.   -0.25  0.5 ]]