マイコン宇宙講座-彗星の位置予報

明るく、肉眼でも見える彗星は、それだけで華やかな天文現象です。いままでに数々の彗星が天空を賑わせてきました。残念ながら近年は、昔のように華々しい彗星の出現はないのは寂しい気がします。かっては眼視による彗星捜索は観測機器の進歩によって写真に取って代わられ、また、SOHOで撮影された写真から数々の太陽に接近する彗星が発見されています。時代の流れといえばそれまでですが、眼視による発見で、天空を飾る池谷・関彗星のような発見はもうこないのかもしれません。

コンピュータの進化によって、天体の位置計算は大きく変わってきました。今のようにコンピュータがない時代は、三角関数表や対数表を用いて手で計算していました。観測結果から軌道要素の計算、位置予報ならともかく摂動を含む計算は、数ヶ月や年単位の計算時間が必要だったと聞きます。位置予報でも大変な計算ですが。今では、コンピュータによって、昔のように時間をかけることなく瞬時に求めることができます。もちろん、計算だけでなくコンピュータによる天体の自動導入、画像から位置計算や測光といった処理をアマチュアでも行えるようになり、コンピュータはいまやとってはならないものになっています。

サブルーチン Nearly Parabolic

※サブルーチンはlib.pyに記述してください。

# NEARLY PARABOLIC
def nearly_parabolic(tp, t, q, ec, K):
    r1 = 1.0 + 9.0 * ec
    aa = math.sqrt(0.1 * r1)
    bb = 5.0 * (1.0 - ec) / r1
    cc = math.sqrt(5.0 * (1.0 + ec) / r1)

    b = 1.0
    a0 = 0.0
    while True:
        u = b * aa * K[1] * (tp - t) / (math.sqrt(2.0) * math.pow(q, 1.5))
        r2 = 1.0
        while True:
            v = (u + 2.0 * math.pow(r2, 3) / 3.0) / (1.0 + r2 * r2)
            if abs(v - r2) > 1.0e-6:
                r2 = v
            else:
                break
        a = bb * v * v
        a2 = a * a
        a3 = a2 * a
        b = 1.0 - 0.017142857 * a2 - 0.003809524 * a3
        if abs(a - a0) > 1.0e-6:
            a0 = a
        else:
            break

    c = 1.0 + 0.4 * a + 0.21714286 * a2 + 0.12495238 * a3
    d = 1.0 - a + 0.2 * a2 + 0.00571429 * a3
    qd = q * d
    v = cc * c * v

    cc = qd * (1.0 - math.pow(v, 2))
    ss = 2.0 * qd * v
    v = 2.0 * math.atan(v)

    return ss, cc, v

メインルーチン m61.py

プログラム実行時に求められる日付と時刻については、近日点通過時刻の前後を指定するようにしてください。ハレー彗星のように近日点通過時刻が1986年2月9日の場合、現在の位置を求めようとして2022年7月1日というように入力すると、尾の見かけ上の長さを計算中に平方根の値が範囲外(マイナス値)になってしまうため、プログラムがブレークします。その距離の遠さから計算結果が0より小さくなってしまうからだとは思います。これを回避するために、0より小さくなった場合は、尾の見かけ上の長さを0とするように処理を追加しています。なお、計算は1950年分点で計算されていますので、2022年を指定しても位置は正しくないと思います。

# m61.py
# マイコン宇宙講座
# 6-1 彗星の位置予報プログラム
import math
import lib


M2PI = 2.0 * math.pi

x = [[0 for i in range(10)] for j in range(4)]
f = [0, 0, 0, 0]
q = [0, 0, 0, 0]
fx = [0, 0, 0, 0]   # f[n + 3]
qx = [0, 0, 0, 0]   # q[n + 3]
sx = [0, 0, 0, 0]   # s[n]
ex = [0, 0, 0, 0]   # e[n]
tx = [0, 0, 0, 0]
elm = [0 for i in range(11)]


