将GSL ODE解算器转换为Python

时间:2013-04-25 15:47:37

标签: python cython gsl pygsl

我使用类似于example的GSL ODE求解器解决了一组耦合的ODE。目前,这是通过在python中编写文件来实现自动化,例如

text = """
#include <stdio.h>
#include <gsl/gsl_errno.h>

...

"""

然后用相关的单词替换text中的字符串并写入文件script.c。然后我使用os.system来运行它,例如

os.system("gcc -Wall -I/usr/local/include -c script.c")
os.system("gcc -static script.o -lgsl -lgslcblas -lm")
os.system("./a.out >  %s" % (file_name) )

所有这些都非常优雅,所以我一直在阅读有关替代品的内容,并且到目前为止已经发现了PyGSL,CythonGSL。这些似乎缺乏适当的文档,我不够聪明,无法弄清楚它们是如何工作的!

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:4)

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文件的顶级目录中。像许多python包一样 构建C库,在构建步骤期间打印 lot 警告,但它 完成没有错误。

这里有一些代码演示了如何在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()

结果图:

plot of the solution generated by pygsl

答案 1 :(得分:1)

如果您可以编写一个带有参数的C库,而不是使用Python代码中C代码的字符串替换,那么您可以单独编译C库,并使用CFFI从Python代码中调用函数。

这些替换有多复杂/动态?