1

I'm writing a simulation of a 2d protoplanetary disk, and right now, the most time consuming bit of code is calculating the gravitational attraction. This is the code I'm currently using.

for(int i=0; i<particleCount; i++){
    if(boolArray[i]){    //boolArray is linked with particleArray, false means the linked particle has collided with another particle and no longer exists
        double iX = particleArray[i].getXPosition();
        double iY = particleArray[i].getYPosition();
        double iM = particleArray[i].getMass();
        for(int j=0; j<particleCount; j++){
            if(i!=j&&boolArray[j]){
                double rX = iX-particleArray[j].getXPosition();
                double rY = iY-particleArray[j].getYPosition();
                double rT = Math.sqrt(rX*rX+rY*rY);
                double rF = rT*rT*rT;
                double fT = -constantGravity*iM*particleArray[j].getMass()/rF;
                particleArray[i].updateForce(rX*fT, rY*fT);
            }
        }
    }
}

Does anybody have any ideas on how to speed it up? I think the sqrt in

double rT = Math.sqrt(rX*rX+rY*rY);

is the biggest culprit, but I'm not sure if I could even get rid of it.

The compile-ready code can be found at https://github.com/quietsamurai98/2D-Accretion-Simulation/tree/Trails-png

  • Java uses Smart Power algorithm for sqrt function which has complexity of O(log n) which is fast. That is not the reason for delay – Rishi Sep 22 '16 at 00:28
  • have you considered to use sectors instead of particles for homogenouos areas (dust ...)? That should lower the amount of objects considerably of coarse the accuracy will be a bit lower but if you realize the discrete integration is far from reality anyway ... so stretching accuracy a bit more should not have too big impact. To be sure you should compare results after few iteration with booth approaches they should be +/- the same – Spektre Sep 22 '16 at 06:04

2 Answers2

1

You are calculating twice for each pair of point. Try this.

for (int i = 0; i < particleCount; i++) {
    if (boolArray[i]) { // boolArray is linked with particleArray, false
                        // means the linked particle has collided with
                        // another particle and no longer exists
        double iX = particleArray[i].getXPosition();
        double iY = particleArray[i].getYPosition();
        double iM = particleArray[i].getMass();
        for (int j = i + 1; j < particleCount; j++) {
            if (boolArray[j]) {
                double rX = iX - particleArray[j].getXPosition();
                double rY = iY - particleArray[j].getYPosition();
                double rT = Math.sqrt(rX * rX + rY * rY);
                double rF = rT * rT * rT;
                double fT = -constantGravity * iM * particleArray[j].getMass() / rF;
                particleArray[i].updateForce(rX * fT, rY * fT);
                particleArray[j].updateForce(-rX * fT, -rY * fT);
            }
        }
    }
}
1

You can also use quad-trees(or octrees for 3d). You then calculate the force of gravity from each body within the same cell and then for every outside cell calculate the sum of the masses within the cell and calculate the force of gravity from the center of that cell with said mass. This will lose precision but with a well balanced quad tree and very large number of N-Bodies will look pretty realistic. https://en.wikipedia.org/wiki/Barnes%E2%80%93Hut_simulation

py13579
  • 56
  • 5