inline-r-0.7.0.0: tests/shootout/nbody.R
# ------------------------------------------------------------------
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# Contributed by Leo Osvald
# ------------------------------------------------------------------
pi <- 3.141592653589793
solar_mass <- 4 * pi * pi
days_per_year <- 365.24
n_bodies <- 5
body_x <- c(
0, # sun
4.84143144246472090e+00, # jupiter
8.34336671824457987e+00, # saturn
1.28943695621391310e+01, # uranus
1.53796971148509165e+01 # neptune
)
body_y <- c(
0, # sun
-1.16032004402742839e+00, # jupiter
4.12479856412430479e+00, # saturn
-1.51111514016986312e+01, # uranus
-2.59193146099879641e+01 # neptune
)
body_z <- c(
0, # sun
-1.03622044471123109e-01, # jupiter
-4.03523417114321381e-01, # saturn
-2.23307578892655734e-01, # uranus
1.79258772950371181e-01 # neptune
)
body_vx <- c(
0, # sun
1.66007664274403694e-03 * days_per_year, # jupiter
-2.76742510726862411e-03 * days_per_year, # saturn
2.96460137564761618e-03 * days_per_year, # uranus
2.68067772490389322e-03 * days_per_year # neptune
)
body_vy <- c(
0, # sun
7.69901118419740425e-03 * days_per_year, # jupiter
4.99852801234917238e-03 * days_per_year, # saturn
2.37847173959480950e-03 * days_per_year, # uranus
1.62824170038242295e-03 * days_per_year # neptune
)
body_vz <- c(
0, # sun
-6.90460016972063023e-05 * days_per_year, # jupiter
2.30417297573763929e-05 * days_per_year, # saturn
-2.96589568540237556e-05 * days_per_year, # uranus
-9.51592254519715870e-05 * days_per_year # neptune
)
body_mass <- c(
solar_mass, # sun
9.54791938424326609e-04 * solar_mass, # jupiter
2.85885980666130812e-04 * solar_mass, # saturn
4.36624404335156298e-05 * solar_mass, # uranus
5.15138902046611451e-05 * solar_mass # neptune
)
offset_momentum <- function() {
body_vx[[1]] <<- -sum(body_vx * body_mass) / solar_mass
body_vy[[1]] <<- -sum(body_vy * body_mass) / solar_mass
body_vz[[1]] <<- -sum(body_vz * body_mass) / solar_mass
}
advance <- function(dt) {
dxx <- outer(body_x, body_x, "-") # ~2x faster then nested for loops
dyy <- outer(body_y, body_y, "-")
dzz <- outer(body_z, body_z, "-")
distance <- sqrt(dxx * dxx + dyy * dyy + dzz * dzz)
mag <- dt / (distance * distance * distance) # ~fast as distance^3
diag(mag) <- 0
body_vx <<- body_vx - as.vector((dxx * mag) %*% body_mass)
body_vy <<- body_vy - as.vector((dyy * mag) %*% body_mass)
body_vz <<- body_vz - as.vector((dzz * mag) %*% body_mass)
body_x <<- body_x + dt * body_vx
body_y <<- body_y + dt * body_vy
body_z <<- body_z + dt * body_vz
}
energy <- function() {
dxx <- outer(body_x, body_x, "-")
dyy <- outer(body_y, body_y, "-")
dzz <- outer(body_z, body_z, "-")
distance <- sqrt(dxx * dxx + dyy * dyy + dzz * dzz)
q <- (body_mass %o% body_mass) / distance
return(sum(0.5 * body_mass *
(body_vx * body_vx + body_vy * body_vy + body_vz * body_vz)) -
sum(q[upper.tri(q)]))
}
nbody <- function(args) {
n = if (length(args)) as.integer(args[[1]]) else 1000L
options(digits=9)
offset_momentum()
cat(energy(), "\n")
for (i in 1:n)
advance(0.01)
cat(energy(), "\n")
}
if (!exists("i_am_wrapper"))
nbody(commandArgs(trailingOnly=TRUE))