2016-10-13 123 views
2

使用Julia方程求解器可以创建简单的弹跳球模型吗?模拟弹跳球?

我开始用这样的:

using ODE 

function bb(t, f) 
    (y, v) = f 
    dy_dt = v 
    dv_dt = -9.81 
    [dy_dt, dv_dt] 
end 

const y0 = 50.0    # height 
const v0 = 0.0    # velocity 
const startpos = [y0; v0] 

ts = 0.0:0.25:10    # time span 

t, res = ode45(bb, startpos, ts) 

产生寻找有用的号码:

julia> t 
44-element Array{Float64,1}: 
    0.0 
    0.0551392 
    0.25 
    0.5 
    0.75 
    1.0 
    ⋮ 
    8.75 
    9.0 
    9.25 
    9.5 
    9.75 
10.0 

julia> res 
44-element Array{Array{Float64,1},1}: 
[50.0,0.0] 
[49.9851,-0.540915] 
[49.6934,-2.4525] 
[48.7738,-4.905] 
[47.2409,-7.3575] 
⋮ 
[-392.676,-93.195] 
[-416.282,-95.6475] 
[-440.5,-98.1] 

但不知何故,它需要介入时的高度为0,扭转速度。还是我在错误的轨道上?

+1

你不能在ODE中这样做,因为那需要事件处理。但是,事件处理现在位于[DifferentialEquations.jl](https://github.com/JuliaDiffEq/DifferentialEquations.jl/issues/64)列表的顶部。那里有解决方案时我会发布。 –

+0

如果您有兴趣确保DifferentialEquations.jl框架能够处理您感兴趣的各种问题,请随时参考[关于此问题](https://github.com/JuliaDiffEq/DifferentialEquations.jl/问题/ 64)。考虑到API,已经能够处理这个问题以及更多问题,例如更改问题大小。我打算像一个星期左右发布。 –

回答

5

DifferentialEquations.jl offers sophisticated callbacks and event handling。由于the DifferentialEquations.jl algorithms are about 10x faster同时提供higher order interpolation,这些算法无疑是更好的选择。

第一个链接是显示如何执行事件处理的文档。简单的界面使用宏。我从定义函数开始。

f = @ode_def BallBounce begin 
    dy = v 
    dv = -g 
end g=9.81 

我在这里展示ParameterizedFunctions.jl使语法更好,但你可以直接作为就地更新f(t,u,du)(如Sundials.jl)定义的功能。接下来定义确定事件发生的函数。它可以是任何积极的功能,并在事件时间点击零。在这里,我们检查时,球击中地面,或当y=0,所以:

function event_f(t,u) # Event when event_f(t,u,k) == 0 
    u[1] 
end 

下一页你说在事件发生时该怎么办。在这里我们要扭转速度的符号:

function apply_event!(u,cache) 
    u[2] = -u[2] 
end 

你把这些功能一起使用宏来建立回调:

callback = @ode_callback begin 
    @ode_event event_f apply_event! 
end 

现在你解决一切正常。您使用f和初始条件来定义ODEProblem,然后在时间范围内调用求解。唯一的一点额外为你传递回调与解算器一起:

u0 = [50.0,0.0] 
prob = ODEProblem(f,u0) 
tspan = [0;15] 
sol = solve(prob,tspan,callback=callback) 

然后我们就可以用情节食谱自动绘制解决方案:

plot(sol) 

结果是这样的:

ballbounce

几件事情需要注意:

  1. DifferentialEquations.jl将自动使用插值来更安全地检查事件。例如,如果事件发生在一个时间步内但不在末尾,DifferentialEquations.jl仍然会找到它。可以将更多或更少的插值点作为@ode_event宏的选项。

  2. DifferentialEquations.jl使用rootfinding方法来磨合事件的时刻。即使自适应求解器通过事件,通过在插值上使用查找找到事件的确切时间,从而得到不连续性的权利。你可以在图中看到,因为球永远不会消极。

  3. 这个可以做的事情还有很多。 Check out the docs。你可以用这个做很多事情。例如,让您的ODE在运行过程中改变大小以模拟出生和死亡的细胞群体。这是其他解算器软件包无法做到的。

  4. 即使具备所有这些功能,速度也不会受到影响。

让我知道如果您需要任何额外的功能添加到“易用”界面宏。

3

有点哈克:

function bb(t, f) 
    (y, v) = f 
    dy_dt = v 
    dv_dt = -9.81*sign(y) 
    [dy_dt, dv_dt] 
end 

,你只要按照惯例,其中y和-y是指相同的高度。然后,您可以绘制abs(y)来绘制弹跳球的轨迹。

+0

这样的方法不能很好地工作,因为它假定时间步长非常小,以便事件与时间点“足够接近”。否则这会引入大量的错误(并且在这里你会得到一些负值)。这种方法可能完全错过振荡解决方案的事件。这就是为什么需要插值。 ODE.jl没有很好的插值,这就是为什么在没有很多工作的情况下不可能实现的原因。 –

+0

这个特定的hacky解决方案的错误将比尝试颠倒速度要小得多。如果ODE求解器失败,它可能也会因实际的物理潜在问题而失败。 – saolof

+0

哦,等等,我看到你在这里做什么......虽然它不是很普遍。你使用约为0的完美对称性,这个例子很简单。我会假设OP真的想要计算更复杂的东西。 –