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')

我建议您使用调试器,这样您就可以了解脚本中发生了什么。特别是当您使用矩阵和索引时。很多小事都会出错 :)