Shadow Academy トップ > 我流・物理数学 > 非線形物理学(カオス理論) > ローレンツ方程式のシミュレーション


ローレンツ方程式のシミュレーション

繰り返しの回数:n (n×Δt 秒後に終了)
時間の刻み幅:Δt [s] (n×Δt 秒後に終了)
σ 気体の性質に依存するパラメータ
ex). σ=10
r 温度差を表わすコントロール・パラメータ
ex). r=28
b 水平方向の波長に依存するパラメータ
ex). b=8/3 ≈ 2.66666666666666667
初期値:x0  
初期値:y0  
初期値:z0  
データ出力形式:

データ出力欄:



解説

ローレンツ方程式は、連立微分方程式:

dx  

=-σxσy
dt  
   
dy  

=-xzrxy
dt  
   
dz  

xybz
dt  
で表される。従って、ローレンツ方程式を
数値計算によってシミュレーションする場合、
上述の式を4次のルンゲ・クッタ法(RK4)で解けばよい。




スクリプトプログラムの使い方

各テキストフィールドに数値を入力後、「計算する」ボタンを押すと、
新しいページテキストエリアにデータが生成されるので、そこで、「全て選択」して、
テキストエディタを起動して、ファイルにコピーペーストし、名前を付けて保存する。
ここでは、Cドライブ以下のtempフォルダに「lorenz.dat」という名前で保存する。
これをグラフ作成ツール「wgnuplot」を用いて、グラフ化するには、
wgnuplotを起動して、以下のコマンドを入力する。

x-y-z座標系で出力(三次元空間)

set terminal png
set output 'c:\temp\lorenz.png'
splot 'c:\temp\lorenz.dat' using 2:3:4 with lines
exit




ソースコード(新版)

lorenz.html

<form><!-- getElementByIdを使用する為、name属性を指定しない -->
<table border="1" style="margin-left:auto;margin-right:auto;text-align:center;">
  <tr>
    <td style="text-align:right;">繰り返しの回数:<i>n</i>=</td>
    <td style="text-align:left;"><input type="text" id="n" value="1000"></td>
    <td style="text-align:left;">(<i>n</i>&times;<i>&Delta;t</i> 秒後に終了)</td>
  </tr>
  <tr>
    <td style="text-align:right;">時間の刻み幅:<i>&Delta;t</i>=</td>
    <td style="text-align:left;"><input type="text" id="dt" value="0.01">[s]</td>
    <td style="text-align:left;">(<i>n</i>&times;<i>&Delta;t</i> 秒後に終了)</td>
  </tr>
  <tr>
    <td style="text-align:right;"><i>&sigma;</i>=</td>
    <td style="text-align:left;"><input type="text" id="sigma" value="10"></td>
    <td style="text-align:left;">気体の性質に依存するパラメータ<br>
ex). <i>&sigma;</i>=10</td>
  </tr>
  <tr>
    <td style="text-align:right;"><i>r</i>=</td>
    <td style="text-align:left;"><input type="text" id="r" value="28"></td>
    <td style="text-align:left;">温度差を表わすコントロール・パラメータ<br>
ex). <i>r</i>=28</td></td>
  </tr>
  <tr>
    <td style="text-align:right;"><i>b</i>=</td>
    <td style="text-align:left;"><input type="text" id="b" value="2.66666666666666667"></td>
    <td style="text-align:left;">水平方向の波長に依存するパラメータ<br>
ex). <i>b</i>=8/3 &asymp; 2.66666666666666667</td></td>
  </tr>
  <tr>
    <td style="text-align:right;">初期値:<i>x</i><sub>0</sub>=</td>
    <td style="text-align:left;"><input type="text" id="x0"></td>
    <td style="text-align:left;"> </td>
  </tr>
  <tr>
    <td style="text-align:right;">初期値:<i>y</i><sub>0</sub>=</td>
    <td style="text-align:left;"><input type="text" id="y0"></td>
    <td style="text-align:left;"> </td>
  </tr>
  <tr>
    <td style="text-align:right;">初期値:<i>z</i><sub>0</sub>=</td>
    <td style="text-align:left;"><input type="text" id="z0"></td>
    <td style="text-align:left;"> </td>
  </tr>
  <tr>
    <td style="text-align:right;">データ出力形式:</td>
    <td style="text-align:left;" colspan="2">
      <label for="csv"><input type="radio" name="separator" id="csv">CSV(半角コンマ区切り)</label><br>
      <label for="ssv"><input type="radio" name="separator" id="ssv" checked>SSV(半角スペース区切り)</label><br>
      <input type="button" value="計算する" onClick="lorenzcalc()" style="width:200px;height:40px;"></td>
  </tr>
  <tr>
    <td style="text-align:right;">データ出力欄:</td>
    <td style="text-align:left;" colspan="2"><textarea id="data" cols="50" rows="20"></textarea></td>
  </tr>
</table>
</form>

lorenz.js

