PDE Solving: 'NoneType' has no attribute 'toarray' 错误
PDE Solving: 'NoneType' has no attribute 'toarray' error
我正在学习如何在 Python 中使用有限差分法,以泊松方程为例。但是当我 运行 时,一切都很好,直到我得到 post 标题中提到的错误的逆向部分中的 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()
- 函数没有 return 任何东西。所以 ASparse 在这一点上是 None
,显然没有 toarray()
方法。因此,您需要将 createA 实现为 return I,但即使只是 returns 一个整数。
你真正想做的事情:
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')
我建议您使用调试器,这样您就可以了解脚本中发生了什么。特别是当您使用矩阵和索引时。很多小事都会出错 :)
我正在学习如何在 Python 中使用有限差分法,以泊松方程为例。但是当我 运行 时,一切都很好,直到我得到 post 标题中提到的错误的逆向部分中的 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()
- 函数没有 return 任何东西。所以 ASparse 在这一点上是 None
,显然没有 toarray()
方法。因此,您需要将 createA 实现为 return I,但即使只是 returns 一个整数。
你真正想做的事情:
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')
我建议您使用调试器,这样您就可以了解脚本中发生了什么。特别是当您使用矩阵和索引时。很多小事都会出错 :)