今回は、Python(SymPy)を勉強に活用する実践例として、Python(SymPy)で極座標のラプラシアンを求める方法を紹介したいと思います。2次元と3次元のラプラシアンは電磁気学や量子力学などではおなじみです。物理学の教科書などで扱う問題の多くは回転対称・球対称な場合なので、極座標に移って問題を議論するのはごく自然なことです。
しかし、デカルト座標で表せばあんなに簡単な形に書けるラプラシアンが、ひとたび極座標へ座標変換するやいなやその見た目を大きく変えます。極座標での表式を導出するのにもちょっと手間がかかって、あっちのサインとこっちのコサインがキャンセルしたり組み合わさったり、すったもんだの末に授業が1コマ終わってたりします。
このような、単純だけれども面倒な計算にこそコンピュータを使ってラクをしたいものです。PythonのSymPyは、そのようなことを可能にする数式処理ライブラリです。
次の記事の中ではPython(SymPy)の使い方のごく初歩的な部分を紹介しています:
本記事では、2次元、3次元のラプラシアンの極座標表示をPython(SymPy)を使って求めます。おまけとして、4次元の極座標で表したラプラシアンも求めてみます。5次元、6次元の場合についても結果だけ載せておきます。
(考察する対象を容易に拡張できるのもコンピュータを使うメリットです)
2次元ラプラシアン
まずはウォーミングアップとして2次元のラプラシアン
を2次元極座標 で表してみましょう。 と の関係は
または
で与えられます。さて、微分の連鎖律から
です。ここで行列 を
によって導入しました。この行列は
import sympy as sp sp.var('x, y') r = sp.sqrt(x**2+y**2) theta = sp.atan(y/x) r2 = sp.simplify(sp.Matrix([ [sp.diff(r,x),sp.diff(theta,x)], [sp.diff(r,y),sp.diff(theta,y)] ])) del(r, theta) sp.var('r, theta', positive = True) R2 = sp.trigsimp(r2.subs(x, r*sp.cos(theta)).subs(y, r*sp.sin(theta))) R2
とPythonで入力することにより
と計算されます。ここで を勝手な関数として
とすると
によってラプラシアンを求めることができます:
from sympy.core.function import Function f = Function('f')(r,theta) T2 = R2*sp.Matrix([[sp.diff(f,r)],[sp.diff(f,theta)]]) i = sp.symbols('i',integer=True) sp.trigsimp(sp.summation( R2[i,0]*sp.diff(T2[i,0],r)+R2[i,1]*sp.diff(T2[i,0],theta), (i,0,1)))
に入力して上の数式をPythonで計算させることにより
がわかります。
3次元ラプラシアン
次に3次元のラプラシアン
を3次元極座標 で表してみましょう。 と の関係は
または
で与えられます。ここで2次元のときと同様に を勝手な関数として
を導入します。すると
によってラプラシアンを求めることができます。まず変数を初期化しておきます
%reset
2次元の場合と同様に
import sympy as sp sp.var('x, y, z') r = sp.sqrt(x**2+y**2+z**2) theta = sp.atan(sp.sqrt(x**2+y**2)/z) phi = sp.atan(y/x) r3 = sp.simplify(sp.Matrix([ [sp.diff(r,x),sp.diff(theta,x),sp.diff(phi,x)], [sp.diff(r,y),sp.diff(theta,y),sp.diff(phi,y)], [sp.diff(r,z),sp.diff(theta,z),sp.diff(phi,z)] ])) del(r, theta, phi) sp.var('r, theta, phi', nonnegative = True) R3 = sp.expand(sp.trigsimp( r3.subs(x, r*sp.sin(theta)*sp.cos(phi)). subs(y, r*sp.sin(theta)*sp.sin(phi)).subs(z, r*sp.cos(theta)) ), trig = True).subs(sp.Abs(sp.sin(theta)), sp.sin(theta)) T3 = R3*sp.Matrix([ [sp.diff(r,x),sp.diff(theta,x),sp.diff(phi,x)], [sp.diff(r,y),sp.diff(theta,y),sp.diff(phi,y)], [sp.diff(r,z),sp.diff(theta,z),sp.diff(phi,z)] ]) from sympy.core.function import Function f = Function('f')(r,theta,phi) T3 = R3*sp.Matrix([[sp.diff(f,r)],[sp.diff(f,theta)],[sp.diff(f,phi)]]) i = sp.symbols('i',integer=True) sp.trigsimp(sp.summation( R3[i,0]*sp.diff(T3[i,0],r)+R3[i,1]*sp.diff(T3[i,0],theta)+R3[i,2]*sp.diff(T3[i,0],phi), (i,0,2)))
を入力することにより
がわかります。
4次元ラプラシアン
ついでに4次元のラプラシアン
を4次元極座標 で表してみましょう。 と の関係は
または
です。なんとなくパターンが見えてきますね。あとは省略しますが
%reset -f # -f は定義したシンボルを初期化する確認が不要である場合のオプションです import sympy as sp sp.var('x, y, z, w') r = sp.sqrt(x**2+y**2+z**2+w**2) theta = sp.atan(sp.sqrt(x**2+y**2+z**2)/w) phi = sp.atan(sp.sqrt(x**2+y**2)/z) psi = sp.atan(sp.sqrt(x**2)/y) r4 = sp.simplify(sp.Matrix([ [sp.diff(r,x),sp.diff(theta,x),sp.diff(phi,x),sp.diff(psi,x)], [sp.diff(r,y),sp.diff(theta,y),sp.diff(phi,y),sp.diff(psi,y)], [sp.diff(r,z),sp.diff(theta,z),sp.diff(phi,z),sp.diff(psi,z)], [sp.diff(r,w),sp.diff(theta,w),sp.diff(phi,w),sp.diff(psi,w)] ])) del(r, theta, phi, psi) sp.var('r, theta, phi, psi', nonnegative = True) R4 = sp.expand(sp.trigsimp( r4.subs(x, r*sp.sin(theta)*sp.sin(phi)*sp.sin(psi)). subs(y, r*sp.sin(theta)*sp.sin(phi)*sp.cos(psi)). subs(z, r*sp.sin(theta)*sp.cos(phi)). subs(w, r*sp.cos(theta))). subs(sp.Abs(sp.sin(theta)), sp.sin(theta)). subs(sp.Abs(sp.sin(phi)), sp.sin(phi)). subs(sp.Abs(sp.sin(psi)), sp.sin(psi)), trig = True) T4 = R4*sp.Matrix([ [sp.diff(r,x),sp.diff(theta,x),sp.diff(phi,x),sp.diff(psi,x)], [sp.diff(r,y),sp.diff(theta,y),sp.diff(phi,y),sp.diff(psi,y)], [sp.diff(r,z),sp.diff(theta,z),sp.diff(phi,z),sp.diff(psi,z)], [sp.diff(r,w),sp.diff(theta,w),sp.diff(phi,w),sp.diff(psi,w)] ]) from sympy.core.function import Function f = Function('f')(r,theta,phi,psi) T4 = R4*sp.Matrix([[sp.diff(f,r)],[sp.diff(f,theta)],[sp.diff(f,phi)],[sp.diff(f,psi)]]) i = sp.symbols('i',integer=True) sp.trigsimp(sp.summation( R4[i,0]*sp.diff(T4[i,0],r)+R4[i,1]*sp.diff(T4[i,0],theta) +R4[i,2]*sp.diff(T4[i,0],phi)+R4[i,3]*sp.diff(T4[i,0],psi), (i,0,3)))
から
と求まります。
以上の結果から5次元、6次元、…の場合の結果を予想してみて、その予想が正しかったかどうか、Pythonを使って検証してみるというのも面白いかもしれません。
ちなみに、答えだけ書いておくと