今回は Python(SymPy)を活用する具体例として、4次元時空のSchwarzschild(シュワルツシルト)解がアインシュタイン方程式の解になっていることをPython(SymPy)を使って確認してみたいと思います。シュワルツシルト解は静的で球対称な場合のアインシュタイン方程式の真空解として求められます。
一般に、アインシュタイン方程式は時空の計量テンソルを偏微分してクリストッフェル記号、それを複雑に組み合わせた曲率テンソルを計算しないといけません。今回計算するような静的で球対称な場合には、仮定する変数依存性が少ないので手計算でもなんとかなるかもしれませんが、計算過程で求めなければいけない量が多く、そういった面倒な計算にはコンピュータを使ってラクをするのが良いでしょう。PythonのSymPyは、そのようなことを可能にする数式処理ライブラリです。
次の記事の中ではPython(SymPy)の使い方のごく初歩的な部分を紹介しています:
本記事では、4次元時空のSchwarzschild解をPython(SymPy)を使って求めます。おまけとして、5次元の場合についても同様に計算してみます。(考察する対象を容易に拡張できるのがコンピュータを使うメリットです)6次元の場合についても答えだけ載せておきました。
4次元時空のリーマン幾何
以下、同じ項のなかで同じ文字の添字が上下に現れた場合、その添字については0から3までの和をとるものと約束します。(この約束をアインシュタインの規約といいます)
座標系の設定
4次元時空の座標系(いま3次元空間部分については極座標系をとることにします)
はSymPyで
import sympy as sp sp.var('t, r, theta, phi') xi = sp.Matrix([ [t],[r],[theta],[phi] ])
と入力します。後で他の次元に拡張しやすくするために、時空の次元を文字Dとしておきましょう。
D = len(xi)
計量テンソルの設定
上で導入した座標系 に付随する時空の計量テンソル は不変距離 に対して
として定義されます。計量テンソルは2階対称テンソル場なので、しばしば対称行列で次のように表されます。
いま計量テンソルとして次の形を仮定してみましょう。
すなわち、計量の非自明な成分は以下の通りです。
ただし は動径 の関数で、その関数形は後でアインシュタイン方程式から決めます。これらをSymPyで入力するには
f = sp.Function('f')(r) g = sp.Matrix([ [-f, 0, 0, 0], [0, 1/f, 0, 0], [0, 0, r**2, 0], [0, 0, 0, r**2*sp.sin(theta)**2] ])
とします。 として導入される上付き添字の は
ginv = g.inv()
で計算されます。
Christoffel記号
天下りですが、Levi-Civita接続を定めるChristoffel記号は以下の量です。
以下の曲率なども同様ですが、ここでは幾何学的な量の詳細については割愛します。理解したいという方は、以下のような一般相対論の教科書を参照してください。
Christoffel記号はSymPyでは次のようにして計算できます。
def Gamma(k,i,j): gm = 0 for n in range(D): gm = gm + sp.Rational(1,2)*ginv[k,n]*(g[n,i].diff(xi[j])\ +g[n,j].diff(xi[i])-g[i,j].diff(xi[n])) return gm
例えば
Gamma(1,3,3)
として
などと求まります。
Riemannの曲率テンソル
リーマン曲率テンソルは以下の量です。
def R(i,j,k,l): rm = Gamma(i,l,j).diff(xi[k]) - Gamma(i,k,j).diff(xi[l]) for n in range(D): rm = rm + Gamma(n,l,j)*Gamma(i,k,n) - Gamma(n,k,j)*Gamma(i,l,n) return rm
例えば
R(1,3,1,3)
として
などと求まります。
Ricciテンソル
リッチテンソルは
です。
def Ricc(j,k): ric = 0 for n in range(D): ric = ric + R(n,j,n,k) return ric
これは2階テンソルなので、行列表記してみましょう:
RiccMat = sp.Matrix([ [Ricc(0,0), Ricc(0,1), Ricc(0,2), Ricc(0,3)], [Ricc(1,0), Ricc(1,1), Ricc(1,2), Ricc(1,3)], [Ricc(2,0), Ricc(2,1), Ricc(2,2), Ricc(2,3)], [Ricc(3,0), Ricc(3,1), Ricc(3,2), Ricc(3,3)] ]) sp.simplify(RiccMat)
より
と計算されます。
4次元Schwarzschild解
5次元Schwarzschild解
5次元の場合に、時間 と4次元空間の極座標 からなる座標系で
として4次元の場合と同様の計算をします:
%reset import sympy as sp sp.var('t, r, theta, phi, psi') xi = sp.Matrix([ [t],[r],[theta],[phi],[psi] ]) D = len(xi) f = sp.Function('f')(r) g = sp.Matrix([ [-f, 0, 0, 0, 0], [0, 1/f, 0, 0, 0], [0, 0, r**2, 0, 0], [0, 0, 0, r**2*sp.sin(theta)**2, 0], [0, 0, 0, 0, r**2*sp.sin(theta)**2*sp.sin(phi)**2] ]) ginv = g.inv() def Gamma(k,i,j): gm = 0 for n in range(D): gm = gm + sp.Rational(1,2)*ginv[k,n]*(g[n,i].diff(xi[j])\ +g[n,j].diff(xi[i])-g[i,j].diff(xi[n])) return gm def R(i,j,k,l): rm = Gamma(i,l,j).diff(xi[k]) - Gamma(i,k,j).diff(xi[l]) for n in range(D): rm = rm + Gamma(n,l,j)*Gamma(i,k,n) - Gamma(n,k,j)*Gamma(i,l,n) return rm def Ricc(j,k): ric = 0 for n in range(D): ric = ric + R(n,j,n,k) return ric RiccMat = sp.Matrix([ [Ricc(0,0), Ricc(0,1), Ricc(0,2), Ricc(0,3), Ricc(0,4)], [Ricc(1,0), Ricc(1,1), Ricc(1,2), Ricc(1,3), Ricc(1,4)], [Ricc(2,0), Ricc(2,1), Ricc(2,2), Ricc(2,3), Ricc(2,4)], [Ricc(3,0), Ricc(3,1), Ricc(3,2), Ricc(3,3), Ricc(3,4)], [Ricc(4,0), Ricc(4,1), Ricc(4,2), Ricc(4,3), Ricc(4,4)] ]) R = sp.simplify((ginv*RiccMat).trace()) GMat = sp.simplify(RiccMat - sp.Rational(1,2)*g*R) GMat
より、Einsteinテンソル
がわかります。Einstein方程式 より
が関数 に課されます。この場合についても、第2式は第1式から自動的に満たされて
という に関する1階常微分方程式を得ます。その解は を定数として
であることがわかります。この関数形によって定まる時空の計量
は5次元Schwarzschild解とよばれます。
6次元Schwarzschild解
6次元の場合に、時間 と5次元空間の極座標 からなる座標系で
の仮定のもとで上と同様の解析をしてみると、Einstein方程式から に対して条件
が課されます。その解は
で与えられます。対応する計量が6次元Schwarzschild解です。
一般の n 次元の場合は、これまでの結果から予想できるでしょうか。
いかがだったでしょうか。今回は数式処理ライブラリSymPyを使って煩雑な計算をコンピュータに任せてみました。一度正しいコードを書いてしまえば、容易に他の次元に拡張できてしまう点などもコンピュータを使う利点です。アインシュタイン方程式の厳密解には、Schwarzschild解以外にもいくつか知られているものがあります。それらについてもコードを拡張して確認してみても良いかもしれません。
ちなみに、宇宙項を加えたドジッター解、電場を加えたライスナー・ノルドシュトロム解を以下の記事で扱っています。あわせて読んでみて下さい。
キーワード:Python、SymPy、Riemann幾何、一般相対論、Schwarzschild解