//
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Anteisei extends Applet implements ActionListener {
//スクリーン
private Image img;
private Graphics gra;
//ユーザーとのインターフェイス
private double eps,q;
private Label la1,la2;
private TextField tf1,tf2;
private Button bt1,bt2;
private TextArea ta;
//安定性解析の関数のためのパラメーター
private double f;
private double u,v;
private double a,b,c,d;
private double tr_A,det_A,D;//線形化して出来た行列
//二分法のためのパラメーター
final private double EPS =1e-15;//打ち切り誤差
final private int limit=50;//打ち切り回数
private double low,mid,high;
private int k=1;
private double lastf,sol;
//座標系の変換パラメーター
private double ratiox,ratioy,X0,Y0;
private int WX = 500, WY =500;
//描画範囲
private double x_max = 10;
private double x_min = -1;
private double x_margin = (x_max-x_min)/10;
private double y_max = 120;
private double y_min = -20;
private double y_margin = (y_max-y_min)/10;
private boolean IsIn(double x, double y) {
return (x_min <= x && x <= x_max && y_min <= y && y <= y_max);
}
// 座標変換の準備
private void space(double x0, double y0, double x1, double y1) {
X0 = x0; Y0 = y0;
ratiox = WX / (x1 - x0);
ratioy = WY / (y1 - y0);
}
// ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系)
private int wx(double x) {
return (int)(ratiox * (x - X0));
}
// ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系)
private int wy(double y) {
return WY - (int)(ratioy * (y - Y0));
}
//tf からの数値読み取り
private void ReadFields(){
eps = Double.valueOf(tf1.getText()).doubleValue();
q = Double.valueOf(tf2.getText()).doubleValue();
}
//2乗の計算
private double sqr(double x){
return(x * x);
}
//判別式の関数 g1
private double g1(double f){
u = (1-f-q+Math.sqrt(sqr(f+q-1)+4*q*(1+f)))/2;
v = u;
a = (-2*u*u*u + (1 - 4 * q)*u*u + 2*q*(1-q)*u
+ q*(q-2*f*v))/(eps*sqr(q+u));
b = f*(q-u)/(eps*(q+u));
c = 1;
d = -1;
tr_A = a + d;
det_A = a*d - b*c;
D = sqr(tr_A) - 4*det_A;
return D;
}
//固有方程式の根の関数 g2
private double g2(double f){
u = (1-f-q+Math.sqrt(sqr(f+q-1)+4*q*(1+f)))/2;
v = u;
a = (-2*u*u*u + (1 - 4 * q)*u*u + 2*q*(1-q)*u
+ q*(q-2*f*v))/(eps*sqr(q+u));
b = f*(q-u)/(eps*(q+u));
c = 1;
d = -1;
tr_A = a + d;
det_A = a*d - b*c;
D = sqr(tr_A) - 4*det_A;
if(D>0)
return (tr_A+Math.sqrt(D))/2;
else
return (tr_A)/2;
}
public void init() {
//tf la bt のレイアウト
setLayout(null);
add(la1 = new Label("εの値:"));
la1.setBounds (510,20,90,30);
add(la2 = new Label("qの値:"));
la2.setBounds (510,70,90,30);
add(tf1 = new TextField(""+1e-2));
tf1.setBounds (610,20,80,30);
add(tf2 = new TextField(""+8e-4));
tf2.setBounds (610,70,80,30);
//Startボタン
add(bt1 = new Button("Start"));
bt1.addActionListener(this);
bt1.setBounds (610,140,80,30);
//Clearボタン
add(bt2 = new Button("Clear"));
bt2.addActionListener(this);
bt2.setBounds (610,190,80,30);
//TextArea
add(ta =new TextArea(5,7));
ta.setBounds (510,280,180,220);
//スクリーンの確保
img=createImage(WX,WY);
gra=img.getGraphics();
gra.setColor(new Color(230,230,230));
gra.fillRect(0,0,WX,WY);
//座標軸とます目
space(x_min-x_margin, y_min-y_margin
, x_max+x_margin, y_max+y_margin);
gra.setColor(Color.gray);
for (double i=x_min; i<=x_max ; i=i+1){
gra.drawLine(wx(i),wy(y_min),wx(i),wy(y_max));
}
for (double i=y_min; i<=y_max; i=i+10){
gra.drawLine(wx(x_min),wy(i),wx(x_max),wy(i));
}
gra.setColor(Color.black);
gra.drawLine(wx(x_min), wy(0.0), wx(x_max), wy(0.0));
gra.drawLine(wx(0.0), wy(y_min), wx(0.0), wy(y_max));
gra.drawString("0",wx(0.0),wy(0.0));
gra.drawString("5",wx(5),wy(0.0));
gra.drawString("10",wx(10),wy(0.0));
gra.setColor(Color.blue);
gra.drawString("判別式のグラフ",120,20);
gra.drawString("5000",wx(-1),wy(50));
gra.drawString("10000",wx(-1),wy(100));
gra.setColor(Color.red);
gra.drawString("固有値の実部の最大値のグラフ",220,20);
gra.drawString("50",wx(0),wy(50));
gra.drawString("100",wx(0),wy(100));
}
public void paint(Graphics g){
update(g);
}
public void update(Graphics g){
g.drawImage(img,0,0,this);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == bt1) {
//一つ前の点と今の点
double fx1,fx2;
double fy1,fy2,fy3,fy4;
//点を結ぶときの幅
double delta1 = 5e-5;
space(x_min-x_margin, y_min-y_margin
, x_max+x_margin, y_max+y_margin);
ReadFields();
for(f=0; f<=x_max; f=f+delta1) {
fx1=f-delta1;
fx2=f;
fy1=g1(f-delta1)/100;
fy2=g1(f)/100;
fy3 = g2(f-delta1);
fy4 = g2(f);
//判別式のグラフの表示
gra.setColor(Color.blue);
if(IsIn(fx1,fy1) && IsIn(fx2,fy2)) {
gra.drawLine(wx(fx1),wy(fy1),wx(fx2),wy(fy2));
fx1=fx2;fy1=fy2;
}
//固有方程式の根のグラフの表示
gra.setColor(Color.red);
if(IsIn(fx1,fy3) && IsIn(fx2,fy4)) {
gra.drawLine(wx(fx1),wy(fy3),wx(fx2),wy(fy4));
fx1=fx2;fy3=fy4;
}
}
repaint();
double delta2 = 5e-2;
//二分法による解の表示
for(double x=0; x<=x_max; x=x+delta2){
low=x;
high=x+delta2;
if( g1(low)*g1(high)<=0){
for (k=1;k<=limit;k++){
mid=(low+high)/2;
if(g1(low)*g1(mid)<0)
high=mid;
else
low=mid;
if(g1(mid)==0 || Math.abs(high-low)limit){
ta.setText(ta.getText()+"収束しない");
}
}
}
if ( g2(low)*g2(high)<=0){
for (k=1;k<=limit;k++){
mid=(low+high)/2;
if(g2(low)*g2(mid)<0)
high=mid;
else
low=mid;
if(g2(mid)==0 || Math.abs(high-low)limit){
ta.setText(ta.getText()+"収束しない");
}
}
}
}
ta.setText(ta.getText()+sol+"