Skip to content

Commit 36e68b7

Browse files
berquistButt4cak3
authored andcommitted
Update Rust implementations for Verlet algorithms (algorithm-archivists#297)
1 parent 954ebfa commit 36e68b7

File tree

3 files changed

+30
-25
lines changed

3 files changed

+30
-25
lines changed

contents/verlet_integration/code/julia/verlet.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function stormer_verlet(pos::Float64, acc::Float64, dt::Float64)
2424
prev_pos = temp_pos
2525

2626
# Because acceleration is constant, velocity is straightforward
27-
vel += acc*dt
27+
vel += acc * dt
2828
end
2929

3030
return time, vel
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fn verlet(mut pos: f64, acc: f64, dt: f64) {
1+
fn verlet(mut pos: f64, acc: f64, dt: f64) -> f64 {
22
let mut prev_pos = pos;
33
let mut time = 0.0;
44

@@ -9,24 +9,29 @@ fn verlet(mut pos: f64, acc: f64, dt: f64) {
99
prev_pos = temp_pos;
1010
}
1111

12-
println!("{}", time);
12+
time
1313
}
1414

15-
fn stormer_verlet(mut pos: f64, acc: f64, dt: f64) {
15+
fn stormer_verlet(mut pos: f64, acc: f64, dt: f64) -> (f64, f64) {
1616
let mut prev_pos = pos;
1717
let mut time = 0.0;
18+
let mut vel = 0.0;
1819

1920
while pos > 0.0 {
2021
time += dt;
2122
let temp_pos = pos;
2223
pos = pos * 2.0 - prev_pos + acc * dt * dt;
2324
prev_pos = temp_pos;
25+
26+
// Because acceleration is constant, velocity is
27+
// straightforward
28+
vel += acc * dt;
2429
}
2530

26-
println!("{}", time);
31+
(time, vel)
2732
}
2833

29-
fn velocity_verlet(mut pos: f64, acc: f64, dt: f64) {
34+
fn velocity_verlet(mut pos: f64, acc: f64, dt: f64) -> (f64, f64) {
3035
let mut time = 0.0;
3136
let mut vel = 0.0;
3237

@@ -36,11 +41,15 @@ fn velocity_verlet(mut pos: f64, acc: f64, dt: f64) {
3641
vel += acc * dt;
3742
}
3843

39-
println!("{}", time);
44+
(time, vel)
4045
}
4146

4247
fn main() {
43-
verlet(5.0, -10.0, 0.01);
44-
stormer_verlet(5.0, -10.0, 0.01);
45-
velocity_verlet(5.0, -10.0, 0.01);
48+
let time_v = verlet(5.0, -10.0, 0.01);
49+
let (time_sv, vel_sv) = stormer_verlet(5.0, -10.0, 0.01);
50+
let (time_vv, vel_vv) = velocity_verlet(5.0, -10.0, 0.01);
51+
52+
println!("Time for original Verlet integration: {}", time_v);
53+
println!("Time and velocity for Stormer Verlet integration: {}, {}", time_sv, vel_sv);
54+
println!("Time and velocity for velocity Verlet integration: {}, {}", time_vv, vel_vv);
4655
}

contents/verlet_integration/verlet_integration.md

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Verlet Integration
22

3-
Verlet Integration is essentially a solution to the kinematic equation for the motion of any object,
3+
Verlet integration is essentially a solution to the kinematic equation for the motion of any object,
44

55
$$
66
x = x_0 + v_0t + \frac{1}{2}at^2 + \frac{1}{6}bt^3 + \cdots
77
$$
88

9-
Where $$x$$ is the position, $$v$$ is the velocity, $$a$$ is the acceleration, $$b$$ is the often forgotten jerk term, and $$t$$ is time. This equation is a central equation to almost every Newtonian physics solver and brings up a class of algorithms known as *force integrators*. One of the first force integrators to work with is *Verlet Integration*.
9+
where $$x$$ is the position, $$v$$ is the velocity, $$a$$ is the acceleration, $$b$$ is the often forgotten jerk term, and $$t$$ is time. This equation is a central equation to almost every Newtonian physics solver and brings up a class of algorithms known as *force integrators*. One of the first force integrators to work with is *Verlet Integration*.
1010

1111
So, let's say we want to solve for the next timestep in $$x$$. To a close approximation (actually performing a Taylor Series Expansion about $$x(t\pm \Delta t)$$), that might look like this:
1212

@@ -20,13 +20,13 @@ $$
2020
x(t-\Delta t) = x(t) - v(t)\Delta t + \frac{1}{2}a(t)\Delta t^2 - \frac{1}{6}b(t) \Delta t^3 + \mathcal{O}(\Delta t^4)
2121
$$
2222

23-
Now, we have two equations to solve for two different timesteps in x, one of which we already have. If we add the two equations together and solve for $$x(t+\Delta t)$$, we find
23+
Now, we have two equations to solve for two different timesteps in x, one of which we already have. If we add the two equations together and solve for $$x(t+\Delta t)$$, we find that
2424

2525
$$
2626
x(t+ \Delta t) = 2x(t) - x(t-\Delta t) + a(t)\Delta t^2 + \mathcal{O}(\Delta t^4)
2727
$$
2828

29-
So, this means, we can find our next $$x$$ simply by knowing our current $$x$$, the $$x$$ before that, and the acceleration! No velocity necessary! In addition, this drops the error to $$\mathcal{O}(\Delta t^4)$$, which is great!
29+
So, this means we can find our next $$x$$ simply by knowing our current $$x$$, the $$x$$ before that, and the acceleration! No velocity necessary! In addition, this drops the error to $$\mathcal{O}(\Delta t^4)$$, which is great!
3030
Here is what it looks like in code:
3131

3232
{% method %}
@@ -60,9 +60,7 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
6060
[import:1-15, lang:"swift"](code/swift/verlet.swift)
6161
{% endmethod %}
6262

63-
64-
65-
Now, obviously this poses a problem, what if we want to calculate a term that requires velocity, like the kinetic energy, $$\frac{1}{2}mv^2$$? In this case, we certainly cannot get rid of the velocity! Well, we can find the velocity to $$\mathcal{O}(\Delta t^2)$$ accuracy by using the Stormer-Verlet method, which is the same as before, but we calculate velocity like so
63+
Now, obviously this poses a problem; what if we want to calculate a term that requires velocity, like the kinetic energy, $$\frac{1}{2}mv^2$$? In this case, we certainly cannot get rid of the velocity! Well, we can find the velocity to $$\mathcal{O}(\Delta t^2)$$ accuracy by using the Stormer-Verlet method, which is the same as before, but we calculate velocity like so
6664

6765
$$
6866
v(t) = \frac{x(t+\Delta t) - x(t-\Delta t)}{2\Delta t} + \mathcal{O}(\Delta t^2)
@@ -74,8 +72,7 @@ $$
7472
v(t+\Delta t) = \frac{x(t+\Delta t) - x(t)}{\Delta t} + \mathcal{O}(\Delta t)
7573
$$
7674

77-
However, the error for this is $$\mathcal{O}(\Delta t)$$, which is quite poor, but get's the job done in a pinch.
78-
Here's what it looks like in code:
75+
However, the error for this is $$\mathcal{O}(\Delta t)$$, which is quite poor, but it gets the job done in a pinch. Here's what it looks like in code:
7976

8077
{% method %}
8178
{% sample lang="jl" %}
@@ -103,7 +100,7 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
103100
{% sample lang="javascript" %}
104101
[import:18-35, lang:"javascript"](code/javascript/verlet.js)
105102
{% sample lang="rs" %}
106-
[import:15-27, lang:"rust"](code/rust/verlet.rs)
103+
[import:15-32, lang:"rust"](code/rust/verlet.rs)
107104
{% sample lang="swift" %}
108105
[import:17-34, lang:"swift"](code/swift/verlet.swift)
109106
{% endmethod %}
@@ -113,7 +110,7 @@ Now, let's say we actually need the velocity to calculate out next timestep. Wel
113110

114111
# Velocity Verlet
115112

116-
In some ways, this algorithm is even simpler than above. We can calculate everything like so
113+
In some ways, this algorithm is even simpler than above. We can calculate everything like
117114

118115
$$
119116
\begin{align}
@@ -123,7 +120,7 @@ v(t+\Delta t) &= v(t) + \frac{1}{2}(a(t) + a(t+\Delta t))\Delta t
123120
\end{align}
124121
$$
125122

126-
Which is literally the kinematic equation above, solving for $$x$$, $$v$$, and $$a$$ every timestep. You can also split up the equations like so
123+
which is literally the kinematic equation above, solving for $$x$$, $$v$$, and $$a$$ every timestep. You can also split up the equations like so
127124

128125
$$
129126
\begin{align}
@@ -162,13 +159,12 @@ Unfortunately, this has not yet been implemented in LabVIEW, so here's Julia cod
162159
{% sample lang="javascript" %}
163160
[import:37-50, lang:"javascript"](code/javascript/verlet.js)
164161
{% sample lang="rs" %}
165-
[import:29-40, lang:"rust"](code/rust/verlet.rs)
162+
[import:34-45, lang:"rust"](code/rust/verlet.rs)
166163
{% sample lang="swift" %}
167164
[import:36-49, lang:"swift"](code/swift/verlet.swift)
168165
{% endmethod %}
169166

170-
171-
Even though this method is more used than the simple Verlet method mentioned above, it unfortunately has an error term of $$\mathcal{O} \Delta t^2$$, which is two orders of magnitude worse. That said, if you want to have a simulation with many objects that depend on one another --- like a gravity simulation --- the Velocity Verlet algorithm is a handy choice; however, you may have to play further tricks to allow everything to scale appropriately. These types of simulations are sometimes called *n-body* simulations and one such trick is the Barnes-Hut algorithm, which cuts the complexity of n-body simulations from $$\sim \mathcal{O}(n^2)$$ to $$\sim \mathcal{O}(n\log(n))$$
167+
Even though this method is more widely used than the simple Verlet method mentioned above, it unforunately has an error term of $$\mathcal{O}(\Delta t^2)$$, which is two orders of magnitude worse. That said, if you want to have a simulaton with many objects that depend on one another --- like a gravity simulation --- the Velocity Verlet algorithm is a handy choice; however, you may have to play further tricks to allow everything to scale appropriately. These types of simulatons are sometimes called *n-body* simulations and one such trick is the Barnes-Hut algorithm, which cuts the complexity of n-body simulations from $$\sim \mathcal{O}(n^2)$$ to $$\sim \mathcal{O}(n\log(n))$$.
172168

173169
## Example Code
174170

0 commit comments

Comments
 (0)