# 彗星の軌道要素
# 他の彗星の場合は、ここのデータを入れ替える
# ただし、離心率が0.8を超える彗星のみ
def OrbitElements():
    elm = [0 for i in range(11)]

    c = 'COMET P/Halley'
    elm[1] = 1986.0         # 近日点通過時刻 T
    elm[2] = 2.0
    elm[3] = 9.6613
    elm[4] = 0.587096       # 近日点距離 q
    elm[5] = 0.967267       # 離心率 e
    elm[6] = 111.8534       # 近日点引数 ω
    elm[7] = 58.1531        # 昇交点黄経 Ω
    elm[8] = 162.2378       # 軌道傾斜角 i
    elm[9] = 5.2            # 全光度 m1
    elm[10] = 0.2           # 尾

    return c, elm


print()
std = input('計算を始めたい日と時分(JST) ? ')
dy, dt = std.split(',')
dy = float(dy)
dt = float(dt)

jd, yy, mm, dd, hh, ms, ss = lib.mjd(dy, dt)

jd = 10.0 * int(jd / 10.0)
jd1 = jd

std = input('計算期間(日単位) ? ')
ii = int(std)
std = input('計算間隔(日単位) ? ')
iv = int(std)

yz = 0
mz = 0

jd2 = jd + ii

# 彗星の位置予報

# 彗星の軌道要素の読み込み
c, elm = OrbitElements()
yy = elm[1]
mm = elm[2]
dd = elm[3]
pe = elm[6]
nd = elm[7]
ic = elm[8]
m1 = elm[9]
tl = elm[10]

jd = lib.julian(yy, mm, dd) - 2400000.5
t = jd

pe = pe / lib.K[3]
nd = nd / lib.K[3]
ic = ic / lib.K[3]

f, q = lib.eph_const(pe, nd, ic, lib.K)

for i in range(1, 4):
    fx[i] = f[i]
    qx[i] = q[i]

no = lib.K[1] / math.pow(elm[4] / (1.0 - elm[5]), 1.5)
a = elm[4] / (1.0 - elm[5])
pd = pow(a, 1.5)

print()
print('    ' + c)
print()
print('     T    =  %4d  %2d  %7.4f ET' % (yy, mm, dd))
print('     Peri.= %8.5f               e = %10.6f' % (pe * lib.K[3], elm[5]))
print('     Node = %9.5f (1950)        a = %9.5f AU' % (nd * lib.K[3], a))
print('     Inc. = %8.5f               n =  %9.6f' % (ic * lib.K[3], no * lib.K[3]))
print('        q =  %9.6f (AU)         P =  %4.2f 年' % (elm[4], pd))
print()
print('Date (0時ET)    R.A. (1950) Decl.     Delta      r      Mag    Elong.   PA   Tail')
print('----------------------------------------------------------------------------------')
print('   年  月  日    h  m        。 ,        AU       AU     等       。      。    。')

