source code
(* The Computer Language Benchmarks Game
* https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
*
* Contributed by Troestler Christophe
*)
let pi = 3.141592653589793
let solar_mass = 4. *. pi *. pi
let days_per_year = 365.24
type planet = { mutable x : float; mutable y : float; mutable z : float;
mutable vx: float; mutable vy: float; mutable vz: float;
mass : float }
let advance bodies dt =
let n = Array.length bodies - 1 in
for i = 0 to Array.length bodies - 1 do
let b = bodies.(i) in
for j = i+1 to Array.length bodies - 1 do
let b' = bodies.(j) in
let dx = b.x -. b'.x and dy = b.y -. b'.y and dz = b.z -. b'.z in
let dist2 = dx *. dx +. dy *. dy +. dz *. dz in
let mag = dt /. (dist2 *. sqrt(dist2)) in
b.vx <- b.vx -. dx *. b'.mass *. mag;
b.vy <- b.vy -. dy *. b'.mass *. mag;
b.vz <- b.vz -. dz *. b'.mass *. mag;
b'.vx <- b'.vx +. dx *. b.mass *. mag;
b'.vy <- b'.vy +. dy *. b.mass *. mag;
b'.vz <- b'.vz +. dz *. b.mass *. mag;
done
done;
for i = 0 to n do
let b = bodies.(i) in
b.x <- b.x +. dt *. b.vx;
b.y <- b.y +. dt *. b.vy;
b.z <- b.z +. dt *. b.vz;
done
let energy bodies =
let e = ref 0. in
for i = 0 to Array.length bodies - 1 do
let b = bodies.(i) in
e := !e +. 0.5 *. b.mass *. (b.vx *. b.vx +. b.vy *. b.vy +. b.vz *. b.vz);
for j = i+1 to Array.length bodies - 1 do
let b' = bodies.(j) in
let dx = b.x -. b'.x and dy = b.y -. b'.y and dz = b.z -. b'.z in
let distance = sqrt(dx *. dx +. dy *. dy +. dz *. dz) in
e := !e -. (b.mass *. b'.mass) /. distance
done
done;
!e
let offset_momentum bodies =
let px = ref 0. and py = ref 0. and pz = ref 0. in
for i = 0 to Array.length bodies - 1 do
px := !px +. bodies.(i).vx *. bodies.(i).mass;
py := !py +. bodies.(i).vy *. bodies.(i).mass;
pz := !pz +. bodies.(i).vz *. bodies.(i).mass;
done;
bodies.(0).vx <- -. !px /. solar_mass;
bodies.(0).vy <- -. !py /. solar_mass;
bodies.(0).vz <- -. !pz /. solar_mass
let jupiter = { x = 4.84143144246472090e+00;
y = -1.16032004402742839e+00;
z = -1.03622044471123109e-01;
vx = 1.66007664274403694e-03 *. days_per_year;
vy = 7.69901118419740425e-03 *. days_per_year;
vz = -6.90460016972063023e-05 *. days_per_year;
mass = 9.54791938424326609e-04 *. solar_mass; }
let saturn = { x = 8.34336671824457987e+00;
y = 4.12479856412430479e+00;
z = -4.03523417114321381e-01;
vx = -2.76742510726862411e-03 *. days_per_year;
vy = 4.99852801234917238e-03 *. days_per_year;
vz = 2.30417297573763929e-05 *. days_per_year;
mass = 2.85885980666130812e-04 *. solar_mass; }
let uranus = { x = 1.28943695621391310e+01;
y = -1.51111514016986312e+01;
z = -2.23307578892655734e-01;
vx = 2.96460137564761618e-03 *. days_per_year;
vy = 2.37847173959480950e-03 *. days_per_year;
vz = -2.96589568540237556e-05 *. days_per_year;
mass = 4.36624404335156298e-05 *. solar_mass; }
let neptune = { x = 1.53796971148509165e+01;
y = -2.59193146099879641e+01;
z = 1.79258772950371181e-01;
vx = 2.68067772490389322e-03 *. days_per_year;
vy = 1.62824170038242295e-03 *. days_per_year;
vz = -9.51592254519715870e-05 *. days_per_year;
mass = 5.15138902046611451e-05 *. solar_mass; }
let sun = { x = 0.; y = 0.; z = 0.; vx = 0.; vy = 0.; vz = 0.;
mass = solar_mass; }
let bodies = [| sun; jupiter; saturn; uranus; neptune |]
let () =
let n = int_of_string(Sys.argv.(1)) in
offset_momentum bodies;
Printf.printf "%.9f\n" (energy bodies);
for i = 1 to n do advance bodies 0.01 done;
Printf.printf "%.9f\n" (energy bodies)
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
OCaml native-code
5.4.0+dev0-2024-08-25
Thu, 05 Sep 2024 18:07:00 GMT
MAKE:
mv nbody.ocaml nbody.ml
~/.opam/5.1.1/bin/ocamlopt -noassert -unsafe -fPIC -nodynlink -inline 100 -O3 -ccopt -march=ivybridge nbody.ml -o nbody.ocaml_run
rm nbody.ml
1.83s to complete and log all make actions
COMMAND LINE:
./nbody.ocaml_run 50000000
PROGRAM OUTPUT:
-0.169075164
-0.169059907