Excelで24節気を概算する

JPLの[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)というページに、太陽系の惑星の位置をある程度の精度で計算するための軌道要素（ケプラー要素）や計算手順が記載されている。このページの情報をもとに、地球の位置を計算すれば24節気を計算することができるはずなので、2021年の24節気をエクセルを使って計算してみた。
このページによると、誤差は20秒角とのことなので、24節気を計算した場合の誤差は8分程度と考えられるが、どうだろうか？

# ケプラー要素の説明

地球月重心を含む各惑星は楕円軌道に沿って移動していると考えられる。この章では楕円軌道のパラメータを紹介する。

$ $楕円の乗っている平面（公転面）を決定するのに 昇交点黄経(longitude of the ascending node) $\Omega$ と軌道傾斜角（inclination）$I$を使う。楕円軌道の形を決定するのに*軌道長半径（semi-major axis）*$a$ と *離心率（eccentricity）* $e$ を使う。公転面上で、楕円の向きを決定するのに近点引数（argument of perihelion）$\\omega$ を使う。
上記5つのパラメータで楕円軌道が決定できる。楕円軌道上の位置を表すために、さらに*平均近点角（mean anomaly）* $M$を使う。この記事では、これらの6変数を軌道要素と呼ぶ。太陽と惑星の質量が固定されていることを考慮すると、「位置と速度の6変数」と「軌道要素の6変数」は等価である。

ケプラー運動では楕円軌道を決定するための5つのパラメータは時刻によらず不変で、軌道は楕円である。しかし、各惑星は厳密にはケプラー運動をしおらず、あくまで「瞬時の軌道要素」⇔「瞬時の位置と速度」が相互に変換できるということである[^1]。実際の惑星の運動では、楕円軌道を決定するための5つのパラメータ（例えば近点引数）が常に変化しているということになる。

[^1]: 数学で、2次の接触をする円というのがあるが、関係ない

$\omega$と$M$は意味が少しわかりにくいので、代わりに近点黄経$\varpi$と平均黄経$L$を使うことがある。近点黄経は$\varpi=\Omega+\omega$、平均黄経は$L=\Omega+\omega+M$と定義する。$a,e,I,L,\varpi,\Omega$をケプラー要素と呼び、「ケプラー要素の6変数」は「軌道要素の6変数」や「位置と速度の6変数」と等価である。

# 24節気の説明

太陽の視黄経が0°、15°、などになる瞬間を春分、清明などと呼び、黄道1周360°に存在する24回をまとめて24節気と呼ぶ。それぞれの視黄経に対応する名称は規則的ではなく、次の表のようになっている[^3]。

|視黄経|+0|+15|+30|+45|+60|+75|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|**0**|春分|清明|穀雨|立夏|小満|芒種|
|**90**|夏至|小暑|大暑|立秋|処暑|白露|
|**180**|秋分|寒露|霜降|立冬|小雪|大雪|
|**270**|冬至|小寒|大寒|立春|雨水|啓蟄|

[^3]: 部分的には規則的になっている。例えば、小寒・大寒の逆側が小暑、大暑となっている、など。

「24節気を計算する」というのは、このように定められた春分や清明などの日時を求めることである。

24節気は、国立天文台で計算し、暦要項という文書で発表しているため24節気の日時を知りたい場合は、国立天文台から発表されている情報を参照してください。この記事の趣旨はそれをあえて自前でエクセルで数式を組んで計算してみた、ということである。

太陽は黄道を1年で1周するので1日あたり約1°進んでいる[^4]。ということは1時間で2.5分角、1分で2.5秒角くらい進む。24節気を計算した際の誤差を検討する際に使うので、この関係を表にしておく。

|角度|太陽が進むのにかかる時間|
|:-:|:-:|
|1°|1日|
|0.3°|7時間|
|1分角|24分|
|20秒角|8分|
|2.5秒角|1分|
|1秒角|24秒|
|42mas|1秒|

[^4]: 赤経は0h〜24hで表記するが黄経なので°で表記する

# [Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html) の見方

このページではケプラー要素を使った惑星の位置の求め方が説明されている。
後半にTable 1、Table 2a、Table 2bの3つの数表がある。この表に出てくるEM Baryというのが地球月重心のことである。今回は、2021年の24節気を計算しようとしているので、Table 1を使うのが適切である。ページ上部の表によると、Table 1を使った場合の誤差は20秒角なので、24節気の計算誤差は8分程度と予想される[^5]。

[^5]: 赤経の誤差が20秒角とのことだが、黄経も同様と考えた

ユリウス日というのは紀元前の特定の日からの通算日数で、小数部分を使い時刻を表す。小数部分の使い方はエクセルのシリアル値と同様である。エクセルのシリアル値に2415018.125を足すと、ユリウス日になる。2415018.125というのは、2000年1月1日正午のユリウス日2451544.625と、エクセルのシリアル値36526.5[^6]の差である[^7]。

[^6]: エクセルの「1904年から計算する」という設定をしていない場合
[^7]: この小数部分の説明。ユリウス日は世界時で特定の日の正午を基準にしているため、日本時間の正午は整数より0.375=9/24小さい値となる。一方、日本で使っているエクセルのシリアル値は日本の真夜中の0時を基準にしているため、正午の小数部分は0.5となる。

記載されているEM Baryのケプラー要素の数値について考察してみよう。

|軌道要素|考察|
|:-:|:-|
|軌道長半径|ほぼ1天文単位。1天文単位は、地球から太陽までの距離とほぼ等しくなるように定義されているため|
|離心率|0に近い値なので軌道は真円に近い楕円|
|軌道傾斜角|座標系の基準が地球のためほぼ0|
|昇交点黄経|座標系の基準が地球のためほぼ0|
|近点黄経|変化率が0.323°/世紀というのは、1周するのに約11万年かかるペース[^8]|
|平均黄経|変化率が36000°/世紀に近いというのは、1世紀（＝100年）の間に地球が太陽を100周するから|

