我需要构建如下所示的2D拉普拉斯:
,其中
,我是单位矩阵。到目前为止,我已经使用diags method of scipy完成了它,但我想知道是否有一种更聪明的方法可以使用block_diag method来完成它。有没有人试图用这种方法建立2D拉普拉斯?
我目前创建此方法的方法是使用此函数:
from scipy.sparse import diags
# Defining the size of the matrix
nx = 3
ny = 3
N = nx*ny
main_diag = [-4.0 for i in xrange(N)]
side_diag = []
for i in xrange(1,N):
if i%4 == 0:
side_diag.append(0)
else:
side_diag.append(1)
up_down_diag = [1.0 for i in xrange(N-4)]
diagonals = [main_diag,side_diag,side_diag,up_down_diag,up_down_diag]
laplacian = diags(diagonals, [0, -1, 1,nx,-nx], format="csr")
print laplacian.toarray()
答案 0 :(得分:2)
我用数组替换了你对列表的使用:
import numpy as np
from scipy import sparse
nx, ny = 3, 3
N = nx*ny
main_diag = np.ones(N)*-4.0
side_diag = np.ones(N-1)
side_diag[np.arange(1,N)%4==0] = 0
up_down_diag = np.ones(N-3)
diagonals = [main_diag,side_diag,side_diag,up_down_diag,up_down_diag]
laplacian = sparse.diags(diagonals, [0, -1, 1,nx,-nx], format="csr")
print laplacian.toarray()
制造
[[-4. 1. 0. 1. 0. 0. 0. 0. 0.]
[ 1. -4. 1. 0. 1. 0. 0. 0. 0.]
[ 0. 1. -4. 1. 0. 1. 0. 0. 0.]
[ 1. 0. 1. -4. 0. 0. 1. 0. 0.]
[ 0. 1. 0. 0. -4. 1. 0. 1. 0.]
[ 0. 0. 1. 0. 1. -4. 1. 0. 1.]
[ 0. 0. 0. 1. 0. 1. -4. 1. 0.]
[ 0. 0. 0. 0. 1. 0. 1. -4. 0.]
[ 0. 0. 0. 0. 0. 1. 0. 0. -4.]]
对角线的右侧是[1 1 1 0 1 1 1 0]模式吗?
对于像这样的小例子,它可能运行相同的速度,但是使用数组而不是列表的大尺寸应该更快 - 而且它与稀疏的基础代码更加一致。
像diags
这样的均匀对角线看起来相当不错。
我只使用了另一个SO问题的块格式。 https://stackoverflow.com/a/34124377/901925
coo
适用于由重叠较小的基质组成的基质,例如有限元刚度。但是将对角线重新编入coo
是很乏味的。
对于它的价值,sparse.diags
使用dia_matrix
,已将对角线列表转换为dia
data
矩阵。你可以看一下,但它的布局并不那么明显。要制作csr
矩阵,diags
会将此dia
格式转换为coo
,然后转换为csr
。但通常你不应该担心所有这些转换。使用在您的问题中最有意义的格式,让sparse
处理转换详细信息。
如果您想更多地探索块格式,您需要概述如何将问题视为块。
答案 1 :(得分:0)
N维拉普拉斯算子可以表示为一维拉普拉斯算子的Kronecker积:
import scipy.sparse as sp
def laplacian2D(N):
diag=np.ones([N*N])
mat=sp.spdiags([diag,-2*diag,diag],[-1,0,1],N,N)
I=sp.eye(N)
return sp.kron(I,mat,format='csr')+sp.kron(mat,I)