Skip to content

Instantly share code, notes, and snippets.

@chrisseaton
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisseaton/91c7cbf8f6f4f6ea44bb to your computer and use it in GitHub Desktop.
Save chrisseaton/91c7cbf8f6f4f6ea44bb to your computer and use it in GitHub Desktop.
# Copied with little modifications from: http://benchmarksgame.alioth.debian.org/u32/program.php?test=nbody&lang=yarv&id=2
# 10000000
SOLAR_MASS = 4 * Math::PI**2
DAYS_PER_YEAR = 365.24
class Planet
property :x
property :y
property :z
property :vx
property :vy
property :vz
property :mass
def initialize(@x, @y, @z, vx, vy, vz, mass)
@x = x
@y = y
@z = z
@vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
@mass = mass * SOLAR_MASS
end
def move_from_i(bodies, nbodies, dt, i)
while i < nbodies
b2 = bodies[i]
dx = @x - b2.x
dy = @y - b2.y
dz = @z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
mag = dt / (distance * distance * distance)
b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
@vx -= dx * b2_mass_mag
@vy -= dy * b2_mass_mag
@vz -= dz * b2_mass_mag
b2.vx += dx * b_mass_mag
b2.vy += dy * b_mass_mag
b2.vz += dz * b_mass_mag
i += 1
end
@x += dt * @vx
@y += dt * @vy
@z += dt * @vz
end
end
def energy(bodies)
e = 0.0
nbodies = bodies.size
0.upto(nbodies - 1) do |i|
b = bodies[i]
e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)
(i + 1).upto(nbodies - 1) do |j|
b2 = bodies[j]
dx = b.x - b2.x
dy = b.y - b2.y
dz = b.z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
e -= (b.mass * b2.mass) / distance
end
end
e
end
def offset_momentum(bodies)
px, py, pz = 0.0, 0.0, 0.0
bodies.each do |b|
m = b.mass
px += b.vx * m
py += b.vy * m
pz += b.vz * m
end
b = bodies[0]
b.vx = - px / SOLAR_MASS
b.vy = - py / SOLAR_MASS
b.vz = - pz / SOLAR_MASS
end
BODIES = [
# sun
Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
# jupiter
Planet.new(
4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01,
1.66007664274403694e-03,
7.69901118419740425e-03,
-6.90460016972063023e-05,
9.54791938424326609e-04),
# saturn
Planet.new(
8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01,
-2.76742510726862411e-03,
4.99852801234917238e-03,
2.30417297573763929e-05,
2.85885980666130812e-04),
# uranus
Planet.new(
1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01,
2.96460137564761618e-03,
2.37847173959480950e-03,
-2.96589568540237556e-05,
4.36624404335156298e-05),
# neptune
Planet.new(
1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01,
2.68067772490389322e-03,
1.62824170038242295e-03,
-9.51592254519715870e-05,
5.15138902046611451e-05)
]
if ARGV.length != 1
puts "Usage: nbody n"
exit 1
end
n = ARGV[0].to_i
offset_momentum(BODIES)
puts energy(BODIES)
nbodies = BODIES.size
dt = 0.01
loop do
start = Time.now
n.times do
i = 0
while i < nbodies
b = BODIES[i]
b.move_from_i(BODIES, nbodies, dt, i + 1)
i += 1
end
end
puts energy(BODIES)
puts Time.now - start
end
# Copied with little modifications from: http://benchmarksgame.alioth.debian.org/u32/program.php?test=nbody&lang=yarv&id=2
# 10000000
SOLAR_MASS = 4 * Math::PI**2
DAYS_PER_YEAR = 365.24
class Planet
attr_accessor :x
attr_accessor :y
attr_accessor :z
attr_accessor :vx
attr_accessor :vy
attr_accessor :vz
attr_accessor :mass
def initialize(x, y, z, vx, vy, vz, mass)
@x = x
@y = y
@z = z
@vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
@mass = mass * SOLAR_MASS
end
def move_from_i(bodies, nbodies, dt, i)
while i < nbodies
b2 = bodies[i]
dx = @x - b2.x
dy = @y - b2.y
dz = @z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
mag = dt / (distance * distance * distance)
b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
@vx -= dx * b2_mass_mag
@vy -= dy * b2_mass_mag
@vz -= dz * b2_mass_mag
b2.vx += dx * b_mass_mag
b2.vy += dy * b_mass_mag
b2.vz += dz * b_mass_mag
i += 1
end
@x += dt * @vx
@y += dt * @vy
@z += dt * @vz
end
end
def energy(bodies)
e = 0.0
nbodies = bodies.size
0.upto(nbodies - 1) do |i|
b = bodies[i]
e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)
(i + 1).upto(nbodies - 1) do |j|
b2 = bodies[j]
dx = b.x - b2.x
dy = b.y - b2.y
dz = b.z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
e -= (b.mass * b2.mass) / distance
end
end
e
end
def offset_momentum(bodies)
px, py, pz = 0.0, 0.0, 0.0
bodies.each do |b|
m = b.mass
px += b.vx * m
py += b.vy * m
pz += b.vz * m
end
b = bodies[0]
b.vx = - px / SOLAR_MASS
b.vy = - py / SOLAR_MASS
b.vz = - pz / SOLAR_MASS
end
BODIES = [
# sun
Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
# jupiter
Planet.new(
4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01,
1.66007664274403694e-03,
7.69901118419740425e-03,
-6.90460016972063023e-05,
9.54791938424326609e-04),
# saturn
Planet.new(
8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01,
-2.76742510726862411e-03,
4.99852801234917238e-03,
2.30417297573763929e-05,
2.85885980666130812e-04),
# uranus
Planet.new(
1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01,
2.96460137564761618e-03,
2.37847173959480950e-03,
-2.96589568540237556e-05,
4.36624404335156298e-05),
# neptune
Planet.new(
1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01,
2.68067772490389322e-03,
1.62824170038242295e-03,
-9.51592254519715870e-05,
5.15138902046611451e-05)
]
if ARGV.length != 1
puts "Usage: nbody n"
exit 1
end
n = ARGV[0].to_i
offset_momentum(BODIES)
puts energy(BODIES)
nbodies = BODIES.size
dt = 0.01
loop do
start = Time.now
n.times do
i = 0
while i < nbodies
b = BODIES[i]
b.move_from_i(BODIES, nbodies, dt, i + 1)
i += 1
end
end
puts energy(BODIES)
puts Time.now - start
end
# Crystal
$ ./benchmark 10000000
-0.169075
-0.169078
00:00:05.3290830
-0.169032
00:00:05.1136050
-0.169035
00:00:05.2884420
-0.169087
00:00:05.2451600
-0.16906
00:00:05.1745340
-0.169012
00:00:05.0551180
-0.169026
00:00:05.4827040
-0.169086
00:00:05.2481410
-0.169068
00:00:05.2768550
-0.169035
00:00:05.3656790
-0.169052
00:00:05.2575230
# JRuby+Truffle
$ jt run --graal ../crystal/benchmark.rb 10000000
-0.16907516382852447
-0.16907784165395368
5.744
-0.16903166455119054
4.055
-0.1690346802933269
2.9
-0.16908707545910232
3.695
-0.16905990680291394
2.41
-0.1690124738905867
2.349
-0.16902624725633023
2.374
-0.16908638036010323
2.358
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment