I am trying to tackle the Nbody example in my java class (this is my first semester in java).
The Details of the program are as follows:
Write a program Nbody.java that reads in the universe from standard input using Scanner, simulates its dynamics using the leapfrog scheme described above, and animates it using our StdDraw. Maintain several arrays to store the data. To make the computer simulation, write an infinite loop that repeatedly updates the position and velocity of the particles. When plotting, consider using StdDraw.setXscale(-R, +R) and StdDraw.setYscale(-R, +R) to scale the physics coordinates to the screen coordinates.
I’ve written the following code which compiles & loads the background image, the song, & the planets with correct placement. However, I cannot get the plantes to rotate as they should.
Here is my code:
import java.util.Scanner;
public class Nbody {
// method dist calculates distance between two points
// it accepts four double values (x1, y1, x2, y2)
// it returns a double value
private static double dist(double x1, double y1, double x2, double y2)
{
double r;
r = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
return r;
}
public static void main(String[] args) {
final double G = 6.67e-11; // constant value G
final double deltaT = 25000.0; // constant value delta T, which determines animation interval
// ax and ay are accerlations on x axis and y axis
double ax;
double ay;
Scanner scan = new Scanner (System.in); // define a keyboard object: scan
int bodyNum = scan.nextInt(); // read in the first integer, which specify how many particles
double radius = scan.nextDouble(); // read in radius of universe
// define arrays to save x values and y values of each particle
double[] x = new double[bodyNum];
double[] y = new double[bodyNum];
// define arrays to save velocity of each particle
double[] vx = new double[bodyNum];
double[] vy = new double[bodyNum];
double[] m = new double[bodyNum]; // array stores mass of each particle
String[] name = new String[bodyNum]; // array stores file name of each particles
double[] Fx = new double[bodyNum]; // force on X axis
double[] Fy = new double[bodyNum]; // force on Y axis
StdDraw.setXscale(-radius, radius); // Set the X scale
StdDraw.setYscale(-radius, radius); // Set the Y scale
StdDraw.picture(0, 0, "starfield.jpg"); // Display background pic centered at (0,0)
// read in inital location values and velocity values for each particle
for (int i = 0; i < bodyNum; i++)
{
x[i] = scan.nextDouble();
y[i] = scan.nextDouble();
vx[i] = scan.nextDouble();
vy[i] = scan.nextDouble();
m[i] = scan.nextDouble();
name[i] = scan.next();
StdDraw.picture(x[i], y[i], name[i]); // display particle pic on screen
}
// This following line play background music, uncomment it in lab
// If you work from a remote location via VNC, comment it
StdAudio.play("2001.mid");
// main animation loop
while(true){
// array Fx and Fy store net force acting on each body
// initialize these two arrays to zeros
for (int n = 0; n<bodyNum; n++)
{
Fx[n] = 0.0;
Fy[n] = 0.0;
}
// for loop to process all bodies
for(int body = 0; body<bodyNum; body++)
{
// calculate the gravitational attraction between current body
// and all other bodies
Fx[body] = (m[body] * m[body+1]) / (x[body+1] -x[body])*G;
Fy[body] = (m[body] * m[body+1]) / (y[body+1] -y[body])*G;
for (int j = 0; j < bodyNum; j++)
{
// calculate only when two bodies are different
// Please fill out the following if statement body
if(body != j)
{
Fx[j] = (m[j] * m[j+1]) / (y[j+1] -y[j])*G;
Fy[j] = (m[j] * m[j+1]) / (y[j+1] -y[j])*G;
}
}
}
// update vleocity value and location value for each particle
// please fill out the for loop
for (int j = 0; j < bodyNum; j++)
{
// calculate accleration rate
ax = Fx[j] / m[j];
ay = Fy[j] / m[j];
// update vleocity value
vx[j] = vx[j] + deltaT * ax;
vy[j] = vy[j] + deltaT * ay;
// update location value
x[j] = x[j] + deltaT * vx[j];
y[j] = y[j] + deltaT * vy[j];
}
// redraw background
StdDraw.setXscale(-radius, radius);
StdDraw.setYscale(-radius, radius);
StdDraw.picture(0, 0, "starfield.jpg");
for (int i = 0; i < bodyNum; i++){
// display the particle
StdDraw.picture(x[i], y[i], name[i]);
}
// display and pause for 30ms
StdDraw.show(30);
}
}
}
Any thoughts?
Your force calculations seem quite a bit off to me. I’d do it like this:
This computes the x and y components of the force acting on
bodydue tobody2and then adds that to the x and y force components forbodyand subtracts them frombody2. By indexing frombody + 1, we can account for equal-and-opposite forces on two bodies in the same inner loop pass, reducing the number of calculations by half.For updating positions, you are using the velocity at the end of the time delta, as if the bodies were moving for the entire delta at the velocity at the end of the delta. It might be more accurate to do some sort of interpolation, but that should be a second order effect.