【发布时间】:2018-08-14 12:18:33
【问题描述】:
我对 Python 比较陌生,在编写一段生成并求解微分方程组的代码时遇到了一些问题。
我这样做的方法是创建一组变量和系数,(x0, x1, ..., xn) 和 (c0, c1 ,..., cn ) 分别位于具有函数 var() 的列表中。然后在EOM1() 中构造方程。初始条件以及方程组都放在 EOM2() 中,并使用odeint 求解。
目前下面的代码运行,尽管效率不高,我认为这是因为odeint 会在每次交互时运行所有代码(这是我需要修复的其他问题,但不是主要问题!)。
import sympy as sy
from scipy.integrate import odeint
n=2
cn0list = [0.01, 0.05]
xn0list = [0.01, 0.01]
def var():
xnlist=[]
cnlist=[]
for i in range(n+1):
xnlist.append('x{0}'.format(i))
cnlist.append('c{0}'.format(i))
return xnlist, cnlist
def EOM1():
drdtlist=[]
for i in range(n):
cn1=sy.Symbol(var()[1][i])
xn0=sy.Symbol(var()[0][i])
xn1=sy.Symbol(var()[0][i+1])
eom=cn1*xn0*(1.0-xn1)-cn1*xn1-xn1
drdtlist.append(eom)
xi=sy.Symbol(var()[0][0])
xf=sy.Symbol(var()[0][n])
drdtlist[n-1]=drdtlist[n-1].subs(xf,xi)
return drdtlist
def EOM2(xn, t, cn):
x0, x1 = xn
c0, c1 = cn
f = EOM1()
output = []
for part in f:
output.append(part.evalf(subs={'x0':x0, 'x1':x1, 'c0':c0, 'c1':c1}))
return output
abserr = 1.0e-6
relerr = 1.0e-4
stoptime = 10.0
numpoints = 20
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
wsol = odeint(EOM2, xn0list, t, args=(cn0list,), atol=abserr, rtol=relerr)
我的问题是我很难让 Python 正确处理 Sympy 生成的变量。我用这条线解决了这个问题
output.append(part.evalf(subs={'x0':x0, 'x1':x1, 'c0':c0, 'c1':c1}))
在 EOM2() 中。不幸的是,我不知道如何将这一行概括为从 x0 到 xn 以及从 c0 到 cn 的变量列表。这同样适用于 EOM2(),
中的前一行 x0, x1 = xn
c0, c1 = cn
换句话说,我将 n 设置为任意数字,Python 有没有办法像我在上面手动输入的那样解释每个元素?我已经尝试了以下
output.append(part.evalf(subs={'x{0}'.format(j):var(n)[0][j], 'c{0}'.format(j):var(n)[1][j]}))
然而这产生了导致我首先使用 evalf 的错误,
TypeError: can't convert expression to float
有什么方法可以做我想做的事,生成一组 n 方程,然后用odeint 求解?
【问题讨论】:
-
你为什么首先使用符号?