是否有可能让scipy.integrate.odeint与一对向量(或向量向量)一起工作

时间:2015-04-02 00:14:25

标签: python scipy ipython vectorization

使用scipy.integrate.odeint解决自由落体问题

进口

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

%matplotlib inline

常量和积分间隔

G = 9.8    # m / sec / sec

# First 1 second of motion
t = np.arange (0, 1.1, 0.1)

速度的矢量解

这里我们返回velocity_vector()中的加速度矢量,设置初始V0,并积分1秒。我们期望Vx和Vy是常数,Vz线性递减,斜率为-G。

def velocity_vector (x, t, params):
    # x = (Vx, Vy, Vz)
    # Ordinary differential equation - velocity of an object in frictionless free-fall.
    g = params
    acceleration = np.array ([0, 0, -g])
    return acceleration

v0 = np.array ([1, 2, 0])
soln = odeint (velocity_vector, v0, t, args = (G,))

fig = plt.figure (1, figsize = (8,8))

ax1 = fig.add_subplot(311)
ax1.plot(t, soln [:,0])
ax1.set_xlabel ('time')
ax1.set_ylabel ('Vx')

ax1 = fig.add_subplot(312)
ax1.plot(t, soln [:,1])
ax1.set_xlabel ('time')
ax1.set_ylabel ('Vy')

ax1 = fig.add_subplot(313)
ax1.plot(t, soln [:,2])
ax1.set_xlabel ('time')
ax1.set_ylabel ('Vz')

plt.show ()

一维位置和速度的矢量解

这里我们返回运动()中z维度的加速度和速度矢量,设置初始Z0和V0,并积分1秒。我们期望Xz是二次的,并且Vz线性地减小,具有-G的斜率。

def motion (x, t, params):
    # x = (Sx, Vx)
    # Ordinary differential equation - velocity of an object in frictionless free-fall.
    g = params
    acceleration = np.array ([-g * t, -g])
    return acceleration

v0 = np.array ([5.0, 0])
soln = odeint (motion, v0, t, args = (G,))

fig,axes = plt.subplots(1, 2) # one row, two columns
fig.subplots_adjust(wspace=0.6)

axes[0].plot(t, soln [:,0])
axes[0].set_xlabel ('time')
axes[0].set_ylabel ('Sz')

axes[1].plot(t, soln [:,1])
axes[1].set_xlabel ('time')
axes[1].set_ylabel ('Vz')

plt.show ()

一维位置和速度的矢量解

让我们看看我们是否可以通过提供向量列表并返回向量列表来组合这两种方法。

def position_and_velocity (x, t, params):
    # x = (S, V) as vectors
    # Ordinary differential equation - velocity of an object in frictionless free-fall.
    g = params
    acceleration = np.array ([-g * t, -g])
    return acceleration

s = np.array ([0, 0, 5])
v = np.array ([1, 2, 0])
SV0 = np.array ([s, v])
soln = odeint (position_and_velocity, SV0, t, args = (G,))

#fig,axes = plt.subplots(1, 2) # one row, two columns
#fig.subplots_adjust(wspace=0.6)

#axes[0].plot(t, soln [:,0])
#axes[0].set_xlabel ('time')
#axes[0].set_ylabel ('Sz')

#axes[1].plot(t, soln [:,1])
#axes[1].set_xlabel ('time')
#axes[1].set_ylabel ('Vz')

#plt.show ()


---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-29-a12f336fc4fc> in <module>()
      9 v = np.array ([1, 2, 0])
     10 SV0 = np.array ([s, v])
---> 11 soln = odeint (position_and_velocity, SV0, t, args = (G,))
     12 
     13 #fig,axes = plt.subplots(1, 2) # one row, two columns


/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/scipy/integrate/odepack.py in odeint(func, y0, t, args, Dfun, col_deriv, full_output, ml, mu, rtol, atol, tcrit, h0, hmax, hmin, ixpr, mxstep, mxhnil, mxordn, mxords, printmessg)
    146     output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
    147                              full_output, rtol, atol, tcrit, h0, hmax, hmin,
--> 148                              ixpr, mxstep, mxhnil, mxordn, mxords)
    149     if output[-1] < 0:
    150         print(_msgs[output[-1]])


ValueError: object too deep for desired array

似乎scipy.integrate.odeint()可以处理向量并使用向量求解方程,但不是像本例中的向量向量。有没有办法避免在这里返回六个不同的函数,而不仅仅是两个?

2 个答案:

答案 0 :(得分:1)

odeint仅处理1-d数组。要在组合系统上使用odeint,您必须将两个三维向量连接成一个6维向量。如果您正在尝试使用两个现有函数来计算两个三维系统的两个方程的右侧,那么您必须创建一个接受六维向量的新函数,将其拆分进入适当的3-d子向量,调用两个现有函数,然后将结果连接为6-d向量以返回。

答案 1 :(得分:1)

正如沃伦所说,答案是odeint确实需要一维数组。诀窍是设置传递给odeint的函数,以便它将传入的1-D数组转换为所需的矢量形式的第二个 - 在这种情况下,2个3-D矢量,以矢量形式执行计算,然后重塑结果作为一维数组返回。

答案使用方便的numpy reshape函数演示了该技术。

def position_and_velocity (x, t, params):
    # x = (S, V) as vectors
    # Ordinary differential equation - velocity of an object in frictionless free-fall.
    G = params
    g = np.array ([0, 0, -G])
    # convert the 6 element vector to 2 3 element vectors of displacement and velocity
    # to use vector formulation of the math
    s,v = x.reshape (2,3)
    acceleration = np.array ([v * t, g])
    # reshape the two vector results back into one for odeint
    return np.reshape (acceleration, 6)

s = np.array ([0, 0, 5])
v = np.array ([40, 10, 0])
SV0 = np.array ([s, v])
# pass reshaped displacement and velocity vector to odeint
soln = odeint (position_and_velocity, np.reshape (SV0, 6), t, args = (G,))