1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
type method_ = Explicit_euler | Semi_implicit_euler | Verlet | Rk4
let methods = [ Explicit_euler; Semi_implicit_euler; Verlet; Rk4 ]
let name = function
| Explicit_euler -> "explicit Euler"
| Semi_implicit_euler -> "semi-implicit Euler"
| Verlet -> "Verlet"
| Rk4 -> "RK4"
let ( +* ) (v : Vec2.t) ((dt, w) : float * Vec2.t) : Vec2.t = Vec2.add v (Vec2.scale dt w)
let explicit_euler ~(force : Force.t) ~(dt : float) (b : Body.t) : Body.t =
let a = force b.pos b.vel in
{ b with pos = b.pos +* (dt, b.vel); vel = b.vel +* (dt, a) }
let semi_implicit_euler ~(force : Force.t) ~(dt : float) (b : Body.t) : Body.t =
let a = force b.pos b.vel in
let vel = b.vel +* (dt, a) in
{ b with pos = b.pos +* (dt, vel); vel }
let verlet ~(force : Force.t) ~(dt : float) (b : Body.t) : Body.t =
let a = force b.pos b.vel in
let pos = b.pos +* (dt, b.vel) +* (dt *. dt /. 2., a) in
let a' = force pos (b.vel +* (dt, a)) in
{ b with pos; vel = b.vel +* (dt /. 2., Vec2.add a a') }
let rk4 ~(force : Force.t) ~(dt : float) (b : Body.t) : Body.t =
let deriv (pos, vel) = (vel, force pos vel) in
let at (pos, vel) h (dpos, dvel) = (pos +* (h, dpos), vel +* (h, dvel)) in
let s = (b.pos, b.vel) in
let k1 = deriv s in
let k2 = deriv (at s (dt /. 2.) k1) in
let k3 = deriv (at s (dt /. 2.) k2) in
let k4 = deriv (at s dt k3) in
let avg f = Vec2.scale (1. /. 6.) (Vec2.add (Vec2.add (f k1) (Vec2.scale 2. (f k2))) (Vec2.add (Vec2.scale 2. (f k3)) (f k4))) in
{ b with pos = b.pos +* (dt, avg fst); vel = b.vel +* (dt, avg snd) }
let step (m : method_) ~(force : Force.t) ~(dt : float) (b : Body.t) : Body.t =
match m with
| Explicit_euler -> explicit_euler ~force ~dt b
| Semi_implicit_euler -> semi_implicit_euler ~force ~dt b
| Verlet -> verlet ~force ~dt b
| Rk4 -> rk4 ~force ~dt b