var lorenzcalc = function(){
  var n = parseInt(document.getElementById("n").value); // 繰り返しの回数(n*dt秒後に終了)
  var dt = parseFloat(document.getElementById("dt").value); // 時間の刻み幅(n*dt秒後に終了)
  var sigma = parseFloat(document.getElementById("sigma").value); // 気体の性質に依存するパラメータ
  var r = parseFloat(document.getElementById("r").value); // 温度差を表わすコントロール・パラメータ
  var b = parseFloat(document.getElementById("b").value); // 水平方向の波長に依存するパラメータ
  var x0 = parseFloat(document.getElementById("x0").value); // xの初期値
  var y0 = parseFloat(document.getElementById("y0").value); // yの初期値
  var z0 = parseFloat(document.getElementById("z0").value); // zの初期値

  var t,x,y,z,i; // 時刻t、変数x,y,z及び、ループ変数を宣言
  var j1,j2,j3,j4,k1,k2,k3,k4,l1,l2,l3,l4; // 4次のルンゲクッタ法で使用する変数を宣言

  var data = ""; // データを表す変数を空の初期値と共に宣言
  var separator = ""; // データの区切り文字

  // データの区切り文字の種類を選択して取得
  if(document.getElementById("csv").checked == true){ separator=","; } // 半角コンマ区切り
  if(document.getElementById("ssv").checked == true){ separator=" "; } // 半角スペース区切り

  t = 0; // 時刻を初期化
  x = x0; // xにその初期条件を代入
  y = y0; // yにその初期条件を代入
  z = z0; // zにその初期条件を代入

  data = t + separator + Math.round(1000*x)/1000
           + separator + Math.round(1000*y)/1000
           + separator + Math.round(1000*z)/1000;
  // 時刻t=0での、xとyとz(小数点以下第3位未満を四捨五入)
  // をデータを表す変数dataに代入して、データを上書きする。

  for(i=0;i<n;++i){
    j1=dt*(-sigma*x+sigma*y);
    k1=dt*(-x*z+r*x-y);
    l1=dt*(x*y-b*z);
  // (x+j1/2),(y+k1/2),(z+l1/2)
    j2=dt*(-sigma*(x+j1/2)+sigma*(y+k1/2));
    k2=dt*(-(x+j1/2)*(z+l1/2)+r*(x+j1/2)-(y+k1/2));
    l2=dt*((x+j1/2)*(y+k1/2)-b*(z+l1/2));
  // (x+j2/2),(y+k2/2),(z+l2/2)
    j3=dt*(-sigma*(x+j2/2)+sigma*(y+k2/2));
    k3=dt*(-(x+j2/2)*(z+l2/2)+r*(x+j2/2)-(y+k2/2));
    l3=dt*((x+j2/2)*(y+k2/2)-b*(z+l2/2));
  // (x+j3),(y+k3),(z+l3)
    j4=dt*(-sigma*(x+j3)+sigma*(y+k3));
    k4=dt*(-(x+j3)*(z+l3)+r*(x+j3)-(y+k3));
    l4=dt*((x+j3)*(y+k3)-b*(z+l3));

    t=Math.round(1000*(t+dt))/1000;
    x=x+(j1+2*j2+2*j3+j4)/6;
    y=y+(k1+2*k2+2*k3+k4)/6;
    z=z+(l1+2*l2+2*l3+l4)/6;

    data += "\n" + t 
           + separator + Math.round(1000*x)/1000
           + separator + Math.round(1000*y)/1000
           + separator + Math.round(1000*z)/1000;
    // 時刻tでの、xとyとz(小数点以下第3位未満を四捨五入)
    // をデータを表す変数dataに代入して、データを上書きする。
  }

  document.getElementById("data").value = data; // テキストエリアへ出力する
};



ソースコード(旧版)

lorenz.html

<form name="lorenzform">
<table border="5" style="margin-left:auto;margin-right:auto;text-align:center;">
<tr>
<td style="text-align:right;">繰り返しの回数:<i>n</i>=</td>
<td style="text-align:left;"><input type="text" name="n"></td>
<td style="text-align:left;">(<i>n</i>×<i>Δt</i> 秒後に終了)</td>
</tr>
<tr>
<td style="text-align:right;">時間の刻み幅:<i>Δt</i>=</td>
<td style="text-align:left;"><input type="text" name="dt">[s]</td>
<td style="text-align:left;">(<i>n</i>×<i>Δt</i> 秒後に終了)</td>
</tr>
<tr>
<td style="text-align:right;"><i>σ</i>=</td>
<td style="text-align:left;"><input type="text" name="sigma"></td>
<td style="text-align:left;">気体の性質に依存するパラメータ
<br>ex). <i>σ</i>=10</td>
</tr>
<tr>
<td style="text-align:right;"><i>r</i>=</td>
<td style="text-align:left;"><input type="text" name="r"></td>
<td style="text-align:left;">温度差を表わすコントロール・パラメータ
<br>ex). <i>r</i>=28</td></td>
</tr>
<tr>
<td style="text-align:right;"><i>b</i>=</td>
<td style="text-align:left;"><input type="text" name="b"></td>
<td style="text-align:left;">水平方向の波長に依存するパラメータ
<br>ex). <i>b</i>=8/3 ≈ 2.66666666666666667</td></td>
</tr>
<tr>
<td style="text-align:right;">初期値:<i>x</i><sub>0</sub>=</td>
<td style="text-align:left;"><input type="text" name="x0"></td>
<td style="text-align:left;"> </td>
</tr>
<tr>
<td style="text-align:right;">初期値:<i>y</i><sub>0</sub>=</td>
<td style="text-align:left;"><input type="text" name="y0"></td>
<td style="text-align:left;"> </td>
</tr>
<tr>
<td style="text-align:right;">初期値:<i>z</i><sub>0</sub>=</td>
<td style="text-align:left;"><input type="text" name="z0"></td>
<td style="text-align:left;"> </td>
</tr>
</table>
<input type="button" value="計算する" onClick="lorenzcalc()">
</form>

