*之后的TypeError:f()参数必须是可迭代的,而不是浮点值



我正在使用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中的v0t_span位置自变量错误

在再次阅读了scipy.intergrate.solve_ivp的文档后,我注意到代码中v0t_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。我不打算详细解释。如果你想学习如何使用它们,请阅读这篇文章。

最新更新