【发布时间】:2021-08-02 06:11:03
【问题描述】:
(TLDR:当您将方程作为纯 Python 列表传递时,SymPy 的 linsolve 函数无法求解线性方程组,该方程组是通过将有限差分法应用于 ODE BVP 生成的,但能够这样做说SymPy 的 Matrix 函数中的方程式列表。这可能是一个需要修复的错误,特别是考虑到在 SymPy 文档中,the example 他们给你的让他们将列表作为参数传递给 linsolve。)
我有一个边值问题常微分方程,我打算使用有限差分法求解。我的 ODE,在 SymPy 表示中,是x*y(x).diff(x,2) + y(x).diff(x) + 500 = 0,有y(1)=600 和y(3.5)=25。整个代码如下:
import sympy as sp
from numpy import *
from matplotlib.pyplot import *
y = sp.Function('y')
ti = time.time()
steps = 10
ys = [ y(i) for i in range(steps+1) ]
ys[0], ys[-1] = 600, 25
xs = linspace(1, 3.5, steps+1)
dx = xs[1] - xs[0]
eqns = [ xs[i]*(ys[i-1] - 2*ys[i] + ys[i+1])/dx**2 +
( ys[i+1] - ys[i-1] )/2/dx + 500
for i in range(1, steps) ]
ys[1:-1] = sp.linsolve(eqns, ys[1:-1]).args[0]
scatter(xs, ys)
tf = time.time()
print(f'Time elapsed: {tf-ti}')
十个步骤,这工作得很好。但是,如果我立即超过 11 步,SymPy 将不再能够求解线性方程组。尝试绘制结果会引发TypeError: can't convert expression to float。检查 y 值 ys 的列表会发现其中一个变量,特别是倒数第二个变量,并没有被 sympy 的 linsolve 解决,而是根据这个未解决的变量来解决其他变量的解决方案。例如,如果我有 50 个步骤,倒数第二个变量是 y(49),这在其他未知数的解决方案中具有特色,并且未解决,例如2.02061855670103*y(49) - 26.1340206185567。相比之下,在我解决的另一个 BVP ODE 中,y(x).diff(x,2) + y(x).diff(x) + y(x) - 1 与 y(0)=1.5 和 y(3)=2.5,无论我想要 10、50 还是 200 步都没有任何问题。它很好地解决了所有变量,但这似乎是一个特殊的例外,因为我在许多其他 ODE 中遇到了上述问题。
SymPy 的不一致在这里非常令人沮丧。唯一的安慰是,在我遇到这个问题之前,我实际上已经用我想要的不同数量的步骤解决了几次。我将eqns 变量包含在sympy 的Matrix 函数中,就像ys[1:-1] = sp.linsolve(sp.Matrix(eqns), ys[1:-1]).args[0] 一样,只是因为它在终端中以这种方式显示得更好。但为了解决在脚本文件中,我认为将其包裹在 sp.Matrix 中是不必要的,我自然将其删除以简化事情。
【问题讨论】:
标签: python-3.x matrix sympy differential-equations finite-difference