[^8]: [金日点の移動](https://eco.mtk.nao.ac.jp/koyomi/wiki/B6E1C6FCC5C0A4CEB0DCC6B0.html)参照

それではさっそく、エクセルを使って計算してみよう。

# エクセルで[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)の手順を実施

まずは[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)のTable 1をエクセルに貼り付け、「区切り位置」機能で表にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/c05fa559-8b6e-5760-9db9-d1be36b1316d.png)

日時を入力するセルを作り、ユリウス日を計算し、[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)に記載されている数式を入力してユリウス世紀数とケプラー要素を計算する[^9]。
[^9]: 画像には「光差補正」という列（M列）があるが、後で使うために用意したものであり、当面はL列と同じ値になるようにしてある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/22bd66e4-005a-8c76-54cb-df8b2a3d677a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/2ecc243f-3042-c766-b9d5-32f1b0dfb9a4.png)

次に[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)の通りに平均近点角を計算する（画像のT列）。なおTable 1より、昇交点黄経は0°なので、そのことを利用して数式を簡略化している。角度の変数が-180と180の間になるようにするために、180ずらしてから`MOD`関数を適用し、180を引いている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/99df1b8d-f334-3e7d-68b2-0e2eae4d53ae.png)

次は*離心近点角（eccentric anomaly）* $E$である。[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)に記載されているアルゴリズムを実行するユーザー定義関数は次の通りである[^10]。この関数を使ってW列で離心近点角を求めている。なお、この関数は弧度法で処理するので、V列やX列で弧度法の変換を行なっている。

```vb:
Function kepler(m, ecc)
    e = m - ecc * Sin(m)
    For Count = 1 To 10
        dm = m - e + ecc * Sin(e)
        e = e + dm / (1 - ecc * Cos(e))
    Next
    kepler = e
End Function
```

[^10]: ニュートン法によってケプラー方程式の解の近似値を求めている

次に、[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)の数式で、公転面内での座標と3次元の直交座標を求める。ここでも、昇交点黄経が0°であることを用いて数式を簡略化している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/f3713961-e0cb-f2be-e9e1-8cf88572bf0e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/830de43b-f682-4418-5424-517836617aec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/071752e1-c893-e460-0e12-ddf477ab27c3.png)

以上で、エクセルのAA〜AC列に太陽からみた地球の座標値が表示された。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/d92f0427-efe6-88bf-05d5-239e34497564.png)

# 24節気の計算

まず、視黄経の正解の値として、暦象年表の結果を貼り付けておく（下図のF列）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/648d782a-fa5c-2806-c22a-9c9a8d6fce75.png)

地球から見た座標にするためにAA〜AC列の座標値を-1倍し、`ATAN2`関数を使って黄経を求める。正解との誤差を計算する数式を入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/e88bdab2-d1c5-750e-b295-dc9c5ae3f49e.png)

これによって黄経と誤差が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/8481a014-26b5-0020-cd58-0d558cb6327f.png)

誤差をグラフにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/d6870c6d-baa4-9108-db23-9c1186a89e77.png)

今回計算した黄経は、正解の視黄経に比べて、0.29°程度、小さい値となっていたことがわかる。このまま24節気を計算したら、7時間程度、遅めの時間が求まるはずである。

では24節気を計算してみよう。
24節気の名前と対応する黄経を入力し、AD列の黄経との誤差を計算する数式を入力する。さらに暦象年表のページから、24節気の時刻の正解データを取得し貼り付けておき、正解との誤差を表示する数式を入力しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/6113877d-bbd1-ac53-2669-054ff9c3ed17.png)

24節気の計算には、次のマクロを使う。

```vb:
Sub oikomi()
    For Count = 1 To 50
        If IsEmpty(ActiveCell) Then Exit For
        oikomi1
        ActiveCell.Offset(1, 0).Select
        DoEvents
    Next
End Sub
 
Sub oikomi1()
    oikomi_aux ActiveCell.Offset(0, 1), 1, 365
    oikomi_aux ActiveCell.Offset(0, 1), 1# / 24, 24
    oikomi_aux ActiveCell.Offset(0, 1), 1# / 24 / 60, 60
    oikomi_aux ActiveCell.Offset(0, 1), 1# / 24 / 60 / 60, 60
End Sub

Sub oikomi_aux(objcell, delta, max)
    For Count = 1 To max
            ActiveCell.Value = ActiveCell.Value + delta
            If objcell.Value < 0 Then Exit For
    Next
    ActiveCell.Value = ActiveCell.Value - delta
End Sub
```

このマクロを使うために、次のように初期値を入力しておく（E列）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/17cc060d-1c00-9f24-4161-a261e63c6c6c.png)

マクロを実行してしばらく待つと、計算結果が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128380/aed6663a-e1aa-2896-2109-bd583c488d36.png)

以上で、24節気の計算をエクセルで行った結果を得られた。計算結果は正解と比較して7時間程度遅くなっている。

# 誤差の考察

誤差は8分程度になると予想していたが、7時間となってしまった。この誤差の最大の原因は歳差である。

今回の記事では[Approximate Positions of the Planets](https://ssd.jpl.nasa.gov/planets/approx_pos.html)のページに記載されている情報から計算してみたが、例えば、歳差を考慮するには[Astrodynamic Parameters](https://ssd.jpl.nasa.gov/astro_par.html)に記載されている「general precession in longitude」の値を使えばよい。

実は、歳差、光差、地球月重心と地球の位置のずれ、章動を考慮して、精度が向上することを手元で確認できている。いつか続編記事を作りたい。