我正在使用ODE为一个自由落体对象编写代码,我不知道它说了什么,也不知道如何修复它。它告诉;*之后的TypeError:f((参数必须是可迭代的,而不是float;。谢谢
import numpy as np
import scipy.integrate as spi
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
m = 63974. # particle's mass in kg
k = 12. # drag coefficient
g = 9.81 # gravity acceleration
# The initial position is (0, 0).
v0 = np.zeros(4)
v0[1] = 1668.
v0[3] = 98.
def f(v, t0, k,):
# v has four components: v=[u, u'].
u, udot = v[:2], v[2:]
# We compute the second derivative u'' of u.
udotdot = (-k / m) * np.power(udot,2)
udotdot[1] -= g
# We return v'=[u', u''].
return np.r_[udot, udotdot]
def stop_condition(t,v0):
return v0[0]
stop_condition.terminal = True
stop_condition.direction = -1
t = np.linspace(0., 40., 100,)
t_span = (0,40)
sol = solve_ivp(f, v0, t_span,args=k, events=stop_condition)
print(sol.t_events)
再次提醒您,我不熟悉ODE。但是我已经阅读了scipy.intergrate.solve_ivp
的文档,在您的代码中发现了一些逻辑错误。
1.第一个错误TypeError: f() argument after * must be an iterable, not float
因为在solve_ivp
函数中,args=k
的参数,这表明k
将传递给f
函数。因此,您需要将其更改为[k]
。
# sol = solve_ivp(f, v0, t_span,args=k, events=stop_condition) # your code
sol = solve_ivp(f, v0, t_span,args=[k], events=stop_condition)
实现此操作后,会出现不同的错误。
<ipython-input-38-1a7549e0840c> in f(v, t0, k)
20 def f(v, t0, k,):
21 # v has four components: v=[u, u'].
---> 22 u, udot = v[:2], v[2:]
23 # We compute the second derivative u'' of u.
24 udotdot = (-k / m) * np.power(udot,2)
TypeError: 'float' object is not subscriptable
这告诉我f
函数中的v
参数有错误。
2.第二个错误,修复了fun
参数
阅读scipy.intergrate.solve_ivp
的文档表明,solve_ivp
的第一个位置参数是fun
,它是可调用的,并且您正确地放置了f
,一个可调用的fun
。但文献也指出fun
中的位置自变量是t,y
(fun(t,y)
(。假设v
是您的y
,那么您将它们反过来放置。
# def f(v, t0, k,): # this is yours
def f(t0, v, k):
现在,上一个错误已修复,但引发了另一个错误。
<ipython-input-41-b0878a24d79f> in f(t0, v, k)
23 # We compute the second derivative u'' of u.
24 udotdot = (-k / m) * np.power(udot,2)
---> 25 udotdot[1] -= g
26 # We return v'=[u', u''].
27 return np.r_[udot, udotdot]
IndexError: index 1 is out of bounds for axis 0 with size 0
这告诉我udotdot
的长度小于2。仔细阅读您的代码,我注意到udotdot
应该是长度为4的数组v
的一半。所以,我只是简单地在您的函数中打印出v
来进行检查。
def f(t0, v, k):
print('t:', t0)
print('v:', v)
输出:
t: 0.0
v: [ 0. 40.]
看到这些之后,我注意到v
是不正确的。应该是[0, 1668, 0, 98]
3.solve_ivp
中的v0
和t_span
位置自变量错误
在再次阅读了scipy.intergrate.solve_ivp
的文档后,我注意到代码中v0
和t_span
的位置参数应该切换。
# sol = solve_ivp(f, v0, t_span,args=[k], events=stop_condition) # the code so far
sol = solve_ivp(f, t_span, v0, args=[k], events=stop_condition)
完成此操作后,将引发一个新错误。
TypeError: stop_condition() takes 2 positional arguments but 3 were given
与您以前的错误不同,这次的错误非常明显。因为f
接受3个参数,所以stop_condition
也应该接受3个。
4.更新stop_condition()
# def stop_condition(t, v0): # your code
def stop_condition(t, v0, k):
return v0[0]
通过修复这些行,您的代码应该可以正常工作。然而,我不确定最终输出是否等于您想要的输出(再说一次,我不熟悉ODE(。
奖金
对于f()
和stop_condition()
函数,可以使用*args
和*kwargs
而不是k
。我不打算详细解释。如果你想学习如何使用它们,请阅读这篇文章。