next up previous contents
Next: A..4 2006年1月の再挑戦 Up: A..3 2005年12月の再挑戦 Previous: A..3.1 NewHeat1D.java

A..3.2 NewHeat1Dv3.java

スレッドを使うと次の NewHeat1Dv3.java (実行は http://nalab.mind.meiji.ac.jp/~mk/labo/java/sample/NewHeat1Dv3.html) のようになる。


   1 /*
   2  * NewHeat1Dv3.java
   3  *   version 2.0: 計算スレッドを用意した。
   4  *   version 3.0: ボタン、テキスト・フィールドなどを用意して再計算可能にした。
   5  *   version 4.0: (予定) 陰解法、境界条件の一般化
   6  *   version 5.0: (予定) 初期条件の種類を増やす
   7  */
   8 
   9 import java.awt.Button;
  10 import java.awt.Color;
  11 import java.awt.Frame;
  12 import java.awt.Graphics;
  13 import java.awt.Image;
  14 import java.awt.Label;
  15 import java.awt.TextField;
  16 import java.awt.event.ActionEvent;
  17 import java.awt.event.ActionListener;
  18 import java.awt.event.WindowAdapter;
  19 import java.awt.event.WindowEvent;
  20 
  21 public class NewHeat1Dv3 extends Frame implements Runnable,ActionListener {
  22     /**
  23      * 
  24      */
  25     private static final long serialVersionUID = 1L;
  26     /**
  27      * 
  28      */
  29     static final int ImgX = 500, ImgY = 500;
  30     static final int WinX = ImgX + 200, WinY = ImgY;
  31     Thread th = null;
  32     Image im = null;
  33     Graphics bg = null;
  34     int i, n = -1, nMax;
  35     int N;
  36     double lambda, Tmax, dt, theta;
  37     double h, tau;
  38     int skip;
  39     double [] x, u, newu;
  40     double ratiox, ratioy, X0, Y0;
  41     private String[] labelStr={"N", "lamba", "Tmax", "dt", "theta"};
  42     private Label[] label;
  43     private String[] txStr={"100", "0.5", "1.0", "0.01", "0.5"};
  44     private TextField[] tf;
  45     private String[] btStr = {"Start", "End"};
  46     private Button[] bt;
  47     private void readParameters() {
  48         N = Integer.parseInt(tf[0].getText());
  49         lambda = Double.valueOf(tf[1].getText()).doubleValue();
  50         Tmax = Double.valueOf(tf[2].getText()).doubleValue();
  51         dt = Double.valueOf(tf[3].getText()).doubleValue();
  52         theta = Double.valueOf(tf[4].getText()).doubleValue();
  53     }
  54     public NewHeat1Dv3() {
  55         this.setSize(WinX, WinY);
  56         this.addWindowListener(new WindowAdapter() {
  57                 public void windowClosing(WindowEvent ev) {
  58                     System.exit(0);
  59                 }
  60             });
  61         setLayout(null);
  62         bt = new Button[btStr.length];
  63         for (int i = 0; i < bt.length; i++) {
  64             bt[i] = new Button(btStr[i]);
  65             bt[i].addActionListener(this);
  66             bt[i].setBounds(ImgX, (i+2)*20, (WinX - ImgX)/2, 20);
  67             add(bt[i]);
  68         }
  69         label = new Label[labelStr.length];
  70         tf = new TextField[txStr.length];
  71         for (int i = 0; i < labelStr.length; i++) {
  72             label[i] = new Label(labelStr[i]);
  73             tf[i] = new TextField(txStr[i]);
  74             label[i].setBounds(ImgX, (i+bt.length+2)*20, (WinX - ImgX) / 3, 20);
  75             tf[i].setBounds(ImgX + (WinX-ImgX)/3, (i+bt.length+2)*20, (WinX-ImgX)/2, 20);
  76             add(label[i]);
  77             add(tf[i]);
  78         }
  79         this.setVisible(true);
  80         bt[0].setEnabled(false);
  81         space(-0.1, -0.1, 1.1, 1.1);
  82         // 計算開始の準備
  83         initcomputation();
  84         // 計算スレッドを開始する
  85         this.start();
  86     }
  87     public void start() {
  88         if (th == null) {
  89             th = new Thread(this);
  90             th.start();
  91         }
  92     }
  93     public void stop() {
  94         if (th != null) {
  95             th = null;
  96         }
  97     }
  98     public static void main(String[] args) {
  99         new NewHeat1Dv3();
 100     }
 101     // 座標変換の仕組み
 102     private void space(double x0, double y0, double x1, double y1) {
 103         X0 = x0; Y0 = y0;
 104         ratiox = ImgX / (x1 - x0);
 105         ratioy = ImgY / (y1 - y0);
 106     }
 107     // x座標をユーザー座標からウィンドウ座標に
 108     private int wx(double x) {
 109         return (int)Math.rint(ratiox * (x - X0));
 110     }
 111     // y座標をユーザー座標からウィンドウ座標に
 112     private int wy(double y) {
 113         return ImgY - (int)Math.rint(ratioy * (y - Y0));
 114     }
 115     // 初期データ
 116     private double f(double x) {
 117         if (x <= 0.5)
 118             return x;
 119         else
 120             return 1.0 - x;
 121     }
 122     // 現在の u[] をグラフ化する
 123     private void drawGraph() {
 124         if (bg == null)
 125             repaint();
 126         for (int i = 0; i < N; i++)
 127             bg.drawLine(wx(x[i]), wy(u[i]), wx(x[i+1]), wy(u[i+1]));
 128     }
 129     // ダブルバッファリングの定跡
 130     public void paint(Graphics g) {
 131         if (im == null) {
 132             // createImage() はコンストラクターでは使えず、このタイミングでするしかないとか。
 133             im = this.createImage(this.getWidth(), this.getHeight());
 134             bg = im.getGraphics();
 135         }
 136         g.drawImage(im, 0, 0, this);
 137     }
 138     private void initcomputation() {
 139         // パラメーターを読む
 140         readParameters();
 141         // 刻み幅を決める
 142         h = 1.0 / N;
 143         tau = lambda * h * h;
 144         //
 145         skip = (int)Math.rint(dt / tau);
 146         if (skip <= 0) skip = 1;
 147         nMax = (int)Math.ceil(Tmax / tau);
 148         // ベクトルを3本用意する
 149         x = new double [N+1];
 150         u = new double [N+1];
 151         newu = new double [N+1];
 152         //
 153         n = -1;
 154         System.out.println("init");
 155     }
 156     // 計算スレッド
 157     public void run() {
 158         while (th != null) {
 159             if (n == -1) {
 160                 // 初期値を計算する
 161                 for (int i = 0; i <= N; i++)
 162                     x[i] = i * h;
 163                 for (i = 0; i <= N; i++)
 164                     u[i] = f(i * h);
 165                 n++;
 166                 repaint();
 167                 bg.setColor(Color.white);
 168                 bg.fillRect(0, 0, ImgX, ImgY);
 169                 bg.setColor(Color.black);
 170                 drawGraph();
 171                 repaint();
 172                 try {
 173                     Thread.sleep(10);
 174                 } catch (Exception ex) {
 175                     ex.printStackTrace();
 176                 }
 177             }
 178             else if (n < nMax) {
 179                 do {
 180                     for (i = 1; i < N; i++)
 181                         newu[i] = (1 - 2 * lambda) * u[i] + lambda * (u[i + 1] + u[i - 1]);
 182                     for (i = 1; i < N; i++)
 183                         u[i] = newu[i];
 184                     u[0] = 0.0;
 185                     u[N] = 0.0;
 186                     n++;
 187                 } while (n % skip != 0);
 188                 drawGraph();
 189                 repaint();
 190                 try {
 191                     Thread.sleep(10);
 192                 } catch (Exception ex) {
 193                     ex.printStackTrace();
 194                 }
 195                 // System.out.println(""+ n * tau);
 196             }
 197             Thread.yield();
 198         }
 199     }
 200     public void actionPerformed(ActionEvent e) {
 201         // TODO 自動生成されたメソッド・スタブ
 202         if (e.getSource() == bt[0]) {
 203             bt[0].setEnabled(false);
 204             bt[1].requestFocus();
 205             bt[1].setEnabled(true);
 206             initcomputation();
 207             start();
 208         }
 209         if (e.getSource() == bt[1]) {
 210             bt[0].setEnabled(true);
 211             bt[0].requestFocus();
 212             bt[1].setEnabled(false);
 213             stop();
 214         }
 215     }
 216 }


next up previous contents
Next: A..4 2006年1月の再挑戦 Up: A..3 2005年12月の再挑戦 Previous: A..3.1 NewHeat1D.java
Masashi Katsurada
平成20年2月28日