/* * Heat1dyou.java --- Heat1d_e_4.java を JDK 1.2 に合わせて変更したもの * 2001年1月18日 * * コンパイル: javac Heat1dyou.java * 実行: appletviewer Heat1dyou.java * * */ import java.applet.*; import java.awt.*; import java.awt.event.*; public class Heat1dyou extends Applet implements ActionListener { public int N = 20; public double lambda = 0.5; public double Tmax = 0.5; // ユーザーとのインターフェイス public Label labelLambda, labelN, labelTmax; public TextField inputLambda, inputN, inputTmax; public Button startB; // 差分法による熱方程式シミュレーション public HeatCanvas c1; public void init() { //画面のレイアウト、レイアウトマネージャーの設定 setLayout(new BorderLayout()); //Northパネルの設定 Panel pn = new Panel(); pn.setLayout(new GridLayout(3,2)); //ボタン、テキストフィールドの準備 String s = "lambda (should be <= 1/2)"; labelLambda = new Label(s, Label.LEFT); pn.add(labelLambda); inputLambda = new TextField("" + lambda,10); pn.add(inputLambda); labelN = new Label("N", Label.LEFT); pn.add(labelN); inputN = new TextField("" + N,10); pn.add(inputN); labelTmax = new Label("Tmax", Label.LEFT); pn.add(labelTmax); inputTmax = new TextField("" + Tmax,10); pn.add(inputTmax); inputLambda.addActionListener(this); inputN.addActionListener(this); inputTmax.addActionListener(this); add(pn, "North"); //Centerパネルの設定 Panel pc = new Panel(); c1 = new HeatCanvas(); c1.setSize(400,400); c1.compute(lambda, N, Tmax); pc.add(c1); add(pc,"Center"); //Eastパネルの設定 Panel pe = new Panel(); startB = new Button("Restart"); pe.add(startB); add(pe,"East"); startB.addActionListener(this); } //イベント処理(ボタン) public void actionPerformed(ActionEvent e) { if (e.getSource() == startB) { String str1 = inputLambda.getText().trim(); String str2 = inputN.getText().trim(); String str3 = inputTmax.getText().trim(); lambda = Double.valueOf(str1).doubleValue(); N = Integer.parseInt(str2); Tmax = Double.valueOf(str3).doubleValue(); c1.compute(lambda, N, Tmax); } } } // HeatCanvas.java class HeatCanvas extends Canvas { static final boolean DEBUG = false; // true; private static final String message = "1D Heat Equation"; // 問題に取って基本的なパラメーター // N: 区間の分割数 // Tmax: 最終時刻 // lambda: λ=τ/h^2 private int N; private double Tmax, lambda; // 座標系の変換のためのパラメーター private int CanvasX = 400, CanvasY = 400; private double ratiox, ratioy, X0, Y0; // private HeatCanvas c1; // コンストラクター public HeatCanvas() { super(); space(-0.1, -0.1, 1.1, 1.1); } public HeatCanvas(int cx, int cy) { super(); CanvasX = cx; CanvasY = cy; space(-0.1, -0.1, 1.1, 1.1); } public void compute(double lambda, int N, double Tmax) { this.lambda = lambda; this.N = N; this.Tmax = Tmax; repaint(); } // 初期条件 private double f(double x) { if (x <= 0.5) return x; else return 1.0 - x; } // 座標変換の準備 private void space(double x0, double y0, double x1, double y1) { X0 = x0; Y0 = y0; ratiox = CanvasX / (x1 - x0); ratioy = CanvasY / (y1 - y0); } // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) private int wx(double x) { return (int)(ratiox * (x - X0)); } // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) private int wy(double y) { return CanvasY - (int)(ratioy * (y - Y0)); } // x[], y[] の内容をグラフにする private void drawGaph(Graphics g, double x[], double u[]) { for (int i= 0; i < N; i++) g.drawLine(wx(x[i]), wy(u[i]), wx(x[i + 1]), wy(u[i + 1])); } public void paint(Graphics g) { double h = 1.0 / N; double tau = lambda * h * h; double dt = 0.01; int Jmax = (int) (Tmax / tau); int skip = (int) (dt / tau + 0.5); double [] u, unext, x; // ベクトルを確保する x = new double[N+1]; u = new double[N+1]; unext = new double[N+1]; for (int i = 0; i <= N; i++) x[i] = i * h; // これはあんまり意味がない。 g.setColor(Color.pink); g.fillOval(10, 10, 330, 60); g.setColor(Color.red); for (int i=0; i<4;i++) g.drawOval(10-i, 10-i, 330+2*i, 60+2*i); // タイトルを表示する g.setColor(Color.black); g.setFont(new Font("Helvetica", Font.BOLD, 24)); g.drawString(message, 40, 50); // 初期値を計算する for (int i = 0; i <= N; i++) u[i] = f(i * h); // 初期値のグラフを描く drawGaph(g, x, u); // 時間に関するループ for (int j = 1; j <= Jmax; j++) { int i; for (i = 1; i < N; i++) unext[i] = (1 - 2 * lambda) * u[i] + lambda * (u[i-1] + u[i+1]); for (i = 1; i < N; i++) u[i] = unext[i]; u[0] = 0; u[N] = 0; if (DEBUG) for (i = 0; i <= N; i++) System.out.println("u[" + i + "]=" + u[i]); // 適当な間隔 (dt=0.01) でグラフを描く if (j % skip == 0) drawGaph(g, x, u); } } }