python - 如何将参数传递给`scipy.integrate.solve_ivp`中的事件函数?
问题描述
odeint
Scipy正在远离solve_ivp
,它不再支持为动态函数传递额外的参数。相反,建议使用 lambda。但是,当我对事件尝试相同的操作时,它们无法正常工作。有什么想法吗?
MWE(从文档页面修改):
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
# dynamics of a simple mass with ballistic flight and a bit of drag
def cannon(t, y, p):
return [y[2],y[3], -p['friction']*y[2], p['gravity']-p['friction']*y[3]]
# termination condition: cannonball hits the ground
# this event does not require parameters, but more complex events might
def hit_ground1(t, y, p):
return y[1]
hit_ground1.terminal = True
hit_ground1.direction = -1
def hit_ground2(t,y):
return y[1]
hit_ground2.terminal = True
hit_ground2.direction = -1
p = {'gravity':-1,'friction':0} # paramters as a dict
y0 = [0, 0, 0, 10] # initial conditions
t_span = [0, 22] # integration time a bit over what is necessary
# we can handle dynamics with parameters by using lambdas
# but somehow the same doesn't seem to work with events
sol1 = solve_ivp(fun=lambda t,x:cannon(t,x,p), t_span=t_span,
y0=y0, events=hit_ground2, max_step=0.01)
sol2 = solve_ivp(fun=lambda t,x:cannon(t,x,p), t_span=t_span,
y0=y0, events=lambda t,x:hit_ground1(t,x,p), max_step=0.01)
print(sol1.t[-1]) # terminates correctly
print(sol2.t[-1]) # continues integrating
plt.plot(sol1.t,sol1.y[1], linewidth=3)
plt.plot(sol2.t,sol2.y[1],'--',linewidth=3)
plt.show()
解决方案
事件的属性terminal
和direction
不会转移到您的 lambda 表达式中。您需要将 lambda 保存到一个变量中,并在那里而不是在hit_ground1
函数上添加属性。
def hit_ground1(t, y, p):
return y[1]
ground_event = lambda t,x:hit_ground1(t,x,p)
ground_event.terminal = True
ground_event.direction = -1
使用此事件,它应该按预期工作。
sol2 = solve_ivp(fun=lambda t,x:cannon(t,x,p), t_span=t_span,
y0=y0, events=ground_event, max_step=0.01)
推荐阅读
- r - 总结一下,nrow 不返回任何内容
- python - 从表格数据训练深度学习模型时,损失总是 nan
- react-native - 如何使用选项卡视图滚动全屏?
- node.js - 在 node.js 中创建多个数据库
- ansible - 如何确定主机是容器还是具有可靠事实的虚拟机?
- python - 将特定键添加到“模板”
- signalr - 如何注册 Webhook?
- php - SQL和PHP中结果之间的utf8_encode区别
- vb.net - 保存图片框中的图像
- javascript - Next.js 应用程序使用 minikube 在本地机器上的 docker 容器中构建,但不构建在使用谷歌云 kubernetes 设置的登台上