Search code examples
pythonscipysparse-matrix

Inserting sub-matrices into scipy sparse matrix


How can I efficiently insert sub-matrices at specific positions into my sparse matrix? Also, which scipy sparse matrix class is recommended for such an incremental construction?

More specifically, how can I fill the matrix M in the code below?

def rrd(mesh, rel_rotations, neighbors, R_0):
    M = scipy.sparse.lil_matrix((N_FACES*9*3,N_FACES*9))
    for i in range(0,N_FACES*27,27):
        for j in range(3):
            for k in range(0,N_FACES*9,9):
                M[i+j*9:i+(j+1)*9,k:k+9] = -np.eye(9)
    for i in range(len(rel_rotations)):
        diagonals = [
            rel_rotations[i][0][2],
            np.append(rel_rotations[i][0][1].repeat(3), rel_rotations[i][1][2].repeat(3)),
            np.append(rel_rotations[i][0][0].repeat(3), np.append(rel_rotations[i][1][1].repeat(3), 
            rel_rotations[i][2][2].repeat(3))),
            np.append(rel_rotations[i][1][0].repeat(3), rel_rotations[i][2][1].repeat(3)),
            rel_rotations[i][2][0].repeat(3)
        ]
        diag_rel_rotations = scipy.sparse.diags(diagonals, [-6,-3,0,3,6], shape=(9,9)).todense()
        mod = i % 3
        div = int((i-mod)/3)
        n_idx = neighbors[div][mod]
        M[i+mod*9:i+(mod+1)*9][n_idx*9:(n_idx+1)*9] = diag_rel_rotations

Slicing doesn't work here and I looked through some different types of sparse matrices but couldn't figure out which is the appropriate one for this problem.


Solution

  • lil is the right one for assignment.

    In [553]: M = sparse.lil_matrix((9,9), dtype=int)                                    
    In [554]: M                                                                          
    Out[554]: 
    <9x9 sparse matrix of type '<class 'numpy.int64'>'
        with 0 stored elements in LInked List format>
    
    In [555]: M[2:5, 3:6] = np.eye(3)                                                    
    In [556]: M                                                                          
    Out[556]: 
    <9x9 sparse matrix of type '<class 'numpy.int64'>'
        with 3 stored elements in LInked List format>
    In [557]: M.A                                                                        
    Out[557]: 
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 1, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 1, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0]])
    
    In [558]: d = sparse.diags([[1,2],[1,2,3],[2,3]], [-1,0,1]) 
    In [562]: M[0:3, 6:9] = d