2012-10-21 54 views
0

我想解決我的java類中的Nbody示例(這是我在java中的第一個學期)。是爲什麼行星不會在Nbody.java中旋轉?

該方案的細節如下:

寫一個程序Nbody.java,在使用掃描儀從標準輸入宇宙讀取,模擬使用上述的越級方案及其動力學,並使用我們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);   
    } 
} 
} 

有什麼想法?

+1

究竟是不是正確的工作?計算錯誤還是顯示?如果是後者,是否嘗試過打印出每次迭代的結果,以便查看位置/速度是否正在更新,並且是否合理?請記住,StdDraw不是標準Java的一部分,所以我們不能輕易地嘗試你的程序... – DNA

+0

我相信這是錯誤的計算。回想起來,我有相同的公式計算當前身體與所有其他身體之間的重力吸引力,以及只有當兩個身體不同時.. – Ryan

+0

我也收到運行時錯誤: 線程中的異常「 main「java.lang.ArrayIndexOutOfBoundsException:5 \t at Nbody.main(Nbody.java:107) – Ryan

回答

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 

此計算x和作用於body由於body2力的y分量,然後添加爲body x和y力部件,並從body2減去他們。通過索引body + 1,我們可以計算同一內環通道中兩個物體上的相等和相反的力,從而將計算次數減少一半。

對於更新位置,您使用的是時間增量結束時的速度,就好像物體在增量結束時以整個增量速度移動一樣。做某種插值可能更準確,但這應該是二階效應。

+0

您定義的新雙打在我嘗試編譯「由於不兼容類型」時生成錯誤:/ – Ryan

+0

更改爲:雙fx = f * dx/d; double fy = f * dy/d; – chrome

+0

嗯,現在我回到問題行星沒有更新和接收數組超出界限誤差在線95(雙DX = X [身體2] - X [身體]) – Ryan