物理学の具体的な計算にPython(SymPy)を使って、物理学もPython(SymPy)も同時に学んでしまいましょう。今回はPython(SymPy)を使ってシュレーディンガー方程式を解いてみたいと思います。シュレーディンガー方程式は量子力学の基礎方程式です。この記事で取り上げるのは1次元調和振動子の問題です。
Python(SymPy)のごく基本的な使い方については以下の記事を参照してください:
正準交換関係
まず前提として、量子力学では古典的な物理量にはエルミート演算子が対応します。とくに質点の位置座標と運動量に対応する演算子、位置演算子 と運動量演算子 は次の正準交換関係をみたします。
ここに角括弧は交換子で、2つの演算子 と に対して
と定義します。
1次元空間の波動関数 に対しては位置演算子 と運動量演算子 は
と作用するものと定義します。
実際、このように演算子の作用を定義すると、 の任意のなめらかな関数 に対して
となり、 の関数の空間の上で確かに交換関係が成り立っていることがわかります。
この計算自体は難しいものではないですが、これはPython(SymPy)では以下のようにして計算できます。
%reset -f import sympy as sp sp.var('h', positive = True) # プランク定数 sp.var('x') from sympy.core.function import Function f = Function('f')(x) # 座標 x に依存する任意関数 def X(f): return x*f # 位置演算子 x の関数への作用 def P(f): return -sp.I*h*sp.diff(f,x) # 運動量演算子 p の関数への作用 sp.expand(X(P(f))-P(X(f))) # 交換子
1次元調和振動子のハミルトニアン
で与えられます。ここで は質点の質量、 はバネ定数です。いま
とすればハミルトニアンは
と書き直されます。ハミルトン形式による古典的な運動の定式化では、物理量 に対する時間発展は
で与えられます。ここで波括弧はポアソン括弧で
によって定義されます。
したがって、とくに質点の位置座標 と運動量 の時間発展は
ですが、2つの式から運動量 を消去すれば
さて、ハミルトニアンが物理量の二乗の和になっていることから、因数分解して
と書き表してみましょう。
生成・消滅演算子
ハミルトニアンを上のように因数分解した形から、生成・消滅演算子をそれぞれ
と定義してみます。するとこれらの交換関係が
と計算されます。実際、Pythonで計算すると
sp.var('m, w', positive = True) def a(f): return sp.sqrt(m*w/(2*h))*X(f)+sp.I/sp.sqrt(2*h*m*w)*P(f) def ad(f): return sp.sqrt(m*w/(2*h))*X(f)-sp.I/sp.sqrt(2*h*m*w)*P(f) sp.cancel(a(ad(f))-ad(a(f)))
より、確かに上の交換関係が成り立っています。
エネルギー固有値
いまハミルトニアンは演算子になっているので、各項の積の順序に注意しながら書き直すと
がわかります。
となる非自明な関数として決めます。
より、その固有値は であることがわかります。
またこの波動関数 から、ハミルトニアンの固有状態が以下のようにして構成できます:
ここで は規格化のための定数で、規格化条件
によって決めます。このように構成した関数 に対してハミルトニアンを作用させると
となります。最後の等式では の性質を使いました。
さて、交換子 ですが、これは
と計算されます。 の場合はすでに計算しました。
ある自然数 まで上記の公式が成り立っていると仮定します。
ここで公式
を使うと の場合に対して
となり、公式の成立が示されます。
ハミルトニアンの への作用に話を戻すと
となって、 がハミルトニアンの固有状態で、
その固有値が であることがわかります。
基底状態の波動関数の具体形
記号を簡単化するために、以下のようにして変数を無次元化します。
すると消滅演算子は
と表されます。したがって基底状態の波動関数 に対する方程式は
となります。これは1階線形微分方程式なので簡単に解がわかります:
もとの変数 で書き表すと
です。規格化条件から、位相因子 の不定性を除いて
と決まります。実際
sp.var('theta', real = True) psi0 = sp.exp(sp.I*theta)*((m*w)/(sp.pi*h))**(1/4)*sp.exp(-m*w*x**2/(2*h)) sp.integrate(psi0*sp.conjugate(psi0), (x, -sp.oo, sp.oo) )
より、たしかに規格化されていることがわかります。
励起状態の波動関数の具体形
基底状態に次々と生成演算子を作用させて励起状態が得られるので、いくつか具体的に見てみましょう。以下、物理的でない規格化の位相因子は1とします。
del(psi0) psi0 = ((m*w)/(sp.pi*h))**(sp.Rational(1/4))*sp.exp(-m*w*x**2/(2*h)) psi0
sp.var('C1', positive = True) psi1 = C1*ad(psi0) c1 = sp.solve(sp.integrate(psi1*sp.conjugate(psi1), (x, -sp.oo, sp.oo))-1, C1) psi1 = psi1.subs(C1, c1[0]) psi1
sp.var('C2', positive = True) psi2 = C2*ad(psi1) c2 = sp.solve(sp.integrate(psi2*sp.conjugate(psi2), (x, -sp.oo, sp.oo))-1, C2) psi2 = sp.simplify(psi2.subs(C2, c2[0])) psi2
sp.var('C3', positive = True) psi3 = C3*ad(psi2) c3 = sp.solve(sp.integrate(psi3*sp.conjugate(psi3), (x, -sp.oo, sp.oo))-1, C3) psi3 = sp.simplify(psi3.subs(C3, c3[0])) psi3
より
などと求まります。あるいは無次元の変数 を使えば
と書き表せます。ここで特徴的な多項式が現れることに注意します。
じつは、1次元調和振動子のエネルギー固有関数は、以下で説明するエルミート多項式(Hermite polynoimal) を使って
と表すことができます。
エルミート多項式
エルミート多項式 は、Rodriguesの公式によって
として求まる多項式です。具体的にいくつかあげると、
SymPyの組み込み関数からエルミート多項式を呼び出して
sp.init_printing() x=sp.var('x') sp.hermite(0,x)
sp.hermite(1,x)
sp.hermite(2,x)
sp.hermite(3,x)
あるいは、具体的にRodoriguesの公式を使って
def H(n): return sp.expand((-1)**n*sp.exp(x**2)*sp.diff(sp.exp(-x**2), x, n)) H(0)
H(1)
H(2)
H(3)
より(もちろん、どちらも同じ多項式を与えますが)
といった多項式です。エルミート多項式には次の公式があります:
この公式はRodriguesの公式を微分することで容易に示すことができます。
公式を使うと(規格化した変数で表した)生成演算子の作用のもとで
が成り立つことがわかります。これにより、規格化定数を除いて が求まります。
また、規格化定数もエルミート多項式の性質
から決めることができます。この性質は具体的に
def D(m,n): return sp.integrate(H(m)*H(n)*sp.exp(-x**2), ( x,-sp.oo, sp.oo) ) sp.Matrix([ [D(0,0),D(0,1),D(0,2),D(0,3)], [D(1,0),D(1,1),D(1,2),D(1,3)], [D(2,0),D(2,1),D(2,2),D(2,3)], [D(3,0),D(3,1),D(3,2),D(3,3)]])
によって確かめることができます。
波動関数の図示
エネルギー固有状関数をいくつか図示してみましょう:
Psi0 = psi0.subs(h,1).subs(m,1).subs(w,1) Psi1 = psi1.subs(h,1).subs(m,1).subs(w,1) Psi2 = psi2.subs(h,1).subs(m,1).subs(w,1) Psi3 = psi3.subs(h,1).subs(m,1).subs(w,1) sp.plot(Psi0, Psi1, Psi2, Psi3,(x, -5, 5))
として出力されたのが次の図です:
ただし、、、 はいずれも1としています(見づらかったら、それぞれの励起状態を個別に図示してみてください)。励起状態のエネルギー固有値が上がるごとに節(ゼロ点)の個数が増えていく様子がわかります。
また、粒子の存在確率分布(波動関数の絶対値2乗) も図示してみると
sp.plot(Psi0**2, Psi1**2, Psi2**2, Psi3**2,(x, -5, 5))
により
と図示されます。
さいごに粒子の存在確率分布から、粒子が存在する位置の期待値と分散を求めてみます:まず期待値
sp.integrate( x*Psi0**2, (x, -sp.oo, sp.oo))
sp.integrate( x*Psi1**2, (x, -sp.oo, sp.oo))
sp.integrate( x*Psi2**2, (x, -sp.oo, sp.oo))
sp.integrate( x*Psi3**2, (x, -sp.oo, sp.oo))
次に分散
sp.integrate( x**2*Psi0**2, (x, -sp.oo, sp.oo))
sp.integrate( x**2*Psi1**2, (x, -sp.oo, sp.oo))
sp.integrate( x**2*Psi2**2, (x, -sp.oo, sp.oo))
sp.integrate( x**2*Psi3**2, (x, -sp.oo, sp.oo))
より、いずれの状態に対しても、粒子が存在する位置の期待値 はゼロとなります。このことは、波動関数の分布が原点に対して左右均等であることからもわかります。しかし、分散はエネルギー固有値が大きくなるにつれて大きくなることがわかります。このことは、波動関数の分布が高いエネルギーの状態になるにつれて、原点からより離れた点にも分布のヤマをもつことからわかります。以上、これらの計算結果は、図示した確率分布の様子と直感的にも整合します。