次の Heat1d_e_3.java (実行は http://nalab.mind.meiji.ac.jp/~mk/labo/java/sample/Heat1d_e_3.html) は最初に書いた叩き台プログラムである。
1 /* 2 * Heat1d_e_3.java 3 * 1998年9月20日 (子供が産まれるちょっと前だったわけか) 4 * 5 * コンパイル: javac Heat1d_e_3.java 6 * 実行: appletviewer Heat1d_e_3.java 7 * 8 * <APPLET code="Heat1d_e_3.class" width=500 height=500></APPLET> 9 * 10 * 注意 11 * 何と言っても古いので JDK1.1 以降では警告される。 12 * (1) reshape() よりも setBounds() を使えと言われる (置き換えれば OK)。 13 * (2) action() もよせ、と言われる。 14 */ 15 16 import java.applet.*; 17 import java.awt.*; 18 19 public class Heat1d_e_3 extends Applet { 20 21 static final boolean DEBUG = false; // true; 22 private static final String message = "1D Heat Equation"; 23 private int N = 40; 24 private double Tmax = 0.5, lambda = 0.5; 25 // 座標系の変換のためのパラメーター 26 private double ratiox, ratioy, X0, Y0; 27 // ユーザーとのインターフェイス (パラメーターの入力) 28 private Label labelLambda, labelN; 29 private TextField inputLambda, inputN; 30 private Button startB; 31 32 // 準備 (変数の用意と座標系の初期化など) 33 public void init() { 34 // 35 setLayout(null); 36 37 labelLambda = new Label("lambda (should be <= 1/2)"); 38 add(labelLambda); 39 labelLambda.setBounds(100, 100, 200, 30); 40 inputLambda = new TextField("" + lambda); 41 add(inputLambda); 42 inputLambda.setBounds(300, 100, 100, 30); 43 44 labelN = new Label("N"); 45 add(labelN); 46 labelN.setBounds(100, 130, 200, 30); 47 inputN = new TextField("" + N); 48 add(inputN); 49 inputN.setBounds(300, 130, 100, 30); 50 51 startB = new Button("Restart"); 52 add(startB); 53 startB.setBounds(250, 180, 50, 30); 54 55 space(-0.1, -0.1, 1.1, 1.1); 56 } 57 // ボタンを押されたら、テキスト・フィールドの内容を読み取って、再描画 58 public boolean action(Event evt, Object what) { 59 if (evt.target == startB) { 60 String str1 = inputLambda.getText(); 61 String str2 = inputN.getText(); 62 lambda = Double.valueOf(str1).doubleValue(); 63 N = Integer.parseInt(str2); 64 repaint(); 65 } 66 return true; 67 } 68 69 // 初期条件 70 private double f(double x) { 71 if (x <= 0.5) 72 return x; 73 else 74 return 1-x; 75 } 76 // 座標変換の準備 77 private void space(double x0, double y0, double x1, double y1) { 78 X0 = x0; Y0 = y0; 79 ratiox = 500 / (x1 - x0); 80 ratioy = 500 / (y1 - y0); 81 } 82 // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) 83 private int wx(double x) { 84 return (int)(ratiox * (x - X0)); 85 } 86 // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) 87 private int wy(double y) { 88 return 500 - (int)(ratioy * (y - Y0)); 89 } 90 // x[], y[] の内容をグラフにする 91 private void drawGaph(Graphics g, double x[], double u[]) { 92 for (int i= 0; i < N; i++) 93 g.drawLine(wx(x[i]), wy(u[i]), wx(x[i + 1]), wy(u[i + 1])); 94 } 95 96 public void paint(Graphics g) { 97 98 double h = 1.0 / N; 99 double tau = lambda * h * h; 100 double dt = 0.01; 101 int Jmax = (int) (Tmax / tau); 102 int skip = (int) (dt / tau + 0.5); 103 double [] u, unext, x; 104 105 // ベクトルを確保する 106 x = new double[N+1]; 107 u = new double[N+1]; 108 unext = new double[N+1]; 109 for (int i = 0; i <= N; i++) 110 x[i] = i * h; 111 112 // これはあんまり意味がない。 113 g.setColor(Color.pink); 114 g.fillOval(10, 10, 330, 80); 115 g.setColor(Color.red); 116 for (int i=0; i<4;i++) 117 g.drawOval(10-i, 10-i, 330+2*i, 80+2*i); 118 119 // タイトルを表示する 120 g.setColor(Color.black); 121 g.setFont(new Font("Helvetica", Font.BOLD, 24)); 122 g.drawString(message, 40, 75); 123 124 // 初期値を計算する 125 for (int i = 0; i <= N; i++) 126 u[i] = f(i * h); 127 128 // 初期値のグラフを描く 129 drawGaph(g, x, u); 130 131 // 時間に関するループ 132 for (int j = 1; j <= Jmax; j++) { 133 int i; 134 for (i = 1; i < N; i++) 135 unext[i] = (1 - 2 * lambda) * u[i] 136 + lambda * (u[i-1] + u[i+1]); 137 for (i = 1; i < N; i++) 138 u[i] = unext[i]; 139 u[0] = 0; u[N] = 0; 140 141 if (DEBUG) 142 for (i = 0; i <= N; i++) 143 System.out.println("u[" + i + "]=" + u[i]); 144 // 適当な間隔 (dt=0.01) でグラフを描く 145 if (j % skip == 0) 146 drawGaph(g, x, u); 147 } 148 } 149 }