// 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) } } }