「Maxima でケプラー方程式の近似解と数値解」の SymPy 版。
from sympy import *
from sympy.abc import *
from sympy import pi
# グラフの大きさの設定,inline svg 表示
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] =8,6
plt.rcParams['font.size'] = 12
from IPython.display import set_matplotlib_formats
%matplotlib inline
set_matplotlib_formats('svg')
ベッセル関数によるケプラー方程式のフーリエ級数解
ケプラー方程式
$$u – e \sin u = \omega t$$
のフーリエ級数解は,ベッセル関数 $J_n(x)$ を使って以下のように書ける。
$$u = \omega t+ \sum_{n=1}^{\infty} \frac{2}{n} J_n(n e) \sin(n\, \omega t)$$
現実世界では無限大まで足し算はできないので,以下のように $N$ までの和をとることにする。
$$u(N, e, \omega t) = \omega t+ \sum_{n=1}^{N} \frac{2}{n} J_n(n e) \sin(n\, \omega t)$$
これを関数 Ubes(N, e, omegat)
として定義する。
omegat = Symbol('omegat')
def Ubes(N, e, omegat):
return(omegat +
summation(2/n * besselj(n, n*e) * sin(n * omegat), (n, 1, N))
)
Ubes(2, e, omegat)
# たとえば N=10, e=0.5, omegat = 1.0 の値
print(float(Ubes(10, 0.5, 1.0)))
逐次近似法によるケプラー方程式の近似解
離心率 $e$ は $0 \leq e < 1$ であることから,ケプラー方程式
$$u – e \sin u = \omega t$$
を以下のように逐次近似的に解いてみます。
\begin{eqnarray}
u &=& \omega t + e \sin u \\
u_0 &=& \omega t\\
u_1 &=& \omega t + e \sin u_0 = \omega t + e \sin \omega t\\
u_2 &=& \omega t + e \sin u_1 =\omega t + e \sin\left(\omega t + e \sin \omega t\right) \\
u_3 &=& \omega t + e \sin u_2 =\omega t + e \sin\left\{\omega t + e \sin\left(\omega t + e \sin \omega t\right)\right\} \\
&\vdots&\\
u_{n} &=& \omega t + e \sin u_{n-1} = \dots\\
\end{eqnarray}
$n$ が大きくなると,入れ子になっている項がどんどん増殖していきますが,$u_3$ のあたりまでは,近似的に $u$ は $t$ の陽関数としてあらわされているなぁ… という見た目がします。
上の式にそって,以下のように関数 Uite(N, e, omegat)
を再帰的に定義します。
def Uite(N, e, omegat):
if N ==0:
return(omegat)
else:
return(omegat + e*sin(Uite(N-1, e, omegat)))
Uite(3, e, omegat)
# たとえば N=10, e=0.5, omegat = 1.0 の値
print(float(Uite(10, 0.5, 1.0)))
方程式の数値解法によるケプラー方程式の数値解
$\omega t$ を与えたときに,ケプラー方程式を数値的に解いて $u(\omega t)$ を求める。ケプラー方程式は超越方程式であるので,nsolve()
関数を使って数値に解く。
def Unum(e, omegat):
return(nsolve(u-e*sin(u)-omegat, u, omegat, prec=16))
# たとえば e=0.5, omegat = 1.0 の値
Unum(0.5, 1.0)
数値解と近似解との比較
# 数値解 Unum と逐次近似解 Uite, フーリエ級数解 Ubes の差
e = 0.5
N = 10
print(" omega t Unum Uite-Unum Ubes-Unum ")
for i in range(1, 10):
omti = float(pi/10*i)
print('%8.5f %18.15f %18.15f %18.15f' %
(omti,
Unum(e, omti),
Uite(N, e, omti) - Unum(e, omti),
Ubes(N, e, omti) - Unum(e, omti)
)
)
数値解との差の二乗平均平方根
- 参考:二乗平均平方根
いわゆる RMS (root mean square)
$$RMS \equiv \sqrt{\frac{1}{n} \sum_{i=1}^n \left( U(\omega t_i)- U_{\rm num}(\omega t_i)\right)^2}$$
def RMSite(N, e):
tmpsum = 0
for i in range(1, 10):
omti = float(pi/10*i)
tmpsum = tmpsum + (Uite(N, e, omti)-Unum(e, omti))**2
return(sqrt(1/9 * tmpsum))
def RMSbes(N, e):
tmpsum = 0
for i in range(1, 10):
omti = float(pi/10*i)
tmpsum = tmpsum + (float(Ubes(N, e, omti))-Unum(e, omti))**2
return(sqrt(1/9 * tmpsum))
print('%18.15e' % RMSite(10,0.5))
print('%18.15e' % RMSbes(10,0.5))
グラフ
$a = 5, \ e = 0.6$ の場合の楕円のグラフを描く。
\begin{eqnarray}
x(a, e, \omega t) &=& a (\cos u(\omega t) -e ) \\
y(a, e, \omega t) &=& a \sqrt{1 – e^2} \sin u(\omega t) \\
\end{eqnarray}
def x(a, e, omegat):
return(a*(cos(Uite(10, e, omegat)) - e))
def y(a, e, omegat):
return(a*sqrt(1-e**2)*sin(Uite(10, e, omegat)))
# 縦横比。
import matplotlib.pyplot as plt
# デフォルトでは plt.rcParams['figure.figsize'] = (6.0, 4.0) だった
plt.rcParams['figure.figsize'] = (5, 5)
plot_parametric(
x(5, 0.6, t), y(5, 0.6, t), (t, 0, 2*pi),
xlim=(-9, 3), ylim=(-6, 6));
omt = []
for i in range(1,37):
omt.append(float(pi/18*i))
X = []
for omti in omt:
X.append(x(5, 0.6, omti))
Y = []
for omti in omt:
Y.append(y(5, 0.6, omti))
plt.xlim(-9, 3)
plt.ylim(-6, 6)
plt.plot(X, Y, 'bo');