为Scipy的“ odeint”的边界条件指定不同的时间点?

时间:2018-08-07 18:59:59

标签: python scipy ode

我正在尝试数值求解两个非线性ODE的系统。我正在使用Scipy的odeint函数。 odeint需要参数y0,该参数指定初始条件。但是,似乎假设y0的初始条件是在同一时间点开始的(即,两个条件都在t = 0时)。就我而言,我想指定针对不同时间指定的两个不同边界条件(即omega(t = 0)= 0,theta(t = 100)= 0)。我似乎不知道该怎么做,将不胜感激!

下面的一些示例代码:

from scipy.integrate import odeint

def pend(y, t, b, c):
    theta, omega = y
    dydt = [omega, -b*omega - c*np.sin(theta)]
    return dydt

b = 0.25
c = 5.0
t = np.linspace(0, 100, 101)

# I want to make these initial conditions specified at different times
y0 = [0, 0]

sol = odeint(pend, y0, t, args=(b, c))

1 个答案:

答案 0 :(得分:4)

odeint解决initial value problem。您描述的问题是两点boundary value problem。为此,您可以使用scipy.integrate.solve_bvp

您也可以看看scikits.bvp1lgscikits.bvp_solver,尽管bvp_solver似乎很久没有更新了。

例如,这是使用scipy.integrate.solve_bvp的方法。我更改了参数,以使解决方案不会衰减得这么快并且频率较低。当b = 0.25时,对于ω(0)= 0和|θ(0)|的所有解,衰减足够快,使得θ(100)≈0。大约为1。

函数bc将在t = 0和t = 100时传递[θ(t),ω(t)]的值。它必须返回两个值,它们是边界条件的“残差”。这只是意味着它必须计算必须为0的值。在您的情况下,只需返回y0[1](即ω(0))和y1[0](即θ(100))。 (如果在t = 0处的边界条件为ω(0) = 1,则返回值bc的第一个元素为y0[1] - 1。)

import numpy as np
from scipy.integrate import solve_bvp, odeint
import matplotlib.pyplot as plt


def pend(t, y, b, c):
    theta, omega = y
    dydt = [omega, -b*omega - c*np.sin(theta)]
    return dydt


def bc(y0, y1, b, c):
    # Values at t=0:
    theta0, omega0 = y0

    # Values at t=100:  
    theta1, omega1 = y1

    # These return values are what we want to be 0:
    return [omega0, theta1]


b = 0.02
c = 0.08

t = np.linspace(0, 100, 201)

# Use the solution to the initial value problem as the initial guess
# for the BVP solver. (This is probably not necessary!  Other, simpler
# guesses might also work.)
ystart = odeint(pend, [1, 0], t, args=(b, c,), tfirst=True)


result = solve_bvp(lambda t, y: pend(t, y, b=b, c=c),
                   lambda y0, y1: bc(y0, y1, b=b, c=c),
                   t, ystart.T)


plt.figure(figsize=(6.5, 3.5))
plt.plot(result.x, result.y[0], label=r'$\theta(t)$')
plt.plot(result.x, result.y[1], '--', label=r'$\omega(t)$')
plt.xlabel('t')
plt.grid()
plt.legend(framealpha=1, shadow=True)
plt.tight_layout()

plt.show()

这是结果的图,您可以看到ω(0)= 0和θ(100)= 0。

plot

请注意,边值问题的解决方案不是唯一的。如果我们将创建ystart修改为

ystart = odeint(pend, [np.pi, 0], t, args=(b, c,), tfirst=True)

找到了不同的解决方案,如下图所示:

plot2

在此解决方案中,摆锤几乎在倒置位置(result.y[0, 0] = 3.141592653578858处开始。它开始逐渐下降非常缓慢;逐渐下降得更快,并在t = 100时到达直线下降位置。

平凡解θ(t)≡0和ω(t)≡0也满足边界条件。