解决稀疏的Ax = b

时间:2018-08-18 05:43:38

标签: matrix scipy sparse-matrix linear-algebra umfpack

我需要求解Ax=b,其中A是表示PDE的有限差分法的矩阵。二维问题的A的典型大小约为(256 ^ 2)x(256 ^ 2),它由一些对角线组成。以下示例代码是我构造A的方式:

N = Nx*Ny  # Nx is no. of cols (size in x-direction), Ny is no. rows (size in y-direction)

# finite difference in x-direction
up1 = (0.5)*c
up1[Nx-1::Nx] = 0
down1 = (-0.5)*c
down1[::Nx] = 0
matX = diags([down1[1:], up1[:-1]], [-1,1], format='csc')

# finite difference in y-direction
up1 = (0.5)*c
down1 = (-0.5)*c
matY = diags([down1[Nx:], up1[:N-Nx]], [-Nx,Nx], format='csc')

matXmatY加在一起会得到四个对角线。上面是针对二阶离散化的。对于四阶离散化,我有八个对角线。如果我有二阶导数,那么主对角线也将为非零。

我使用以下代码进行实际求解:

# Initialize A_fixed, B_fixed

if const is True: # the potential term V(x) is time-independent
    A = A_fixed + sp.sparse.diags(V_func(x))
    B = B_fixed + sp.sparse.diags(V_func(x))
    A_factored = sp.sparse.linalg.factorized(A)

for idx, t in enumerate(t_steps[1:],1):
    # Solve Ax=b=Bu

    if const in False: #
        A = A_fixed + sp.sparse.diags(V_func(x,t))
        B = B_fixed + sp.sparse.diags(V_func(x,t))

    psi_n = B.dot(psi_old)

    if const is True:
        psi_new = A_factored(psi_n)
    else:
        psi_new = sp.sparse.linalg.spsolve(A,psi_n,use_umfpack=False)

    psi_old = psi_new.copy()

我有几个问题:

  1. 解决科学难题中的Ax=b的最佳方法是什么?我在spsolve库中使用sp.sparse.linalg,该库使用LU分解。我尝试将标准sp.linalg.solve用于密集矩阵,但是速度慢得多。我还尝试过使用sp.sparse.linalg库中的所有其他迭代求解器,但是它们也较慢(对于1000x1000,它们都需要花费几秒钟,而对于spsolve来说则不到半秒,而我A可能会更大)。有其他替代方法可以进行计算吗?

编辑:我要解决的问题实际上是时间相关的薛定inger方程。如果电位项与时间无关,那么如建议的那样,我可以先对矩阵A进行预分解以加速代码,但是如果电位随时间变化,这将不起作用,因为我需要更改每个时间步上两个矩阵AB的对角项。对于此特定问题,是否有任何方法可以使用类似于预分解或其他方法的方法来加快代码的速度?

  1. 我已经安装了umfpack。我尝试将use_umfpack设置为True和False进行测试,但是令人惊讶的是use_umfpack=True花费的时间几乎是use_umfpack=False的两倍。我认为拥有此软件包可以加快速度。知道是什么情况吗? (PS:如果有任何区别,我正在使用Anaconda Spyder运行代码)

我已经使用cProfile来分析我的代码,几乎所有的时间都花在了spsolve的那一行上。因此,我认为代码的其余部分(矩阵/问题初始化)已经过优化,这是需要解决的矩阵求解部分。

谢谢。

0 个答案:

没有答案