我已经在 Haskell 中实现了 Runge-Kutta。然而,当在位置为 (0, 0, -10) 且速度为 (0, 0, 0) 的物体上运行时,它会非常快速地来回振荡,直到 到达位置 (0, 0, 0)。
出了什么问题?
(注意:我正在基于 this 资源 以及
*|
和 |*
运算符实现,分别将标量乘以向量,以及将向量乘以标量。
integrate :: PhysicalObject a => a -> Second -> Second -> (Position3, Velocity3)
integrate object t dt = (p, v)
where p = (position object) + (dxdt |* dt)
v = (velocity object) + (dvdt |* dt)
dxdt = (1.0 / 6.0) *| (dx1 + (2 *| (dx2 + dx3)) + dx4)
dvdt = (1.0 / 6.0) *| (dv1 + (2 *| (dv2 + dv3)) + dv4)
(dx1, dv1) = (velocity object, acceleration (position object, velocity object) t)
(dx2, dv2) = evaluate (position object, velocity object) t (0.5*dt) (dx1, dv1)
(dx3, dv3) = evaluate (position object, velocity object) t (0.5*dt) (dx2, dv2)
(dx4, dv4) = evaluate (position object, velocity object) t dt (dx3, dv3)
evaluate :: (Vec3 Double, Vec3 Double) -> Second -> Second -> (Vec3 Double, Vec3 Double) -> (Vec3 Double, Vec3 Double)
evaluate (ix, iv) t dt (dx, dv) = (odx, odv)
where odx = sv
odv = acceleration (sx, sv) (t + dt)
sx = ix + (dx |* dt)
sv = iv + (dv |* dt)
acceleration :: (Vec3 Double, Vec3 Double) -> Second -> Vec3 Double
acceleration (sx, sv) t = (-k *| sx) - (b *| sv)
where k = 10
b = 1
在本例中,
acceleration
函数正在模拟弹簧。
我已将其更改为:
acceleration :: (Vec3 Double, Vec3 Double) -> Second -> Vec3 Double
acceleration (sx, sv) t = sv