161 lines
3.7 KiB
Plaintext
161 lines
3.7 KiB
Plaintext
// nbody.cm — N-body gravitational simulation kernel
|
|
// Pure numeric + allocation workload. Classic VM benchmark.
|
|
|
|
var math = use('math/radians')
|
|
|
|
def PI = 3.141592653589793
|
|
def SOLAR_MASS = 4 * PI * PI
|
|
def DAYS_PER_YEAR = 365.24
|
|
|
|
function make_system() {
|
|
// Sun + 4 Jovian planets
|
|
var sun = {x: 0, y: 0, z: 0, vx: 0, vy: 0, vz: 0, mass: SOLAR_MASS}
|
|
|
|
var jupiter = {
|
|
x: 4.84143144246472090,
|
|
y: -1.16032004402742839,
|
|
z: -0.103622044471123109,
|
|
vx: 0.00166007664274403694 * DAYS_PER_YEAR,
|
|
vy: 0.00769901118419740425 * DAYS_PER_YEAR,
|
|
vz: -0.0000690460016972063023 * DAYS_PER_YEAR,
|
|
mass: 0.000954791938424326609 * SOLAR_MASS
|
|
}
|
|
|
|
var saturn = {
|
|
x: 8.34336671824457987,
|
|
y: 4.12479856412430479,
|
|
z: -0.403523417114321381,
|
|
vx: -0.00276742510726862411 * DAYS_PER_YEAR,
|
|
vy: 0.00499852801234917238 * DAYS_PER_YEAR,
|
|
vz: 0.0000230417297573763929 * DAYS_PER_YEAR,
|
|
mass: 0.000285885980666130812 * SOLAR_MASS
|
|
}
|
|
|
|
var uranus = {
|
|
x: 12.8943695621391310,
|
|
y: -15.1111514016986312,
|
|
z: -0.223307578892655734,
|
|
vx: 0.00296460137564761618 * DAYS_PER_YEAR,
|
|
vy: 0.00237847173959480950 * DAYS_PER_YEAR,
|
|
vz: -0.0000296589568540237556 * DAYS_PER_YEAR,
|
|
mass: 0.0000436624404335156298 * SOLAR_MASS
|
|
}
|
|
|
|
var neptune = {
|
|
x: 15.3796971148509165,
|
|
y: -25.9193146099879641,
|
|
z: 0.179258772950371181,
|
|
vx: 0.00268067772490389322 * DAYS_PER_YEAR,
|
|
vy: 0.00162824170038242295 * DAYS_PER_YEAR,
|
|
vz: -0.0000951592254519715870 * DAYS_PER_YEAR,
|
|
mass: 0.0000515138902046611451 * SOLAR_MASS
|
|
}
|
|
|
|
var bodies = [sun, jupiter, saturn, uranus, neptune]
|
|
|
|
// Offset momentum
|
|
var px = 0
|
|
var py = 0
|
|
var pz = 0
|
|
var i = 0
|
|
for (i = 0; i < length(bodies); i++) {
|
|
px += bodies[i].vx * bodies[i].mass
|
|
py += bodies[i].vy * bodies[i].mass
|
|
pz += bodies[i].vz * bodies[i].mass
|
|
}
|
|
sun.vx = -px / SOLAR_MASS
|
|
sun.vy = -py / SOLAR_MASS
|
|
sun.vz = -pz / SOLAR_MASS
|
|
|
|
return bodies
|
|
}
|
|
|
|
function advance(bodies, dt) {
|
|
var n = length(bodies)
|
|
var i = 0
|
|
var j = 0
|
|
var bi = null
|
|
var bj = null
|
|
var dx = 0
|
|
var dy = 0
|
|
var dz = 0
|
|
var dist_sq = 0
|
|
var dist = 0
|
|
var mag = 0
|
|
|
|
for (i = 0; i < n; i++) {
|
|
bi = bodies[i]
|
|
for (j = i + 1; j < n; j++) {
|
|
bj = bodies[j]
|
|
dx = bi.x - bj.x
|
|
dy = bi.y - bj.y
|
|
dz = bi.z - bj.z
|
|
dist_sq = dx * dx + dy * dy + dz * dz
|
|
dist = math.sqrt(dist_sq)
|
|
mag = dt / (dist_sq * dist)
|
|
|
|
bi.vx -= dx * bj.mass * mag
|
|
bi.vy -= dy * bj.mass * mag
|
|
bi.vz -= dz * bj.mass * mag
|
|
bj.vx += dx * bi.mass * mag
|
|
bj.vy += dy * bi.mass * mag
|
|
bj.vz += dz * bi.mass * mag
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
bi = bodies[i]
|
|
bi.x += dt * bi.vx
|
|
bi.y += dt * bi.vy
|
|
bi.z += dt * bi.vz
|
|
}
|
|
}
|
|
|
|
function energy(bodies) {
|
|
var e = 0
|
|
var n = length(bodies)
|
|
var i = 0
|
|
var j = 0
|
|
var bi = null
|
|
var bj = null
|
|
var dx = 0
|
|
var dy = 0
|
|
var dz = 0
|
|
for (i = 0; i < n; i++) {
|
|
bi = bodies[i]
|
|
e += 0.5 * bi.mass * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz)
|
|
for (j = i + 1; j < n; j++) {
|
|
bj = bodies[j]
|
|
dx = bi.x - bj.x
|
|
dy = bi.y - bj.y
|
|
dz = bi.z - bj.z
|
|
e -= (bi.mass * bj.mass) / math.sqrt(dx * dx + dy * dy + dz * dz)
|
|
}
|
|
}
|
|
return e
|
|
}
|
|
|
|
return {
|
|
nbody_1k: function(n) {
|
|
var i = 0
|
|
var j = 0
|
|
var bodies = null
|
|
for (i = 0; i < n; i++) {
|
|
bodies = make_system()
|
|
for (j = 0; j < 1000; j++) advance(bodies, 0.01)
|
|
energy(bodies)
|
|
}
|
|
},
|
|
|
|
nbody_10k: function(n) {
|
|
var i = 0
|
|
var j = 0
|
|
var bodies = null
|
|
for (i = 0; i < n; i++) {
|
|
bodies = make_system()
|
|
for (j = 0; j < 10000; j++) advance(bodies, 0.01)
|
|
energy(bodies)
|
|
}
|
|
}
|
|
}
|