次の 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 }