PyGSL 可能是一个合理的选择。(CythonGSL 也是,但我没试过。)
我正在运行 Ubuntu 12.04(64 位),对于这个安装,我使用的是 Anaconda python 发行版。(它可能适用于 Ubuntu 中的默认 Python,但我没有尝试。)
我从源代码安装了 GSL 1.15,并且我只是按照自述文件中的说明从源代码安装了 PyGSL 0.9.5。也就是说,我跑了
$ python setup.py build
$ python setup.py install
在提取的 tar 文件的顶层目录中。像许多构建 C 库的 python 包一样,在构建步骤期间会打印很多警告,但它完成时没有错误。
下面是一些演示在 PyGSL 中使用 ODE 求解器的代码:
#
# pendulum_demo.py
#
# Use PyGSL to solve the differential equations for a pendulum with
# friction. Plot the solution using matplotlib.
#
import numpy as np
import matplotlib.pyplot as plt
from pygsl import odeiv
def pendsys(t, y, args):
"""
The right-hand side of the first order system of differential equations.
"""
theta, v = y
g, b, L, m = args
f = np.zeros((2,))
f[0] = v
f[1] = -b * v / (m * L ** 2) - np.sin(theta) * g / L
return f
def pendjac(t, y, args):
"""
The Jacobian of the system.
"""
theta, v = y
g, b, L, m = args
jac = np.zeros((2, 2))
jac[0, 1] = 1.0
jac[1, 0] = -g / L * np.cos(theta)
jac[1, 1] = -b / (m * L ** 2)
dfdt = np.zeros((2,))
return jac, dfdt
# Pendulum parameter values
#
# Gravitational constant
g = 9.81
# Friction coefficient
b = 0.5
# Pendulum length
L = 1.0
# Pendulum bob mass
m = 2.0
# Initial conditions
theta0 = np.pi - 0.01
v0 = 0.0
y = [theta0, v0]
t = 0
# Solver control parameters.
abserr = 1e-11
relerr = 1e-9
stoptime = 12.0
# Create the GSL ODE solver
N = 2
step = odeiv.step_rk8pd(N, pendsys, pendjac, args=(g, b, L, m))
control = odeiv.control_y_new(step, abserr, relerr)
evolve = odeiv.evolve(step, control, N)
# h is the initial step size.
h = stoptime / 500.0
# The time values and points in the solution are saved in the lists
# tsol and ysol, respectively. The lists are initialized with
# the initial conditions.
tsol = [t]
ysol = [y]
# Call evolve.apply(...) until the solution reaches stoptime
while t < stoptime:
t, h, y = evolve.apply(t, stoptime, h, y)
tsol.append(t)
ysol.append(y)
tsol = np.array(tsol)
ysol = np.array(ysol)
plt.plot(tsol, ysol[:, 0], label=r'$\theta$')
plt.plot(tsol, ysol[:, 1], label='v')
plt.xlabel('t')
plt.grid(True)
plt.legend()
plt.title('Pendulum with Friction')
plt.show()
结果图: