![]()
![]()
| 1,常備分方程式 | Euler法 Runge−Kutta法 レポート |
| 2,偏微分方程式 (13KB) | Euler法 Crank-Nicholson法 レポート |
| 3,確率論 (13KB) | モンテカルロ法 レポート |
物理的なことをシミュレートするのには、今までのように常微分方程式や偏微分方程式を
使って決定論的に解く方法がありました。しかし、物理現象が決定論的には決まらず
確率的になってしまう場合は、シミュレーションも確率論的に解きます。
![]()
確率論的なシミュレーションをするにはモンテカルロ法がもっとも効果的です。
モンテカルロ法では物理学的な量を、乱数を用いて計算します。
計算方法は次のようにします。
まず、初期状態を作成します。
乱数を用いてランダムに1つの粒子を選び、これに物理的な変化を加える。
(”変化”とは、位置を移動させる,スピンを変えるなど)
「2」の試行で変化したポテンシャルエネルギーをΔUとすると
次のような判定をします。
※βは(KB T)-1です。kBはボルツマン定数です。
この判定で「真」になったものは「2」の試行を採用します。
(「2」の試行が正しいと判定された)
しかし、「偽」と判定されたものは「2」の試行の結果を採用せず元のままにします。
以上の2と3を繰り返します。
この試行を多く行うことによって実際の物理現象に近づきます。
![]()
物質内には原子があり、スピンを持っています。
このスピンが同じ方向を向くと強磁性体になります。
しかし、常温ではこのスピンの向きはランダムで常磁性体になります。
(これは、温度が絶対0度ではなく、エントロピーが増加しようとするためです。)
これが絶対0度になると、スピンによるポテンシャルエネルギーを小さくするために
スピンの向きをそろえようとします。今回のレポートは
温度Tを変化させて、そのときのスピンの状態をシミュレーションします。
m=狽妬j sij=1,−1 これは、電子のスピンです。 今回は簡単のため−1と1しかないものとします。 このm2と温度Tとの関係をグラフにせよ
このシミュレーションプログラムの基本構造は次のようになります。
import java.applet.*;
import java.awt.*;
public class j30c1 extends Applet implements Runnable
{
boolean move = false;
double sumis,deltau,ktoj=0.01;
int [][]is = new int[130][130];
private Thread m_j30c1 = null;
void setis()
{
int i,j;
for (i=1; i<=128; i++){
for (j=1; j<=128; j++){
if (Math.random()>0.5){
is[i][j]=1;
}else{is[i][j]=-1;}
}}
for (i=1; i<=128; i++){
is[0][i]=is[128][i];
is[129][i]=is[1][i];
is[i][0]=is[i][128];
is[i][129]=is[i][1];
}
is[0][0]=is[128][128]; is[0][129]=is[128][1];
is[129][0]=is[1][128]; is[129][129]=is[1][1];
}
public void init()
{
resize(500, 400);
setBackground(Color.white);
setis();
}
public void paint(Graphics g)
{
int i,j,redcount=0;
String str;
g.setColor(Color.green);g.fillRect(3,3,384,384);
g.setColor(Color.red);
for (i=1; i<=128; i++){
for(j=1; j<=128; j++)
if (is[i][j]==1){g.fillRect(i*3,j*3,3,3);redcount++;}
}
g.setColor(Color.black);
g.drawString("mm:"+Math.pow((2*redcount-128*128),2),400,350);
}
public void start()
{
if (m_j30c1 == null)
{
m_j30c1 = new Thread(this);
m_j30c1.start();
}
}
public void stop()
{
if (m_j30c1 != null)
{
m_j30c1.stop();
m_j30c1 = null;
}
}
public void run()
{
int indx,indy,i;
while (true)
{
try{Thread.sleep(1000);}
catch (InterruptedException e){stop();}
if (move){
for (i=0; i<128*128; i++){
indx=(int)(Math.random()*128)+1;
indy=(int)(Math.random()*128)+1;
sumis=(double)( is[indx+1][indy]+is[indx-1][indy]
+is[indx][indy+1]+is[indx][indy-1]);
deltau=(2.0/ktoj)*(double)is[indx][indy]*sumis;
if (deltau<0){is[indx][indy]*=-1;}
else if (Math.random()<=Math.exp(-deltau))
{is[indx][indy]*=-1;}
if (indy==1){is[129][indy]=is[1][indy];}
if (indy==128){is[0][indy]=is[128][indy];}
if (indx==1){is[indx][129]=is[indx][1];}
if (indx==128){is[indx][0]=is[indx][128];}
}
repaint();
}
}
}
public boolean mouseDown(Event evt, int x, int y)
{
move=!move;
if (evt.clickCount==2){
move=true;
setis();
}
if (move){m_j30c1.resume();}else{m_j30c1.suspend();}
return true;
}
}
以上のプログラムを元にして制作したのが下のものです。
左側の画面をClickするごとに動作/停止します。
doubleClickで初期状態に戻ります。
さらに「kToJ」の「0.5倍」「1」「2倍」をclickすることで
現在の数値を変更したり、1にプリセットできます。