我正在学习如何在Python中采用有限差分方法,以泊松方程为例。但是,当我运行时,一切都很好,直到反向部分中的A=ASparse.toarray()
行代码为止,在该行中我看到了帖子标题中提到的错误。为什么会这样,从何处以及如何解决呢?
代码:
import numpy as np
import scipy
import scipy.sparse as sps
import matplotlib.pyplot as plt
# Elliptic PDE problems can be converted to Linear Algebra problems!!!
# Begin with making the matrix A for conversion to a linear system
J = 5
L = 4
I = (J - 1) * (L - 1)
LeadDiag = -4 * np.ones(I)
diag=[LeadDiag]
ASparse = sps.diags(diagonals=diag, offsets=[0])
ASparse = sps.csc_matrix(ASparse)
A = ASparse.toarray()
UpperDiag = np.ones(I - 1)
for i in range(0, I - 1):
if np.mod(i+1, L-1) == 0:
UpperDiag[i] = 0
LowerDiag = np.ones(I - 1)
for i in range(0, I - 1):
if np.mod(i+1, L-1)==0:
LowerDiag[i]=0
SuperDiag = np.ones(I - (L - 1))
SubDiag = np.ones(I - (L - 1))
Diag = [LeadDiag, UpperDiag, LowerDiag, SuperDiag, SubDiag]
ASparse = sps.diags(diagonals=Diag, offsets=[0, 1, -1, L-1, -(L-1)])
ASparse = sps.csc_matrix(ASparse)
A = ASparse.toarray()
print(A)
# Short way to make A
def createA(J, L):
I = (J - 1)*(L - 1)
LeadDiag = -4 * np.ones(I)
UpperDiag = np.ones(I - 1)
for i in range(0, I - 1):
if np.mod(i + 1, L - 1)==0:
UpperDiag[i] = 0
LowerDiag = np.ones(I - 1)
for i in range(1, I - 1):
if np.mod(i+1, L-1)==0:
LowerDiag[i] = 0
SuperDiag=np.ones(I - (L - 1))
SubDiag=np.ones(I-(L-1))
Diag=[LeadDiag, UpperDiag, LowerDiag, SuperDiag, SubDiag]
ASparse = sps.diags(diagonals=Diag, offsets=[0, 1, -1, L-1, -(L-1)])
ASparse=sps.csc_matrix(ASparse)
print(ASparse)
# Define f(x,y) (rho) and plot it on the grid given by (x_j, y_j), choosing J = 100, L = 100, L_x = L_y = 100
def funct(x, y, L_x, L_y):
A = -1/ (np.square(2 * np.pi / L_x) + np.square(np.pi / L_y))
return np.sin(2 * np.pi / L_x * x) * np.sin(np.pi/ L_y * y)
J = 100
L = 100
L_x = 10
L_y = 10
x = np.linspace(0, L_x, J+1, endpoint=True)
y = np.linspace(0, L_y, L+1, endpoint=True)
xv, yv = np.meshgrid(x, y)
print(x.shape, y.shape)
f = funct(xv, yv, L_x, L_y)
print(f.shape)
plt.imshow(f)
plt.colorbar()
plt.show()
# BOUNDARIES
print(f.shape)
Delt = L_x/J
fTemp = np.copy(f)
fTemp[1, :] = fTemp[1, :]+0
fTemp[L, :] = fTemp[L, :]+0
fTemp[:, 1] = fTemp[:, 1]+0
fTemp[:, J] = fTemp[:, J]+0
f1D = np.square(Delt)*fTemp[1:J, 1:L].reshape((J-1)*(L-1))
print(f1D.shape)
#Define the matrix A and compute its inverse
import scipy.sparse.linalg
ASparse=createA(J, L)
A=ASparse.toarray()
print(A.shape)
ASparseInv = sps.linalg.inv(ASparse)
# Solve the Linear Algebra problem!
u=np.dot(ASparseInv.toarray(), f1D)
print(u.shape)
u2D = u.reshape((J - 1), (L-1))
print(u2D.shape)
# Analytical plot
def uexactfunct(x, y, L_x, L_y):
A=-1/np.square(2 * np.pi/L_x) + np.square(np.pi/L_y)
return A*np.sin(2 * np.pi/L_x * x)*np.sin(np.pi/L_y * y)
# Analytical vs numerical plots
plt.imshow(u2D)
plt.colorbar()
plt.show()
plt.imshow(uexactfunct(xv, yv, L_x, L_y))
plt.colorbar()
plt.show()
plt.plot(x[1:-1], u2D[J/2+1, :], 'x', label='numerical')
plt.plot(x[1:-1], uexactfunct(x[1:-1], y[J/2+2], L_x, L_y), '-', label='analytical')
plt.legend()
plt.show()
plt.plot(y[1:-1], u2D[:, L/2 + 1], 'x', label='numerical')
plt.plot(y[1:-1], uexactfunct(x[L/2 + 2], y[1:-1], L_x, L_y), '-', label='analytical')
plt.legend()
plt.show()
您的createA()
-函数不返回任何内容。因此,此时ASparse为None
,显然它没有toarray()
方法。因此,您将希望实现createA以返回I,但是即使那样也只是返回一个整数。
您实际上想做什么:
def createA(J, L):
I = (J - 1) * (L - 1)
LeadDiag = -4 * np.ones(I)
diag = [LeadDiag]
ASparse = sps.diags(diagonals=diag, offsets=[0])
ASparse = sps.csc_matrix(ASparse)
return ASparse
在脚本末尾的绘图中,您必须将索引转换为整数。
plt.plot(x[1:-1], u2D[J/2+1, :], 'x', label='numerical')
必须是
plt.plot(x[1:-1], u2D[int(J/2+1), :], 'x', label='numerical')
我建议您使用调试器,因此您了解脚本中正在发生的事情。特别是在处理矩阵和索引时。很多小事情都会出错:)