# 太陽座標(X,Y,Z)
while True:
    t1 = jd1 - 33281.92334
    t1 = t1 * (2.737909288e-5 + 1.260132857e-17 * t1)
    t2 = t1 * t1

    e, m, p, n, i, a, rd = lib.mean_elements(3, t1, t2)    # GOSUB 5300

    pe = p
    nd = n
    ic = i

    f, q = lib.eph_const(pe, nd, ic, lib.K)                 # GOSUB 4000

    ec = e
    mo = m / M2PI
    mo = M2PI * (mo - int(mo))
    ss, cc, ff = lib.kepler(mo, ec)                     # GOSUB 8500
    b = a * math.sqrt(1.0 - ec * ec)
    for n in range(1, 4):
        f[n] = a * f[n]
        q[n] = b * q[n]

    rs = 0
    for n in range(1, 4):
        x[n][3] = -(ff * f[n] + ss * q[n])
        rs = rs + math.pow(x[n][3], 2)
    rs = math.sqrt(rs)                                      # 地球と太陽との距離

    # 彗星の位置(赤経・赤緯)
    dl = 0
    while True:
        tp = jd1 - 0.005776 * dl
        ss, cc, v = lib.nearly_parabolic(tp, t, elm[4], elm[5], lib.K)

        rc = 0
        ds = 0
        for n in range(1, 4):
            sx[n] = fx[n] * cc + qx[n] * ss
            ex[n] = sx[n] + x[n][3]
            rc = rc + math.pow(sx[n], 2)
            ds = ds + math.pow(ex[n], 2)
        rc = math.sqrt(rc)                                  # 太陽と彗星の距離
        ds = math.sqrt(ds)                                  # 地球と彗星の距離
        if abs(ds - dl) > 0.001:
            dl = ds
        else:
            break

    ss = ex[2]
    cc = ex[1]
    tt = lib.quadrant(ss, cc)                               # GOSUB 3500
    ra = tt
    dc = math.atan(ex[3] * math.cos(ra) / ex[1])
    mg = m1 + 5.0 * math.log(ds) / 2.30259 + 15.0 * math.log(rc) / 2.30259

    cc = (rs * rs + ds * ds - rc * rc) / (2.0 * rs * ds)
    ss = math.sqrt(1.0 - cc * cc)
    eg = math.atan(ss / cc)
    if eg < 0:
        eg = eg + math.pi

    dl = 0
    for n in range(1, 4):
        tx[n] = fx[n] * (rc + tl) * math.cos(v) + qx[n] * (rc + tl) * math.sin(v)
        tx[n] = tx[n] + x[n][3]
        dl = dl + math.pow(tx[n], 2)

    ss = tx[2]
    cc = tx[1]
    tt = lib.quadrant(ss, cc)                               # GOSUB 3500

    rt = tt
    dt = math.atan(tx[3] * math.cos(rt) / tx[1])
    dl = math.sqrt(dl)

    cc = (math.pow(ds, 2) + math.pow(dl, 2) - math.pow(tl, 2)) / (2.0 * ds * dl)
    
    # (1.0 - cc * cc)の計算結果が0より小さい場合は見かけ上の尾の長さを0とする    
    if (1.0 - cc * cc) < 0:
        cl = 0
    else:
        ss = math.sqrt(1.0 - cc * cc)
        cl = math.atan(ss / cc)

    ss = math.cos(dt) * math.sin(rt - ra)
    cc = math.cos(dc) * math.sin(dt) - math.sin(dc) * math.cos(dt) * math.cos(rt - ra)
    tt = lib.quadrant(ss, cc)                               # gosub 3500
    pa = tt

    # 位置予報
    jd = jd1
    yy, mm, dd = lib.jdate(jd, lib.T)

    ra = ra * lib.K[3] / 15.0
    dc = dc * lib.K[3]

    rh = int(ra)
    rm = 60.0 * (ra - rh)
    if int(rm + 1.0e-3) == 60:
        rh = rh + 1
        rm = 0

    sg = lib.sgn(dc)
    dc = abs(dc)
    dh = int(dc)
    dm = 60.0 * (dc - dh)
    if int(dm + 0.01) == 60:
        dc = dc + 1
        dm = 0

    str_sg = '+'
    if sg < 0:
        str_sg = '-'

    eg = eg * lib.K[3]
    cl = cl * lib.K[3]
    pa = pa * lib.K[3]

    sfmt = '         %2d    %2d %5.2f   %s%2d %4.1f   %6.3f   %6.3f   %4.1f    %5.1f   %5.1f  %4.1f' % (dd, rh, rm, str_sg, dh, dm, ds, rc, mg, eg, pa, cl)
    if yy != yz:
        sfmt = '%4d %2d  %2d    %2d %5.2f   %s%2d %4.1f   %6.3f   %6.3f   %4.1f    %5.1f   %5.1f  %4.1f' % (yy, mm, dd, rh, rm, str_sg, dh, dm, ds, rc, mg, eg, pa, cl)
    else:
        if mm != mz:
            sfmt = '     %2d  %2d    %2d %5.2f   %s%2d %4.1f   %6.3f   %6.3f   %4.1f    %5.1f   %5.1f  %4.1f' % (mm, dd, rh, rm, str_sg, dh, dm, ds, rc, mg, eg, pa, cl)
    print(sfmt)

    yz = yy
    mz = mm
    jd1 = jd1 + iv
    if jd1 < jd2:
        continue
    else:
        break
print('-----------------------------------------------------------------------------------')
print()

例題 1985年8月1日から1年間のハレー彗星の位置予報を計算してみよう。なお、時刻は9時とします。9時とするのは、位置予報は世界時0時で発表されるためです。

計算を始めたい日と時分(JST) ? 19850801,090000
計算期間(日単位) ? 365
計算間隔(日単位) ? 10

    COMET P/Halley

     T    =  1986   2   9.6613 ET
     Peri.= 111.85340               e =   0.967267
     Node =  58.15310 (1950)        a =  17.93591 AU
     Inc. = 162.23780               n =   0.012975
        q =   0.587096 (AU)         P =  75.96 年

