scipy.solve_ivp:在事件再次发生时终止轨迹

2024-04-25 20:52:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我想计算返回初始状态所需的时间。作为一个玩具例子,让我们取一个简谐振子d/dt(x,y)=(y,-x),具有初始条件(x,y)=(1,0)。

我希望代码返回T=6.28。。。(=2π),因为这是返回到y为正的初始条件所需的时间。当达到这一点时,它应该停止集成

import numpy as np
from scipy.integrate import solve_ivp

def f(t,x):
    return [x[1], -x[0]]

def event(t,x):
    return x[0]

event.direction = 1
event.terminal = True # Try false, this gives the result but integrates beyond the event I need.

initial_condition = [0, 1]

sol = solve_ivp(f, [0, 10], initial_condition, method='RK45',dense_output=True, \
                events = event, rtol=1e-6, atol=3e-6)

print(sol.t_events)

问题是设置event.terminal = True会直接引导集成,因为事件在t=0时满足。有没有办法让集成仅在事件满足两次后停止


Tags: theimporteventtruereturndef时间事件
2条回答

以下是我一直在使用的解决方法,以供将来参考:

将初始条件设置为事件前面的少量,例如initial_condition = [1e-100, 1]而不是[0, 1]。它似乎不会影响轨迹,即使对于更高自由度的混沌系统,但它不会在t=0时触发事件

另一个可行的解决方法是在一段时间内不发生事件的情况下进行集成,然后将结果用作进一步集成的初始条件,这次是在事件发生的情况下进行集成。我怀疑这个答案对任何人都有用,但我发布这个只是为了完整

与您的解决方法类似,我将1e-100添加到事件中,而不是添加到初始状态。这样做的好处是根本不会影响轨迹,甚至理论上也不会

当然,这确实意味着你未来的事情会提前一小部分发生,但这取决于你的情况,如果这对你来说很重要的话

对于您编写的示例代码,这将使您的事件如下所示:

def event(t,x):
    return x[0] + 1e-100

我尝试过的不起作用的一件事是在集成过程中修改终止参数。我想如果我从event.terminal = False开始,然后在事件定义集event.terminal = True内,那么它将在第一个事件中继续(t=0),并在第二个事件中终止。但是,如果在集成过程中更改了参数,它似乎会忽略更改的参数

(这个问题与Solve_ivp integration gets stuck if initial condition triggers event with terminal = True有关,但我没有名声去标记任何东西。)

相关问题 更多 >