lorenz.js

function lorenzcalc(){
  var n=parseInt(document.lorenzform.n.value);
  /* 繰り返しの回数(n*dt秒後に終了) */
  var dt=parseFloat(document.lorenzform.dt.value);
  /* 時間の刻み幅(n*dt秒後に終了) */
  var sigma=parseFloat(document.lorenzform.sigma.value);
  /* 気体の性質に依存するパラメータ */
  var r=parseFloat(document.lorenzform.r.value);
  /* 温度差を表わすコントロール・パラメータ */
  var b=parseFloat(document.lorenzform.b.value);
  /* 水平方向の波長に依存するパラメータ */
  var x0=parseFloat(document.lorenzform.x0.value);
  /* xの初期値 */
  var y0=parseFloat(document.lorenzform.y0.value);
  /* yの初期値 */
  var z0=parseFloat(document.lorenzform.z0.value);
  /* zの初期値 */

  var t,x,y,z,i;
  /* 時刻t、変数x,y,z及び、ループ変数を宣言 */
  var j1,j2,j3,j4,k1,k2,k3,k4,l1,l2,l3,l4;
  /* 4次のルンゲクッタ法で使用する変数を宣言 */

  t=0; /* 時刻を初期化 */
  x=x0; /* xにその初期条件を代入 */
  y=y0; /* yにその初期条件を代入 */
  z=z0; /* zにその初期条件を代入 */

  document.writeln("<html>");
  document.writeln("<head>");
  document.writeln("<title>ローレンツ・モデル</title>");
  document.writeln("</head>");
  document.writeln("<body bgcolor='#ffd700' text='#000000'>");

  document.writeln("<pre>");
  document.writeln(t," ",Math.round(1000*x)/1000,
    " ",Math.round(1000*y)/1000," ",Math.round(1000*z)/1000);
  /* 時刻t=0での、xとyとzを出力(小数点以下第3位未満を四捨五入) */
  for(i=0;i<n;++i){
    j1=dt*(-sigma*x+sigma*y);
    k1=dt*(-x*z+r*x-y);
    l1=dt*(x*y-b*z);
  // (x+j1/2),(y+k1/2),(z+l1/2)
    j2=dt*(-sigma*(x+j1/2)+sigma*(y+k1/2));
    k2=dt*(-(x+j1/2)*(z+l1/2)+r*(x+j1/2)-(y+k1/2));
    l2=dt*((x+j1/2)*(y+k1/2)-b*(z+l1/2));
  // (x+j2/2),(y+k2/2),(z+l2/2)
    j3=dt*(-sigma*(x+j2/2)+sigma*(y+k2/2));
    k3=dt*(-(x+j2/2)*(z+l2/2)+r*(x+j2/2)-(y+k2/2));
    l3=dt*((x+j2/2)*(y+k2/2)-b*(z+l2/2));
  // (x+j3),(y+k3),(z+l3)
    j4=dt*(-sigma*(x+j3)+sigma*(y+k3));
    k4=dt*(-(x+j3)*(z+l3)+r*(x+j3)-(y+k3));
    l4=dt*((x+j3)*(y+k3)-b*(z+l3));

    t=Math.round(1000*(t+dt))/1000;
    x=x+(j1+2*j2+2*j3+j4)/6;
    y=y+(k1+2*k2+2*k3+k4)/6;
    z=z+(l1+2*l2+2*l3+l4)/6;
    document.writeln(t," ",Math.round(1000*x)/1000,
      " ",Math.round(1000*y)/1000," ",Math.round(1000*z)/1000);
    /* 時刻tでの、xとyとzを出力(小数点以下第3位未満を四捨五入) */
  }
  document.writeln("</pre>");

  document.writeln("</body>");
  document.write("</html>");
}



参考文献

  1. 「Javaによる複雑系入門」(工学社、2008年)
  2. 「非線形物理学―カオス・ソリトン・パターン―」(裳華房、2010年)



Shadow Academy トップへ戻る

inserted by FC2 system