Date (0時ET)    R.A. (1950) Decl.     Delta      r      Mag    Elong.   PA   Tail
----------------------------------------------------------------------------------
   年  月  日    h  m        。 ,        AU       AU     等       。      。    。
1985  7  24     5 47.18   +18 44.0    3.991    3.198   15.8     33.9   261.7   0.5
      8   3     5 53.46   +18 54.6    3.761    3.081   15.4     41.9   264.3   0.6
         13     5 59.36   +19  4.0    3.510    2.962   15.0     50.0   266.3   0.8
         23     6  4.64   +19 12.8    3.238    2.841   14.6     58.3   267.8   1.0
      9   2     6  9.00   +19 21.7    2.950    2.717   14.1     66.9   269.2   1.2
         12     6 12.02   +19 31.7    2.646    2.592   13.5     75.9   270.2   1.5
         22     6 13.07   +19 44.5    2.332    2.464   12.9     85.4   271.0   1.8
     10   2     6 11.16   +20  2.0    2.012    2.333   12.2     95.6   271.4   2.2
         12     6  4.60   +20 27.1    1.690    2.199   11.5    107.0   271.4   2.7
         22     5 50.34   +21  2.5    1.374    2.063   10.6    120.3   270.4   3.1
     11   1     5 22.48   +21 46.7    1.077    1.924    9.6    136.7   267.7   3.2
         11     4 29.84   +22 11.9    0.822    1.781    8.5    158.8   260.3   2.3
         21     2 59.08   +20 18.9    0.654    1.635    7.5    169.6    91.2   1.5
     12   1     1  6.79   +13 43.3    0.632    1.486    6.8    132.1    73.0   7.0
         11    23 40.92   + 6  5.0    0.751    1.334    6.5     99.6    67.7   9.3
         21    22 49.61   + 0 55.7    0.938    1.180    6.1     75.7    65.5   8.7
         31    22 18.39   - 2 14.1    1.139    1.025    5.6     57.2    63.7   7.3
1986  1  10    21 56.71   - 4 23.9    1.323    0.875    4.9     41.4    61.1   5.8
         20    21 38.70   - 6 12.5    1.469    0.737    4.1     26.7    55.9   4.2
         30    21 21.11   - 8  5.8    1.553    0.632    3.2     12.9    39.4   2.3
      2   9    21  2.79   -10 20.3    1.551    0.587    2.7      7.6   308.4   1.5
         19    20 44.70   -13  1.2    1.450    0.622    2.9     20.1   268.3   3.9
      3   1    20 27.45   -16 12.4    1.269    0.721    3.6     34.5   260.3   6.4
         11    20  8.51   -20 19.6    1.039    0.855    4.3     49.7   257.7   8.9
         21    19 39.78   -26 33.2    0.787    1.005    4.7     67.4   258.2  11.9
         31    18 34.80   -37 13.4    0.549    1.159    4.9     92.3   267.0  14.8
      4  10    15 25.04   -47 29.1    0.417    1.314    5.1    131.0   313.7  11.2
         20    12  4.69   -32 58.2    0.515    1.466    6.2    147.8    53.4   6.0
         30    10 58.28   -19 16.8    0.770    1.615    7.8    130.3    92.9   5.7
      5  10    10 35.02   -12 25.4    1.078    1.762    9.1    115.0   103.5   4.8
         20    10 26.27   - 8 49.9    1.404    1.905   10.1    102.9   108.4   3.8
         30    10 23.93   - 6 50.4    1.732    2.045   11.1     92.5   111.5   3.0
      6   9    10 24.96   - 5 44.3    2.058    2.181   11.8     83.0   113.9   2.4
         19    10 27.98   - 5 11.1    2.374    2.315   12.5     74.2   116.1   1.9
         29    10 32.24   - 4 59.7    2.679    2.446   13.2     65.9   118.3   1.5
      7   9    10 37.30   - 5  3.8    2.969    2.575   13.7     57.8   120.6   1.2
         19    10 42.86   - 5 19.2    3.241    2.701   14.2     49.9   123.3   1.0
-----------------------------------------------------------------------------------