1

I'm working on a little N-Body Simulation in JavaScript. It's running as I expected, but I noticed something odd. The simulation uses a verlet integrator and the function that accumulates the forces has the line:

force.length = (this.gravity * pa.mass * pb.mass) / dist * dist;

As I said, the simulation works as expected, but shouldn't the code actually read:

force.length = (this.gravity * pa.mass * pb.mass) / (dist * dist);

where the order of operations is correct for the square of the distance? When I have it that way the simulation blows up. Kind of an odd thing, the wrong way works correctly, or seems to. Anyone have an idea of what the issue is? Complete code and running example here:

https://gist.github.com/arctwelve/ca5868f80d0b0cd5791e http://bl.ocks.org/arctwelve/ca5868f80d0b0cd5791e

TIA

Hal50000
  • 639
  • 1
  • 6
  • 16
  • What do you mean by "blows up"? – Bergi Jan 19 '16 at 23:50
  • 1
    @Bergi "blowing up' is a term used in physics simulation and refers to numeric instability. Usually the thing being simulated appears to quickly lose stability and 'blow up'. In my case I'm using it more generally, in the sense that it's not working at all :) – Hal50000 Jan 20 '16 at 15:34

2 Answers2

3

In your code, var dist = vect.x * vect.x + vect.y * vect.y; is actually setting dist to the square of the distance, so force.length = (this.gravity * pa.mass * pb.mass) / dist; should give you the correct result.

John Sensebe
  • 1,386
  • 8
  • 11
  • Yes! That appears to be it. It's the equivalent of getting the true distance `var dist = Math.sqrt(vect.x * vect.x + vect.y * vect.y);` and then getting its square `force.length = this.gravity * pa.mass * pb.mass / Math.pow(dist, 2);` Interesting, as @Pointy mentioned, my original code negates the distance. The sim still works but the force is a constant, not relative to the distance of the bodies. – Hal50000 Jan 20 '16 at 17:01
  • Yes. You don't really need the true distance in this case, so it's more efficient just to compute its square. So, how about accepting my answer? :-) – John Sensebe Jan 20 '16 at 17:21
  • Sorry, I had to run off to my job at NASA with the corrected algorithm before I could mark your answer correct :) – Hal50000 Jan 20 '16 at 22:11
  • I hope the rocket launched on time. – John Sensebe Jan 20 '16 at 22:14
  • 1
    This was actually for the vending machine. – Hal50000 Jan 20 '16 at 22:15
2

The interpretation of

force.length = (this.gravity * pa.mass * pb.mass) / dist * dist;

is

force.length = ((this.gravity * pa.mass * pb.mass) / dist) * dist;

The division operator and the multiplication operator have the same operator precedence, and they group left-to-right. Thus your expression is effectively

force.length = this.gravity * pa.mass * pb.mass;

I think perhaps your expectations of how the simulation should work may be off.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 'I think perhaps your expectations of how the simulation should work may be off.' Heh, yes, well my expectation is that I'm simulating the universal law of gravitation. As you point out the distance is not a factor in the equation, so that's a pretty good sign I'm doing something wrong. The odd thing is that the simulation does seem (in watching it run) to take into account the distance of bodies. The angle of the force vector does implicitly contain some length information `force.angle = pb.curr.subtract(pa.curr); force.length = this.gravity * pa.mass * pb.mass` – Hal50000 Jan 20 '16 at 16:39
  • ...actually, there's no length or distance added to the force. the force is just a constant of gravity * mass. It yields some interesting results, but is probably not a true n-body sim. – Hal50000 Jan 23 '16 at 05:38