//===========================ファイル名Scatter=========== //4次のルンゲ-クッタ法を用いたクーロン散乱Ver.1.1 //        作成:加藤徳善 1997.3.27 //==================================================== import java.applet.*; import java.awt.*; //import java.lang.*; public class Scatter extends Applet implements Runnable { Graphics g_this; Image offScreen; Graphics offGraphics; Dimension dim1; Thread th; Color col=new Color(90,85,110); //ルンゲ-クッタ関連配列 double x[][]=new double[10][3]; double v[][]=new double[10][3]; double dx[][][]=new double[10][10][3]; double nrm[][][]=new double[10][10][3]; double pow[][]=new double[10][10]; double ik[][][]=new double[4][10][3]; double im[][][]=new double[4][10][3]; double r[][]=new double[10][10]; double aa[][]=new double[10][10]; double al[][]=new double[10][10]; int ap[][]=new int[10][10]; double b[]=new double[10]; double c[]=new double[10]; double d[][]=new double[10][3]; double x0[][]=new double[10][3]; double mass[]=new double[10]; double x1[][]=new double[10][3]; double v1[][]=new double[10][3]; double v2[][]=new double[10][3]; double vn[][]=new double[10][3]; double w[][]=new double[10][3]; double w1[][]=new double[10][3]; double va[]=new double[10]; double f[][]=new double[10][3]; double coef[]={1.,2.,2.,1.}; //力のスイッチ boolean swa=true;//距離に関係する力(万有引力,弾性力など) boolean swb=true;//速さに比例する力(粘性抵抗) boolean swc=true;//速さの二乗に比例する力(慣性抵抗) boolean swd=true;//一定の力(地上の重力など) int dim;//次元-1 int n;//物体数-1 double dt;//時間間隔 //double time;//時間 int FONTSIZE1=12; double oldx[][]=new double[10][3]; Point pt0=new Point(280,190); int drawmode=0;//スレッドによる 1:描画 2:描画停止 int drawinitflag=1;// 1:画面初期化 0:何もしない int stepflag=0;//1:ストロボモード 0:何もしない int DD=10; int oldDD=10; int dd=4; int setDDflag=1; //int iniskip=0; double vv=20.; double rx,ry; public void init(){ int i,k; Font f=new Font("TimesRoman",Font.PLAIN,FONTSIZE1);//フォント作 setFont(f);//フォント選択 setLayout(new BorderLayout());//ボーダーレイアウトに Panel p = new Panel();//パネル作製 p.setLayout(new GridLayout(1,4)); p.add(new Scrollbar(Scrollbar.HORIZONTAL,20,0,5,50)); p.add(new Button("Start"));//部品をパネルに貼り付け p.add(new Button("Reset")); Checkbox cb = new Checkbox("Strobo"); p.add(cb); add("South", p);//パネル貼り付け initrk();//ルンゲ-クッタ関係の初期化 //calc(); resize(500,400); setBackground(col); dim1=this.size();//現在の表示画面の大きさを調べる if (offScreen == null) { offScreen = createImage(dim1.width,dim1.height); offGraphics = offScreen.getGraphics(); } // repaint(); } //加速度の計算 public void acce(){ int i,j,k; double fw,fw1,RR; if(swa||swc){ for(i=0;i<=n;i++){ if(swa){ for(j=0;j<=i;j++){ fw=0.; for(k=0;k<=dim;k++){ if(i!=j){ dx[i][j][k]=x1[i][k]-x1[j][k]; dx[j][i][k]=x1[j][k]-x1[i][k]; } else dx[i][j][k]=x1[i][k]-x0[j][k]; fw+=dx[i][j][k]*dx[i][j][k]; } r[i][j]=Math.sqrt(fw); for(k=0;k<=dim;k++){ if(r[i][j]!=0) nrm[i][j][k]=dx[i][j][k]/r[i][j]; else nrm[i][j][0]=1.; if(i!=j) nrm[j][i][k]=-nrm[i][j][k]; } r[i][j]-=al[i][j]; r[j][i]=r[i][j]; if(ap[i][j]==0) pow[i][j]=1.; if(ap[i][j]==-2) pow[i][j]=1./r[i][j]/r[i][j]; if(ap[i][j]==1) pow[i][j]=r[i][j]; if(ap[i][j]==-12){ RR=(double)DD/2.; if(r[i][j]>RR) pow[i][j]=1./r[i][j]/r[i][j]; else{ pow[i][j]=r[i][j]/RR/RR/RR; } } pow[i][j]=pow[i][j]*aa[i][j]; pow[j][i]=pow[i][j]; } } fw1=0; for(k=0;k<=dim;k++) fw1+=v1[i][k]*v1[i][k]; va[i]=Math.sqrt(fw1); for(k=0;k<=dim;k++){ if(va[i]!=0.) vn[i][k]=v1[i][k]/va[i]; } } } for(i=0;i<=n;i++){ for(k=0;k<=dim;k++) f[i][k]=0.;//clear } for(i=0;i<=n;i++){ for(k=0;k<=dim;k++){ if(swa){ for(j=0;j<=n;j++) f[i][k]+=pow[i][j]*nrm[i][j][k]; } if(swb) f[i][k]+=b[i]*v1[i][k]; if(swc) f[i][k]+=c[i]*va[i]*va[i]*vn[i][k]; if(swd) f[i][k]+=d[i][k]; f[i][k]/=mass[i]; } } } //ルンゲ-クッタ法 public void rk(){ int i,j,k,l; for(i=0;i<=n;i++){ for(k=0;k<=dim;k++){ x1[i][k]=x[i][k]; v1[i][k]=v[i][k]; w[i][k]=0.; w1[i][k]=0.; } } acce(); for(l=0;l<=2;l++){ for(i=0;i<=n;i++){ for(k=0;k<=dim;k++){ ik[l][i][k]=dt*v1[i][k]; im[l][i][k]=dt*f[i][k]; x1[i][k]=x[i][k]+ik[l][i][k]/coef[l+1]; v1[i][k]=v[i][k]+im[l][i][k]/coef[l+1]; w[i][k]+=ik[l][i][k]*coef[l]; w1[i][k]+=im[l][i][k]*coef[l]; } } acce(); } for(i=0;i<=n;i++){ for(k=0;k<=dim;k++){ ik[l][i][k]=dt*v1[i][k]; im[l][i][k]=dt*f[i][k]; x1[i][k]=x[i][k]+(w[i][k]+ik[3][i][k])/6.; v1[i][k]=v[i][k]+(w1[i][k]+im[3][i][k])/6.; } } for(i=0;i<=n;i++){ for(k=0;k<=dim;k++){ x[i][k]=x1[i][k]; v[i][k]=v1[i][k]; } } } public void initrk(){ int i,j; dim=1;//次元-1 n=9;//物体数-1 dt=.3;//計算での時間間隔 for(i=0;i<=n;i++){ x[i][0]=-270 ; x[i][1]=8+16*i; oldx[i][0]=x[i][0] ; oldx[i][1]=x[i][1]; x0[i][0]=0. ; x0[i][1]=0. ; //if(iniskip!=1){ v[i][0]=vv; v[i][1]=0. ; //} mass[i]=1.; } //---力の設定------- swa=true; for(i=0;i<=n;i++){ for(j=0;j<=n;j++){ if(i==j){ aa[j][i]=10000; ap[j][i]=-12;//電荷が一様に半径DD広がっている場合の力の場 } else{ aa[j][i]=0; ap[j][i]=0; } al[j][i]=0; } } swb=false;//速さに比例する力(粘性抵抗) swc=false;//速さの二乗に比例する抵抗(慣性抵抗) swd=false;//一定の力(重力など) } public void calc(){ rk();//ルンゲ-クッタ呼び出し if((x[0][0]>230)||(x[0][0]<-300)||(x[0][1]>250)||(x[0][1]<-220)){ drawmode = 2; } } public boolean mouseDrag(Event e,int xd,int yd){ rx=(xd-pt0.x); ry=(yd-pt0.y); DD=(int)Math.sqrt(rx*rx+ry*ry)*2; if(DD<5) DD=5; if(DD>200) DD=200; repaint(); return true; } public boolean handleEvent(Event e) { int i; if(e.target instanceof Button) { if ("Start".equals(e.arg)) { drawinitflag=1; //stepflag=0; //drawmode = 2; //calc(); drawmode = 1; initrk(); } if ("Reset".equals(e.arg)) { drawinitflag=1; //stepflag=0; drawmode = 2; //iniskip=1; initrk(); repaint(); return true; } return true; } if (e.target instanceof Checkbox){ Checkbox cb = (Checkbox)e.target; //if (((Boolean)e.arg).booleanValue()) { if (cb.getState()) stepflag = 1; else stepflag= 0; return true; //} //return true; } if (e.target instanceof Scrollbar){ Scrollbar sb = (Scrollbar)e.target; vv=(double)sb.getValue(); repaint(); for(i=0;i<=n;i++) v[i][0]=vv; return true; } return super.handleEvent(e); } public void start(){ if(th==null){ th=new Thread(this); th.start(); } } public void run(){ while(th!=null){ if(drawmode==1){ try{ calc(); repaint(); th.sleep(80); }catch(InterruptedException e){ ; } } } } public void stop(){ if(th !=null){ th.stop(); th=null; } } public void update(Graphics g){ paint(g);//updateを無効にし、paintで置き換え } public void paint(Graphics g){ int i,j,k; if(drawinitflag==1){ offGraphics.setColor(getBackground()); offGraphics.fillRect(0,0,dim1.width,dim1.height); //背景色で画面全体を塗りつぶす(初期化) drawinitflag=0; } if(stepflag!=1){ offGraphics.setColor(getBackground()); offGraphics.fillRect(0,0,dim1.width,dim1.height); // for(i=0;i<=n;i++){ // offGraphics.setColor(getBackground()); // offGraphics.fillOval(pt0.x+(int)(oldx[i][0]-dd*.5),pt0.y+(int)(oldx[i][1]-dd*.5),dd,dd); // offGraphics.fillOval(pt0.x+(int)(oldx[i][0]-dd*.5),pt0.y-(int)(oldx[i][1]+dd*.5),dd,dd); // } } if((x[9][0]<-220)||(stepflag==0)){ offGraphics.setColor(getBackground()); offGraphics.fillOval(pt0.x-(int)(oldDD*.5),pt0.y-(int)(oldDD*.5),(int)oldDD,(int)oldDD); oldDD=DD; offGraphics.setColor(new Color(253-DD/2,200-DD/2,40)); offGraphics.fillOval(pt0.x-(int)(DD*.5),pt0.y-(int)(DD*.5),(int)DD,(int)DD);//核 } for(i=0;i<=n;i++){ offGraphics.setColor(Color.green); oldx[i][0]=x[i][0]; oldx[i][1]=x[i][1]; offGraphics.fillOval(pt0.x+(int)(oldx[i][0]-dd*.5),pt0.y+(int)(oldx[i][1]-dd*.5),dd,dd); offGraphics.fillOval(pt0.x+(int)(oldx[i][0]-dd*.5),pt0.y-(int)(oldx[i][1]+dd*.5),dd,dd); } offGraphics.setColor(getBackground()); offGraphics.fillRect(0,352,80,385); offGraphics.setColor(Color.orange); offGraphics.drawString("Radius="+DD/2,4,360); offGraphics.setColor(Color.green); offGraphics.drawString("Speed ="+(int)vv,4,370); g.drawImage(offScreen,0,0,this); } }