2016-10-13 119 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真的想要計算更復雜的東西。 –