動点Pはわからなくても質点Pくらいはシミュレーションしたい(シンプレクティック数値積分法)
はじめに
数値解析学を学ぶと微分方程式の解法として一番簡単なオイラー法が紹介されると思います。そして実際に実装してみると確かに解くことはできるけど、誤差がどんどん大きくなるところに目を瞑っていられなくなります。そこで調和振動子などの物理系に対し、安定して長期間のシミュレーションが行えるシンプレクティック数値積分法を紹介したいと思います。
問題提起
よく古典力学の教科書とかで見る次の状況を考えましょう。
上図のバネをびよーんって伸ばしてから離して振動する質点Pの
ここで
と書けます。そうすると運動方程式は
となります。この
はじめ質点Pは
次に微分方程式の解き方は知らないけど微分は知っているAさんが現れました。Aさんは非常に近い二点間の変化率が微分だと理解していたので、先ほどの式を
この式から次の漸化式が導けます。
位置
横軸が時間、縦軸が位置です。また
運動量
運動量も同様に解析解から遠のいていきます。
この誤差をどう解決するか?
先ほどオイラー法による誤差として、解析解から遠のいていくところを確認しました。そしてより時間が経てばこの誤差は大きなものになっていきます。そこでエネルギー保存の観点からどうすれば解決できるか考えたいと思います。
エネルギーとハミルトニアン
調和振動子におけるエネルギーは、質点の運動エネルギー
は保存します。これを少し一般化しましょう。
を定義しましょう。この
と書けます。このハミルトニアンに
ステップを一つ進めるごとにエネルギーが
オイラー法を工夫する
これらの議論からステップを進めてもエネルギーが蓄積しない手法を考えましょう。結論から言うと次のように改良されます。
オイラー法と何が違うかというと
と見事にエネルギーが保存されます[2]。とりあえずこの改良を通じてオイラー法と比較しつつシミュレーションした結果を示します。まずは位置
位置
次に運動量
運動量
正しく解析解に沿ってシミュレーションできていることが確認できました!この数値解析法をシンプレクティック数値積分法と言います。
ここで注意しなければいけないのは「じゃあシンプレクティック数値積分法はエネルギーを保存するシミュレーション方法なのね!」と理解してしまうことです。あくまでも調和振動子本来のハミルトニアンは
時間ごとのエネルギーの大きさ
ピンク実線: 解析解、青破線: オイラー法、緑破線:シンプレクティック数値積分法
上の図を見るとステップを進めるとオイラー法はエネルギーが大きくなり続けるのに対して、シンプレクティック数値積分法では一定の範囲で振動し続けます。これは
シンプレクティック数値積分法の原理
ではシンプレクティック数値積分法どんな原理で成り立っているのでしょうか?ここでは解析力学という高校や大学1年生で学ぶ古典力学を数学的に体系化したものを使って説明します。
ハミルトンの正準方程式と正準変換
解析力学で学ぶ物体の運動を表す式には、ラグランジュの運動方程式とハミルトンの正準方程式があります。どちらもとても重要なのですがハミルトンの正準方程式を紹介します。ハミルトンの正準方程式は次のように定義されます。
と書けます。この
と同様にハミルトンの正準方程式が成り立つことを要求します[4][5]。この正準方程式を成り立たせる変換は正準変換と呼ばれます。正準変換が成り立つためには
を満たす必要があります。
より、
と
"シンプレクティック"って?
シンプレクティック数値積分法の"シンプレクティック"の由来を説明しようと思います。
相空間
これまで位置と運動量を変数として話を展開させていきました。というのも解析力学(統計力学や量子力学もそうですが)位置と運動量で論じることが多いです。従って位置と運動量からなる空間を作って置けば、その空間内で物理状態を示すことができるようになります。この空間を相空間と呼びます。
相空間の次元は対象とする系によって変わるのですが、例えば今回のような調和振動子の場合一つの質点しか考えないので位置
相空間の図:
ここで調和振動子が常に
であるので、これを相空間に反映させると、
相空間:ピンク実線: 解析解
半径
の軌跡です。質点は必ずこの円に沿って運動するので、時間が経過してもエネルギーが増え続ける(減り続ける)ことはないことが明らかになります。次にシンプレクティック数値積分法で導かれる結果を相空間に反映してみましょう。
相空間:ピンク実線: 解析解、緑破線:シンプレクティック数値積分法
しっかりと円に沿って描かれていることが分かりますね。分かりづらいですがこの時
相空間:ピンク実線: 解析解、青破線: オイラー法、緑破線:シンプレクティック数値積分法
オイラー法の場合は円や楕円で閉じることなく外へ発散していくため、エネルギーが保存しないことが分かります。
シンプレクティックと正準変換
唐突ですが
これを行列の形式に書き直すと、
となります。ここで次のヤコビ行列が定義できます。
そしてヤコビ行列の行列式(ヤコビアン)は面積
の関係を与えます。ここであれ?と思うのがヤコビアンがまさしくポアッソン括弧の定義になっているということです。つまり相空間上で正準変換が成り立つというのは
まとめ
最後にこれまでの話をまとめましょう。
- シンプレクティック数値積分法はシンプレクティック変換を原理とする数値解析法である。
- シンプレクティック数値積分法は厳密にエネルギーを保存しない。
ということです。最後に紹介したシンプレクティックという概念は微分形式を使うと正準変換にしろ面積保存にしろ次のようにたった一つの式で記述することができます。
この
Appendix
参考文献
十河 清(著)「解析力学」株式会社日本評論社
ソースコード
オイラー法とシンプレクティック数値積分法を比較できるシミュレーションコードです。Pythonで書いています。使用する場合はnumpyとmatplotlibもインストールして下さい。使用する場合は自己責任でお願いします。
シミュレーションコード
import numpy as np
import matplotlib.pyplot as plt
x_0 = 1 # 初期位置
epsilon = 0.05 # ステップ幅
t_max = 20 # シミュレーション期間
def hamiltonian(x, p):
return (x**2 + p**2) / 2
t = np.arange(0, t_max, epsilon)
N = len(t)
# a:解析解、e:オイラー法、s:シンプレクティック数値積分法
# 初期化処理
x_a = x_0*np.cos(t)
p_a = -x_0*np.sin(t)
x_e = np.zeros(N)
p_e = np.zeros(N)
x_s = np.zeros(N)
p_s = np.zeros(N)
# 初期値設定
x_e[0] = x_0
x_s[0] = x_0
# エネルギー初期化処理
E_a = hamiltonian(x_a, p_a)
E_e = np.full(N, hamiltonian(x_e[0], p_e[0]))
E_s = np.full(N, hamiltonian(x_s[0], p_s[0]))
for n in range(N-1):
# オイラー法
x_e[n+1] = x_e[n] + epsilon*p_e[n]
p_e[n+1] = -epsilon*x_e[n] + p_e[n]
E_e[n+1] = hamiltonian(x_e[n+1], p_e[n+1])
# シンプレクティック数値積分法
x_s[n+1] = x_s[n] + epsilon*p_s[n]
p_s[n+1] = -epsilon*x_s[n+1] + p_s[n]
E_s[n+1] = hamiltonian(x_s[n+1], p_s[n+1])
analytical_color = [1,0.3,0.3]
euler_color = [0,0,1]
symplectic_color = [0,1,0]
# 位置xシミュレーション結果
plt.subplots(figsize=(10, 4))
plt.xlabel('time (sec)')
plt.ylabel('x')
plt.plot(t, x_a, color=analytical_color, linewidth=6, label='analytical')
plt.plot(t, x_e, color=euler_color, linewidth=3,linestyle="dashed", label='euler')
plt.plot(t, x_s, color=symplectic_color, linewidth=3, linestyle="dashed" ,label='symplectic')
plt.legend()
plt.grid()
# 運動量pシミュレーション結果
plt.subplots(figsize=(10, 4))
plt.xlabel('time (sec)')
plt.ylabel('p')
plt.plot(t, p_a, color=analytical_color, linewidth=6, label='analytical')
plt.plot(t, p_e, color=euler_color, linewidth=3,linestyle="dashed", label='euler')
plt.plot(t, p_s, color=symplectic_color, linewidth=3, linestyle="dashed" ,label='symplectic')
plt.legend()
plt.grid()
# エネルギー評価
ymax = np.ceil(np.amax(E_e))
plt.subplots(figsize=(8, 5))
plt.xlabel('time (sec)')
plt.ylabel(r'Energy $\frac{1}{2}(x^{2} + p^{2})$')
plt.plot(t, E_a, color=analytical_color, linewidth=6, label='analytical')
plt.plot(t, E_e, color=euler_color, linewidth=3,linestyle="dashed", label='euler')
plt.plot(t, E_s, color=symplectic_color, linewidth=3, linestyle="dashed" ,label='symplectic')
plt.ylim(0, ymax)
plt.legend()
plt.grid()
# 相空間
plt.subplots(figsize=(5, 5))
plt.plot(x_a, p_a, color=analytical_color, linewidth=6, label='analytical')
plt.plot(x_e, p_e, color=euler_color, linewidth=3,linestyle="dashed", label='euler')
plt.plot(x_s, p_s, color=symplectic_color, linewidth=3, linestyle="dashed" ,label='symplectic')
plt.xlabel('x')
plt.ylabel('p')
plt.xlim(-1.6, 1.6)
plt.ylim(-1.6, 1.6)
plt.legend()
plt.grid()
plt.show()
-
物理的に考慮すべき対象のこと。単に系と呼ぶことにします。 ↩︎
-
この式変形は少し骨が折れます。めんどくさい人はmathematicaやsympyなどをつかって楽するのもありです。 ↩︎
-
正確には一般化座標、一般化運動量と言います。 ↩︎
-
物理には最小作用の原理というものがあります。簡単に説明すると力学系(時間変化する物理系)は無駄な運動をしないという物理のルールで、例えばボールを落とした時、突然曲がったりすることなく必ず一直線で落下します。ハミルトンの正準方程式が最小作用の原理から導かれることを踏まえると、正準方程式が成り立たないならば最小作用の原理が満たされないということになります。 ↩︎
-
もっと一般化するとこの正準方程式は
ではなくH とか別のハミルトニアンで記述するのが良いでしょう。このハミルトニアンH' は母関数というもの使って探します。 ↩︎H'
Discussion