quietsamurai98 quietsamurai98 - 2 months ago 8
Java Question

Optimizing an n-body gravitational attraction algorithm

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

Answer

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