我正在尝试解决我的java类中的Nbody示例(这是我在java中的第一个学期)。
该计划的详情如下:
编写一个程序Nbody.java,使用Scanner从标准输入读取Universe,使用上述的跳过跳跃方案模拟其动态,并使用我们的StdDraw对其进行动画处理。维护几个数组来存储数据。要进行计算机模拟,请编写一个无限循环,重复更新粒子的位置和速度。绘图时,请考虑使用StdDraw.setXscale(-R,+ R)和StdDraw.setYscale(-R,+ R)将物理坐标缩放到屏幕坐标。
我写了以下代码,编译和编译加载背景图片,歌曲和&行星的位置正确。但是,我不能让它们按原样旋转。
这是我的代码:
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);
}
}
}
有什么想法吗?
答案 0 :(得分:2)
你的力量计算对我来说似乎有点偏差。我这样做:
Arrays.fill(Fx, 0.0);
Arrays.fill(Fy, 0.0);
for (int body = 0; body < bodyNum - 1; body++) {
for (int body2 = body + 1; body2 < bodyNum; body2++) {
double dx = x[body2] - x[body];
double dy = y[body2] - y[body];
double d2 = dx * dx + dy * dy;
double d = Math.sqrt(d2);
double f = G * m[body] * m[body2] / d2;
double fx = f * dx / d;
double fy = f * dy / d;
Fx[body] += fx;
Fy[body] += fy;
Fx[body2] -= fx;
Fy[body2] -= fy;
}
}
// then update positions and velocities based on Fx and Fy arrays
这会计算由body
引起的body2
上的力的x和y分量,然后将其添加到body
的x和y力分量中,并从{body2
中减去它们。 1}}。通过从body + 1
索引,我们可以在同一内环通道中考虑两个物体上的相等和相反的力,将计算次数减少一半。
对于更新位置,您在时间差的末尾使用速度,就好像物体在三角洲末端的速度下移动整个三角洲一样。进行某种插值可能更准确,但这应该是二阶效应。