简体   繁体   English

scipy.solve_ivp:第二次发生事件时终止轨迹

[英]scipy.solve_ivp: Terminate trajectory on second occurrence of event

I want to solve for the time taken to return to the initial condition.我想解决返回初始状态所需的时间。 As a toy example, let's take a simple harmonic oscillator d/dt (x, y) = (y, -x), with initial condition (x,y) = (1,0).作为一个玩具示例,让我们以一个简单的谐振子 d/dt (x, y) = (y, -x) 为例,初始条件为 (x,y) = (1,0)。

I want the code to return T = 6.28... (= 2π), since this is the time taken to return to the initial condition with y positive.我希望代码返回 T = 6.28... (= 2π),因为这是返回到 y 为正的初始条件所需的时间。 It should then stop integration when it reaches this point.当它到达这一点时,它应该停止集成。

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)

The trouble is setting event.terminal = True boots the integration straight away since the event is satisfied at t = 0. Is there any way to have the integration stopping only once the event has been satisfied twice?问题是设置event.terminal = True会立即启动积分,因为事件在 t = 0 时得到满足。有没有办法让积分只有在事件得到两次满足后才停止?

Similar to your workaround, I add 1e-100 to the event instead of to the initial state.与您的解决方法类似,我将 1e-100 添加到事件而不是初始 state。 This has the benefit of not affecting the trajectory at all, not even theoretically.这样做的好处是完全不影响轨迹,甚至在理论上也不受影响。

Of course it does mean that your future events will happen a tiny fraction earlier, but it depends on your situation if that matters to you.当然,这确实意味着你未来的事件会提前一小部分发生,但这取决于你的情况是否对你很重要。

For the example code you wrote, that would make your event the following:对于您编写的示例代码,这将使您的事件如下:

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

One thing I've tried that doesn't work is to modify the termination parameter during the integration.我尝试过但不起作用的一件事是在集成期间修改终止参数。 I thought if I start with event.terminal = False but then inside the event definition set event.terminal = True , then it would continue during the first event (at t=0), and terminate at the second event.我想如果我从event.terminal = False开始,然后在事件定义集event.terminal = True内,那么它将在第一个事件期间(在 t=0)继续,并在第二个事件处终止。 However it seems to ignore the changed parameter if it's changed during the integration.但是,如果在集成期间更改了参数,它似乎会忽略更改的参数。

(This question is related to Solve_ivp integration gets stuck if initial condition triggers event with terminal = True , but I don't have the reputation to flag anything.) (这个问题与Solve_ivp 集成有关,如果初始条件触发带有 terminal = True 的事件,但我没有标记任何东西的声誉。)

For future reference here is the workaround I've been using:为了将来参考,这里是我一直在使用的解决方法:

Set the initial condition to be a tiny amount in front of the event, eg initial_condition = [1e-100, 1] rather than [0, 1] .将初始条件设置为事件前的一小部分,例如initial_condition = [1e-100, 1]而不是[0, 1] It doesn't seem to affect the trajectory, even for higher degree-of-freedom chaotic systems, and yet it doesn't trigger the event at t=0.即使对于更高自由度的混沌系统,它似乎也不会影响轨迹,但它不会在 t=0 时触发事件。

Another workaround that would work would be to integrate without an event for some period of time and then use the result as initial conditions for further integration, this time with the event in place.另一个可行的解决方法是在一段时间内没有事件的情况下进行集成,然后将结果用作进一步集成的初始条件,这次是事件到位。 I doubt this answer will be useful for anyone but I've posted this just for completeness.我怀疑这个答案对任何人都有用,但我发布这个只是为了完整性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM