Heat1dyou.java は (実行は http://nalab.mind.meiji.ac.jp/~mk/labo/java/sample/Heat1dyou.html)、 大したことはしていない (イベント処理を JDK 1.1 以降のそれに置き換えた)。
1 /*
2 * Heat1dyou.java --- Heat1d_e_4.java を JDK 1.2 に合わせて変更したもの
3 * 2001年1月18日
4 *
5 * コンパイル: javac Heat1dyou.java
6 * 実行: appletviewer Heat1dyou.java
7 *
8 * <applet code ="Heat1dyou" width=500 height=500></applet>
9 */
10
11 import java.applet.*;
12 import java.awt.*;
13 import java.awt.event.*;
14
15 public class Heat1dyou extends Applet implements ActionListener {
16
17 public int N = 20;
18 public double lambda = 0.5;
19 public double Tmax = 0.5;
20 // ユーザーとのインターフェイス
21 public Label labelLambda, labelN, labelTmax;
22 public TextField inputLambda, inputN, inputTmax;
23 public Button startB;
24 // 差分法による熱方程式シミュレーション
25 public HeatCanvas c1;
26
27 public void init() {
28 //画面のレイアウト、レイアウトマネージャーの設定
29 setLayout(new BorderLayout());
30
31 //Northパネルの設定
32 Panel pn = new Panel();
33 pn.setLayout(new GridLayout(3,2));
34
35 //ボタン、テキストフィールドの準備
36 String s = "lambda (should be <= 1/2)";
37 labelLambda = new Label(s, Label.LEFT);
38 pn.add(labelLambda);
39
40 inputLambda = new TextField("" + lambda,10);
41 pn.add(inputLambda);
42
43 labelN = new Label("N", Label.LEFT);
44 pn.add(labelN);
45
46 inputN = new TextField("" + N,10);
47 pn.add(inputN);
48
49 labelTmax = new Label("Tmax", Label.LEFT);
50 pn.add(labelTmax);
51
52 inputTmax = new TextField("" + Tmax,10);
53 pn.add(inputTmax);
54
55 inputLambda.addActionListener(this);
56 inputN.addActionListener(this);
57 inputTmax.addActionListener(this);
58
59 add(pn, "North");
60
61 //Centerパネルの設定
62 Panel pc = new Panel();
63 c1 = new HeatCanvas();
64 c1.setSize(400,400);
65 c1.compute(lambda, N, Tmax);
66 pc.add(c1);
67 add(pc,"Center");
68
69 //Eastパネルの設定
70 Panel pe = new Panel();
71 startB = new Button("Restart");
72 pe.add(startB);
73 add(pe,"East");
74 startB.addActionListener(this);
75 }
76
77 //イベント処理(ボタン)
78 public void actionPerformed(ActionEvent e) {
79 if (e.getSource() == startB) {
80 String str1 = inputLambda.getText().trim();
81 String str2 = inputN.getText().trim();
82 String str3 = inputTmax.getText().trim();
83 lambda = Double.valueOf(str1).doubleValue();
84 N = Integer.parseInt(str2);
85 Tmax = Double.valueOf(str3).doubleValue();
86 c1.compute(lambda, N, Tmax);
87 }
88 }
89 }
90
91 // HeatCanvas.java
92
93 class HeatCanvas extends Canvas {
94
95 static final boolean DEBUG = false; // true;
96 private static final String message = "1D Heat Equation";
97 // 問題に取って基本的なパラメーター
98 // N: 区間の分割数
99 // Tmax: 最終時刻
100 // lambda: λ=τ/h^2
101 private int N;
102 private double Tmax, lambda;
103 // 座標系の変換のためのパラメーター
104 private int CanvasX = 400, CanvasY = 400;
105 private double ratiox, ratioy, X0, Y0;
106 //
107 private HeatCanvas c1;
108
109 // コンストラクター
110 public HeatCanvas() {
111 super();
112 space(-0.1, -0.1, 1.1, 1.1);
113 }
114 public HeatCanvas(int cx, int cy) {
115 super();
116 CanvasX = cx; CanvasY = cy;
117 space(-0.1, -0.1, 1.1, 1.1);
118 }
119
120 public void compute(double lambda, int N, double Tmax) {
121 this.lambda = lambda;
122 this.N = N;
123 this.Tmax = Tmax;
124 repaint();
125 }
126
127 // 初期条件
128 private double f(double x) {
129 if (x <= 0.5)
130 return x;
131 else
132 return 1.0 - x;
133 }
134 // 座標変換の準備
135 private void space(double x0, double y0, double x1, double y1) {
136 X0 = x0; Y0 = y0;
137 ratiox = CanvasX / (x1 - x0);
138 ratioy = CanvasY / (y1 - y0);
139 }
140 // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系)
141 private int wx(double x) {
142 return (int)(ratiox * (x - X0));
143 }
144 // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系)
145 private int wy(double y) {
146 return CanvasY - (int)(ratioy * (y - Y0));
147 }
148 // x[], y[] の内容をグラフにする
149 private void drawGaph(Graphics g, double x[], double u[]) {
150 for (int i= 0; i < N; i++)
151 g.drawLine(wx(x[i]), wy(u[i]), wx(x[i + 1]), wy(u[i + 1]));
152 }
153
154 public void paint(Graphics g) {
155
156 double h = 1.0 / N;
157 double tau = lambda * h * h;
158 double dt = 0.01;
159 int Jmax = (int) (Tmax / tau);
160 int skip = (int) (dt / tau + 0.5);
161 double [] u, unext, x;
162
163 // ベクトルを確保する
164 x = new double[N+1];
165 u = new double[N+1];
166 unext = new double[N+1];
167 for (int i = 0; i <= N; i++)
168 x[i] = i * h;
169
170 // これはあんまり意味がない。
171 g.setColor(Color.pink);
172 g.fillOval(10, 10, 330, 60);
173 g.setColor(Color.red);
174 for (int i=0; i<4;i++)
175 g.drawOval(10-i, 10-i, 330+2*i, 60+2*i);
176
177 // タイトルを表示する
178 g.setColor(Color.black);
179 g.setFont(new Font("Helvetica", Font.BOLD, 24));
180 g.drawString(message, 40, 50);
181
182 // 初期値を計算する
183 for (int i = 0; i <= N; i++)
184 u[i] = f(i * h);
185
186 // 初期値のグラフを描く
187 drawGaph(g, x, u);
188
189 // 時間に関するループ
190 for (int j = 1; j <= Jmax; j++) {
191 int i;
192 for (i = 1; i < N; i++)
193 unext[i] = (1 - 2 * lambda) * u[i]
194 + lambda * (u[i-1] + u[i+1]);
195 for (i = 1; i < N; i++)
196 u[i] = unext[i];
197 u[0] = 0; u[N] = 0;
198
199 if (DEBUG)
200 for (i = 0; i <= N; i++)
201 System.out.println("u[" + i + "]=" + u[i]);
202 // 適当な間隔 (dt=0.01) でグラフを描く
203 if (j % skip == 0)
204 drawGaph(g, x, u);
205 }
206 }
207 }