2つの物体の間には,物体の質量に比例し,2物体間の距離の2乗に反比例する引力が作用する.
太陽の周りを回る地球の軌道を計算してみよう.
天体 \(i\) が複数の天体 \(j\) からの万有引力を受けて運動している場合,運動方程式は以下のように書ける.
少々難しい書き方の気がするが,地球(\(i=e\))が太陽(\(j=s\))の周りをまわっているとすれば,地球の運動方程式は,
太陽を中心に固定し, \(\boldsymbol{x}_e- \boldsymbol{x}_s = \boldsymbol{r}\) と書けば,
なじみの書き方になる. xy座標系で計算することにして,
である.
さて,運動方程式を数値計算すればよいのだが,万有引力定数 \(G = 6.67259 \times 10^{-11} \mathrm{m^3 s^{-2} kg^{-1}}\) ,太陽の質量 \(m_s = 1.989 \times 10^{30} \mathrm{kg}\) など非常に小さな数,大きな数が式中に現れている.これをそのまま計算するのは避けたい.
すると,
同様に,
これらを用いて運動方程式を書きなおすと,
右辺からは単位をもった係数がなくなっている.距離がうまく無次元化できているならば大きさは1程度である.左辺の係数も大きさが1程度になるように選びたい.そこで,
になるように \(T\) を決める.すなわち,
とする.すると結局運動方程式は,
となる.元の式と比べると,大きな(あるいは小さな)値をもった係数がなく簡潔である.
ボール投げの時と同様に,速度の変数を使う.(無次元変数を示す「*」は省略)
ルンゲ-クッタ法を使って計算する.以下にコードを示す.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | !+++++++++++++++++++++++++++++++++++++++++++++++
module globals
double precision,parameter:: G = 6.67384d-11
double precision delta_t
end module globals
!+++++++++++++++++++++++++++++++++++++++++++++++
module subfunc
implicit none
contains
function fx(x,y,u) result(xx)
double precision,intent(in):: x,y,u
double precision xx
xx = u
end function fx
function fu(x,y,u) result(xx)
double precision,intent(in):: x,y,u
double precision r,xx
r = sqrt(x**2+y**2)
xx = -x / r**3
end function fu
function fy(x,y,u) result(xx)
double precision,intent(in):: x,y,u
double precision xx
xx = u
end function fy
function fv(x,y,u) result(xx)
double precision,intent(in):: x,y,u
double precision r,xx
r = sqrt(x**2+y**2)
xx = -y / r**3
end function fv
end module subfunc
!+++++++++++++++++++++++++++++++++++++++++++++++
program celestial
use globals
use subfunc
implicit none
integer i
integer,parameter:: n=100
double precision tmax
double precision t(n),x(n),y(n),u(n),v(n)
double precision E(n)
double precision kx1,kx2,kx3,kx4,ku1,ku2,ku3,ku4
double precision ky1,ky2,ky3,ky4,kv1,kv2,kv3,kv4
x(1) = 1.0d0
y(1) = 0.0d0
u(1) = 0.0d0
v(1) = 1.0d0
t(1) = 0.0d0
tmax = 10.0d0
delta_t = (tmax-t(1))/dble(n)
do i = 1, n-1
kx1 = fx(x(i),y(i),u(i))*delta_t
ky1 = fy(x(i),y(i),v(i))*delta_t
ku1 = fu(x(i),y(i),u(i))*delta_t
kv1 = fv(x(i),y(i),v(i))*delta_t
kx2 = fx(x(i)+0.5d0*kx1,y(i)+0.5d0*ky1,u(i)+0.5d0*ku1)*delta_t
ky2 = fy(x(i)+0.5d0*kx1,y(i)+0.5d0*ky1,v(i)+0.5d0*kv1)*delta_t
ku2 = fu(x(i)+0.5d0*kx1,y(i)+0.5d0*ky1,u(i)+0.5d0*ku1)*delta_t
kv2 = fv(x(i)+0.5d0*kx1,y(i)+0.5d0*ky1,v(i)+0.5d0*kv1)*delta_t
kx3 = fx(x(i)+0.5d0*kx2,y(i)+0.5d0*ky2,u(i)+0.5d0*ku2)*delta_t
ky3 = fy(x(i)+0.5d0*kx2,y(i)+0.5d0*ky2,v(i)+0.5d0*kv2)*delta_t
ku3 = fu(x(i)+0.5d0*kx2,y(i)+0.5d0*ky2,u(i)+0.5d0*ku2)*delta_t
kv3 = fv(x(i)+0.5d0*kx2,y(i)+0.5d0*ky2,v(i)+0.5d0*kv2)*delta_t
kx4 = fx(x(i)+kx3,y(i)+ky3,u(i)+ku3)*delta_t
ky4 = fy(x(i)+kx3,y(i)+ky3,v(i)+kv3)*delta_t
ku4 = fu(x(i)+kx3,y(i)+ky3,u(i)+ku3)*delta_t
kv4 = fv(x(i)+kx3,y(i)+ky3,v(i)+kv3)*delta_t
x(i+1) = x(i) + (kx1+2.0d0*kx2+2.0d0*kx3+kx4)/6.0d0
u(i+1) = u(i) + (ku1+2.0d0*ku2+2.0d0*ku3+ku4)/6.0d0
y(i+1) = y(i) + (ky1+2.0d0*ky2+2.0d0*ky3+ky4)/6.0d0
v(i+1) = v(i) + (kv1+2.0d0*kv2+2.0d0*kv3+kv4)/6.0d0
t(i+1) = t(i) + delta_t
end do
E = 0.5d0*(u**2 + v**2) - 1.0d0 / dsqrt(x**2+y**2)
open(unit=10,file='outputRK.dat',status='replace')
write(10,*)'t_rk, x_rk, y_rk, E_rk'
do i = 1,n
write(10,*)t(i),',',x(i),',',y(i),',',E(i)
end do
close(10)
end program celestial
!+++++++++++++++++++++++++++++++++++++++++++++++
|
Warning
モジュールglobalはいらない.関数fuとfv内でのrの計算が重複している.関数の変数からtを(使わないので)削除した.またuだけでなくu,vとしたほうがよいのでは(使わないけど).
座標(1.0,0.0),速度(0.0,1.0)の初期条件で10秒(時間刻みは10/100=0.1)の計算を行っている. ボール投げ問題と比べて関数fxとかfuの中身が少々変わっているだけで,その他はほとんど変更なし.