2015-03-30 76 views
0

我在这里有这个小程序,我必须使它在多线程中工作。我尝试,但它似乎将线程数设置为1时,程序按预期运行。所以,通常程序运行正常。但是,如果我设置值可以说2或4.正在变得疯狂。我没有得到所需的结果。这似乎是计算错误。我将我的头撞在墙上,试图弄清楚什么是错的,但是,我尝试的所有东西似乎都不能解决问题。继承人是连续代码:在多线程中运行Java分子动态仿真程序

/* 
* "Physics" part of code adapted from Dan Schroeder's applet at: 
* 
*  http://physics.weber.edu/schroeder/software/mdapplet.html 
*/ 

import java.awt.* ; 
import javax.swing.* ; 

public class MD { 

    // Size of simulation 

    final static int N = 2000 ; // Number of "atoms" 
    final static double BOX_WIDTH = 100.0 ; 


    // Initial state - controls temperature of system 

    //final static double VELOCITY = 3.0 ; // gaseous 
    final static double VELOCITY = 2.0 ; // gaseous/"liquid" 
    //final static double VELOCITY = 1.0 ; // "crystalline" 

    final static double INIT_SEPARATION = 2.2 ; // in atomic radii 


    // Simulation 

    final static double DT = 0.01 ; // Time step 


    // Display 

    final static int WINDOW_SIZE = 800 ; 
    final static int DELAY = 0 ; 
    final static int OUTPUT_FREQ = 20 ; 


    // Physics constants 

    final static double ATOM_RADIUS = 0.5 ; 

    final static double WALL_STIFFNESS = 500.0 ; 
    final static double GRAVITY = 0.005 ; 
    final static double FORCE_CUTOFF = 3.0 ; 


    // Atom positions 
    static double [] x = new double [N] ; 
    static double [] y = new double [N] ; 

    // Atom velocities 
    static double [] vx = new double [N] ; 
    static double [] vy = new double [N] ; 

    // Atom accelerations 
    static double [] ax = new double [N] ; 
    static double [] ay = new double [N] ; 


    public static void main(String args []) throws Exception { 

     Display display = new Display() ; 

     // Define initial state of atoms 

     int sqrtN = (int) (Math.sqrt((double) N) + 0.5) ; 
     double initSeparation = INIT_SEPARATION * ATOM_RADIUS ; 
     for(int i = 0 ; i < N ; i++) { 
      // lay out atoms regularly, so no overlap 
      x [i] = (0.5 + i % sqrtN) * initSeparation ; 
      y [i] = (0.5 + i/sqrtN) * initSeparation ; 
      vx [i] = (2 * Math.random() - 1) * VELOCITY ; 
      vy [i] = (2 * Math.random() - 1) * VELOCITY ; 
     } 

     int iter = 0 ; 
     while(true) { 

      if(iter % OUTPUT_FREQ == 0) { 
       System.out.println("iter = " + iter + ", time = " + iter * DT) ; 
       display.repaint() ; 
       Thread.sleep(DELAY) ; 
      } 

      // Verlet integration: 
      // http://en.wikipedia.org/wiki/Verlet_integration#Velocity_Verlet 

      double dtOver2 = 0.5 * DT; 
      double dtSquaredOver2 = 0.5 * DT * DT; 
      for (int i = 0; i < N; i++) { 
       x[i] += (vx[i] * DT) + (ax[i] * dtSquaredOver2); 
         // update position 
       y[i] += (vy[i] * DT) + (ay[i] * dtSquaredOver2); 
       vx[i] += (ax[i] * dtOver2); // update velocity halfway 
       vy[i] += (ay[i] * dtOver2); 
      } 

      computeAccelerations(); 

      for (int i = 0; i < N; i++) { 
       vx[i] += (ax[i] * dtOver2); 
         // finish updating velocity with new acceleration 
       vy[i] += (ay[i] * dtOver2); 
      } 

      iter++ ; 
     } 
    } 

