2016-10-13 3 views
2

줄리아 방정식을 사용하여 튀는 공의 간단한 모델을 만들 수 있습니까? 유용한 보이는 숫자를 생산튀는 공을 시뮬레이트 하시겠습니까?

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을 표시하고 있지만 (Sundials.jl 등)를 적절히 갱신 f(t,u,du)로 함수를 직접 정의 할 수 있습니다. 다음은 이벤트 발생시기를 결정하는 함수를 정의합니다. 이벤트 시간에 양수이고 0에 도달하는 모든 함수가 될 수 있습니다. 여기서 우리는 그래서 공은 땅을 칠 때 또는 때 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 

지금 당신이 평소와 같이 해결한다. ODEProblemf과 초기 조건을 사용하여 정의하고 timespan에서 solve를 호출합니다.

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에서 이벤트를 찾습니다.더 많거나 적은 보간점이 매크로로 옵션으로 포함될 수 있습니다.

  2. DifferentialEquations.jl은 이벤트 순간에 도움을 줄 루트 찾기 방법을 사용했습니다. 적응 형 솔버가 이벤트를 지나치더라도 보간에서 루트 찾기를 사용하면 이벤트의 정확한 시간을 찾아 불연속성을 얻을 수 있습니다. 그래프에서 공이 결코 음수가되지 않는 것을 볼 수 있습니다.

  3. 더 많은 작업이 가능합니다. Check out the docs. 이것으로 거의 모든 것을 할 수 있습니다. 예를 들어 출생과 사망에 따른 세포 집단을 모델링하기 위해 실행 동안 ODE 크기를 변경하십시오. 이것은 다른 솔버 패키지가 할 수없는 것입니다.

  4. 이러한 모든 기능을 사용하더라도 속도는 저하되지 않습니다.

"사용 용이성"인터페이스 매크로에 추가 기능이 추가되어야하는지 알려주세요.

3

다소 해키 : 당신은 단지 규칙을 따릅니다 곳 Y와 같은 높이를 참조 -y

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

. 그런 다음 abs (y)를 플롯하여 튀는 공의 궤적을 그릴 수 있습니다.

+0

타임 스 텝이 매우 작아서 이벤트가 시간 지점에 "충분히 가깝습니다"라고 가정하기 때문에 이와 같은 접근 방식은 효과가 없습니다. 그렇지 않으면 많은 양의 오류가 발생할 것입니다 (여기에 몇 가지 음수 값이 있습니다). 이러한 접근법은 진동 솔루션에 대한 사건을 완전히 놓칠 수 있습니다. 이것이 보간이 필요한 이유입니다. ODE.jl에는 좋은 보간이 없기 때문에 많은 보완이 필요하지 않습니다. –

+0

이 특정 해킹 된 솔루션의 오류는 속도를 역전 시키려고 시도하는 것보다 훨씬 작습니다. ODE 솔버가이 작업을 수행하지 못하면 실제 물리적 인 잠재적 인 문제가 발생할 수도 있습니다. – saolof

+0

아 잠깐, 내가 여기서하고있는 것을 보았다 ... 그것은 매우 일반화 할 수 없다. 여러분은 간단한 예를 다루는 0에 대해'y'의 완벽한 대칭을 사용하고 있습니다. 나는 OP가 정말로 더 복잡한 것을 계산하려고한다고 가정 할 것입니다. –