0

I'm making a simple n-Body Simulation. For now, I'm "bruteforcing" it, this means I calculate every force excerted by every object on every other object every frame.

My problem right now is that if I choose a big number of objects, say 2000, in some cases right at the start the objects "planets" dissapear withing about 2 frames. When I check what's happening by adding System.out.println(PlanetHandler.planets.get(0).position.x); into the main loop, I get

487.0
486.99454
NaN
NaN

By commenting out some stuff and trial-and-error, I found that the problem lies here:

private static void computeAndSetPullForce(Planet planet)
{
    for(Planet otherPlanet : planets)
    {
        //Also here, if we are deleting the planet, don't interact with it.
        if(otherPlanet != planet && !otherPlanet.delete)
        {
            //First we get the x,y and magnitudal distance between the two bodies.
            int xDist = (int) (otherPlanet.position.x - planet.position.x);
            int yDist = (int) (otherPlanet.position.y - planet.position.y);
            float dist = Vector2Math.distance(planet.position, otherPlanet.position);

            //Now we compute first the total and then the component forces
            //Depending on choice, use r or r^2
            float force = Constants.GRAVITATIONAL_CONSTANT * ((planet.mass*otherPlanet.mass)/(dist*dist)); 
            float forceX = force * xDist/dist;
            float forceY = force * yDist/dist;

            //Given the component forces, we construct the force vector and apply it to the body.
            Vector2 forceVec = new Vector2(forceX, forceY);
            planet.force = Vector2Math.add(planet.force, forceVec);
        }
    }
}

The "planets" list is a CopyOnWriteArray<Planets>. I've been at this for quite some time now, but haven't figured out what might be causing the values (position, velocity) to go Nan. Maybe someone who's either had some experience with this or is generally adept at this sort of thing could help me out.

Code0
  • 74
  • 1
  • 10
  • The only thing that seem to be able to edit planet.position in what you posted is Vector2Math.distance – Winter Jun 19 '18 at 12:02
  • 1
    You use a distance formula (implying a square root) but you always use the square of the result. You could save some speed by getting the length squared instead. (Always minimize the amount of sqrt/pow calls in a physics engine) – Winter Jun 19 '18 at 12:03
  • But then how would I be able to calculate ` float force = Constants.GRAVITATIONAL_CONSTANT * ((planet.mass*otherPlanet.mass)/(dist*dist)); float forceX = force * xDist/dist; float forceY = force * yDist/dist;`? I can only figure out the components by using geometry if I'm correct. – Code0 Jun 19 '18 at 13:18
  • `float` is a terrible floating point type for any serious usage, and only has around 7-8 digits of precision. Prefer `double` at the very least. – Mike Allen Jun 21 '18 at 20:07

1 Answers1

1

This is the typical case when JVM gives you a NAN. The one you encounter was zero divided by zero( 0/0 ) which in mathematics is an indeterminate form.

if float dist = Vector2Math.distance(planet.position, otherPlanet.position);

returns you 0.

The next statement

float force = Constants.GRAVITATIONAL_CONSTANT * ((planet.mass*otherPlanet.mass)/(dist*dist)); 

in which you compute the force gets divided by zero.

Also, I would recommend you to use BigDecimal whenever precision is required. You can also refer to one of the answers here

Yati Sawhney
  • 1,372
  • 1
  • 12
  • 19
  • Divide by zero throws an exception (for Integers) or gives you Infinity (for doubles and floats). zero divided by zero gets you a NaN, though – Phil Barr Jun 19 '18 at 12:09
  • @PhilBarr my bad its 0/0!! Updated – Yati Sawhney Jun 19 '18 at 12:09
  • I don't see it myself - seems like you might want to put a load of System.out.println() debugging statements in there for wherever you have a division. Maybe your planets are overlapping each other? Also 0/0 isn't the only thing that will get you a NaN. sqrt(x<0) will also do it (I don't see a sqrt in your code but maybe there is elsewhere) – Phil Barr Jun 19 '18 at 12:18
  • there are other things that can cause a NaN. like sqrt(x<0) – Phil Barr Jun 19 '18 at 12:24
  • That thing is a multiplier of iota typically imaginary number :) – Yati Sawhney Jun 19 '18 at 12:25