    // Compute accelerations of all atoms from current positions: 
    static void computeAccelerations() { 

     double dx, dy; // separations in x and y directions 
     double dx2, dy2, rSquared, rSquaredInv, attract, repel, fOverR, fx, fy; 

     // first check for bounces off walls, and include gravity (if any): 
     for (int i = 0; i < N; i++) { 
      if (x[i] < ATOM_RADIUS) { 
       ax[i] = WALL_STIFFNESS * (ATOM_RADIUS - x[i]); 
      } 
      else if (x[i] > (BOX_WIDTH - ATOM_RADIUS)) { 
       ax[i] = WALL_STIFFNESS * (BOX_WIDTH - ATOM_RADIUS - x[i]); 
      } 
      else { 
       ax[i] = 0.0; 
      } 
      if (y[i] < ATOM_RADIUS) { 
       ay[i] = (WALL_STIFFNESS * (ATOM_RADIUS - y[i])); 
      } 
      else if (y[i] > (BOX_WIDTH - ATOM_RADIUS)) { 
       ay[i] = (WALL_STIFFNESS * (BOX_WIDTH - ATOM_RADIUS - y[i])); 
      } 
      else { 
       ay[i] = 0; 
      } 
      ay[i] -= GRAVITY ; 
     } 

     double forceCutoff2 = FORCE_CUTOFF * FORCE_CUTOFF ; 

     // Now compute interaction forces (Lennard-Jones potential). 
     // This is where the program spends most of its time. 


     for (int i = 1; i < N; i++) { 
      for (int j = 0; j < i; j++) {   // loop over all distinct pairs 
       dx = x[i] - x[j]; 
       dx2 = dx * dx; 
       if (dx2 < forceCutoff2) {    // make sure they're close enough to bother 
        dy = y[i] - y[j]; 
        dy2 = dy * dy; 
        if (dy2 < forceCutoff2) { 
         rSquared = dx2 + dy2; 
         if (rSquared < forceCutoff2) { 
          rSquaredInv = 1.0/rSquared; 
          attract = rSquaredInv * rSquaredInv * rSquaredInv; 
          repel = attract * attract; 
          fOverR = 24.0 * ((2.0 * repel) - attract) * rSquaredInv; 
          fx = fOverR * dx; 
          fy = fOverR * dy; 
          ax[i] += fx; // add this force on to i's acceleration (mass = 1) 
          ay[i] += fy; 

          ax[j] -= fx; // Newton's 3rd law 
          ay[j] -= fy; 
         } 
        } 
       } 
      } 
     } 
    } 


    static class Display extends JPanel { 

     static final double SCALE = WINDOW_SIZE/BOX_WIDTH ; 

     static final int DIAMETER = 
       Math.max((int) (SCALE * 2 * ATOM_RADIUS), 2) ; 

     Display() { 

      setPreferredSize(new Dimension(WINDOW_SIZE, WINDOW_SIZE)) ; 

      JFrame frame = new JFrame("MD"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setContentPane(this); 
      frame.pack(); 
      frame.setVisible(true); 
     } 

     public void paintComponent(Graphics g) { 
      g.setColor(Color.WHITE) ; 
      g.fillRect(0, 0, WINDOW_SIZE, WINDOW_SIZE) ; 
      g.setColor(Color.BLUE) ; 
      for(int i = 0 ; i < N ; i++) { 
       g.fillOval((int) (SCALE * (x [i] - ATOM_RADIUS)), 
          WINDOW_SIZE - 1 - (int) (SCALE * (y [i] + ATOM_RADIUS)), 
          DIAMETER, DIAMETER) ; 
      } 
     } 
    } 
} 

任何人都可以发现最新的问题?

回答

0

beginend被声明为静态,所以所有线程在计算过程中都错误地使用了相同的变量。

A)的开始/结束将被错误地在他们的方法中运行()

B的开始时设定到的螺纹之间的竞争条件的一些随机输出)的所有线程将在相同的索引的范围潜在地工作忽略其余的位置,速度,加速度阵列。

而且所有线程在运行uncessary完全相同的代码:

  for (int i = 0; i < N; i++) { 
       x[i] += (vx[i] * DT) + (ax[i] * dtSquaredOver2); 
       // update position 
      ... 

我会建议改变所有的变量实例变量,然后要通过代码修改为静态的只有那些应之间共享线程。读取静态变量是好的,写入必须检查,如果他们是独占的。 (写入x的不同部分,vx ...数组在这个意义上是'独占的',只要确保索引不重叠即可)。

+0

斑点。我从末端移除静态并开始。并在你提到的循环中使用它们。它的工作现在。感谢Zielu – Bobys 2015-03-31 00:29:13