天体の位置計算 – 行列の計算

「天球座標-行列の計算」 37-39頁

赤道座標から地平座標への変換で、恒星の高度と方位角を求めました。ここでは、同じことを行列を使って求めることにします。計算にあたって必要なデータは地点の緯度、恒星時、対象となる恒星の位置の方向余弦です。

最初に行列用の配列を宣言し、配列の中にデータを記述していきます。今回は積だけですので、matmul関数を使って求めていきます。ただ、関数の中に記述できるのは、2つの配列だけですので、それ以上記述するには、関数の中にmatmul関数を記述します。よくわからなければ、コードを参考にしてください。

赤道座標から地平座標へ変換する行列式

\[ \begin{pmatrix} l\\ m\\ n \end{pmatrix} = \begin{pmatrix} \sin\phi & 0 & -\cos\phi\\ 0 & 1 & 0\\ \cos\phi & 0 & \sin\phi \end{pmatrix} \begin{pmatrix} \cos\theta & \sin\theta & 0\\ -\sin\theta & \cos\theta & 0\\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} L\\ M\\ N \end{pmatrix} \]

Fortranによるコード
計算例では、すでに地方恒星時がわかっている前提になっているが、ここでは、ec2hc.f90を改変して、行列の計算を行ってみよう。

メインルーチン pcc_matrix_2.f90

program matrix
    use pcclib

    implicit none
    
    ! 恒星データ
    character(16), parameter :: SNM = 'α CMa  Sirius  '              ! 恒星名
    double precision, parameter :: SRA(1:3) = (/6d0, 42d0, 56.714d0/)   ! 赤経
    double precision, parameter :: SDC(1:3) = (/-16d0, 38d0, 46.36d0/)  ! 赤緯
    double precision, parameter :: SRA_PROPER_MOTION = -0.03791d0     ! 赤経方向の固有運動量
    double precision, parameter :: SDC_PROPER_MOTION = -1.2114d0      ! 赤緯方向の固有運動量
    double precision, parameter :: SRV = -7.6d0                       ! 視線速度
    double precision, parameter :: SAP = 0.377d0                      ! 年周視差

    !検証用恒星データ
    ! character(16), parameter :: SNM = '61 Cyg          ';           ! 恒星名
    ! double precision, parameter :: SRA(1:3) = (/21d0, 4d0, 39.935d0/) ! 赤経
    ! double precision, parameter :: SDC(1:3) = (/38d0, 29d0, 59.10d0/) ! 赤緯
    ! double precision, parameter :: SRA_PROPER_MOTION = 0.35227d0    ! 赤経方向の固有運動量
    ! double precision, parameter :: SDC_PROPER_MOTION = 3.1847d0     ! 赤緯方向の固有運動量
    ! double precision, parameter :: SRV = -64.3d0                    ! 視線速度
    ! double precision, parameter :: SAP = 0.296d0                    ! 年周視差

    ! 地点データ
    character(21), parameter :: OBS_NAME = 'Tokyo Observatory PZT'      ! 地点名
    double precision, parameter :: OBS_LG(1:3) = (/9d0, 18d0, 9.936d0/)   ! 経度
    double precision, parameter :: OBS_LA(1:3) = (/35d0, 40d0, 20.707d0/) ! 緯度
    double precision, parameter :: GAST(1:3) = (/17d0, 51d0, 24.267d0/)

    ! 検証用地点データ
    ! character(21), parameter :: OBS_NAME = 'Ngasawa home         '    ! 地点名
    ! double precision, parameter :: OBS_LG(1:3) = (/9d0, 18d0, 7.573d0/) ! 経度
    ! double precision, parameter :: OBS_LA(1:3) = (/35d0, 47d0, 20.0d0/) ! 緯度
    ! double precision, parameter :: GAST(1:3) = (/17d0, 11d0, 58.714d0/)

    double precision :: dy, dt, t
    double precision :: year, month, day, hour, minute, second
    double precision :: ra_rad, dc_rad, la_rad, lsdt_rad
    double precision :: l, m, n
    double precision :: gasdt, lsdt, long, cv
    double precision :: sdt_hour, sdt_minute, sdt_second
    double precision :: sdt(3), ma(3, 3), mb(3, 3), mc(3, 1), me(3, 1)
    character(255) :: dfmt

    ! 日付と時刻の入力
    write(*,*)
    write(*, fmt='(a)', advance='no') 'DATE AND TIME(JST) ? '
    read(*,*) dy, dt

    ! 日付と時刻を抽出
    year = int(dy / 10000.0d0)
    month = mod(int(dy / 100.0d0), 100)
    day = mod(dy, 100.0d0)
    hour = int(dt / 10000.0d0)
    minute = mod(int(dt / 100.0d0), 100)
    second = mod(dt, 100.0d0)

    ! グリニッジ視恒星時を時の小数点に換算
    gasdt = dms2deg(GAST(1), GAST(2), GAST(3))
    
    ! 経度を時の小数点に換算
    long = dms2deg(OBS_LG(1), OBS_LG(2), OBS_LG(3))
    
    ! 世界0時からの経過時間を時の小数点に換算
    hour = hour - 9d0;
    t = dms2deg(hour, minute, second)
    
    ! 補正値の計算
    cv = (hour * 3600d0 + minute * 60d0 + second) * 0.00273791d0
    cv = cv / 3600d0
    
    ! 地方恒星時
    lsdt = gasdt + long + t + cv
    sdt = deg2dms(lsdt)
    sdt_hour = sdt(1)
    sdt_minute = sdt(2)
    sdt_second = sdt(3)

    ! 恒星時が範囲を超えたときの処理
    if (sdt_hour > 24d0) then
        sdt_hour = sdt_hour - 24d0
    end if
    if (sdt_second >= 60d0) then
        sdt_second = sdt_second - 60d0
        sdt_minute = sdt_minute + 1d0
    end if
    if (sdt_minute == 60d0) then
        sdt_minute = 0d0
        sdt_hour = sdt_hour + 1d0
    end if
    if (sdt_hour == 24d0) then
        sdt_hour = 0d0
    end if

    ra_rad = deg2rad(hms2deg(SRA(1), sRA(2), SRA(3)))
    dc_rad = deg2rad(dms2deg(SDC(1), SDC(2), SDC(3)))
    la_rad = deg2rad(dms2deg(OBS_LA(1), OBS_LA(2), OBS_LA(3)))
    lsdt_rad = deg2rad(hms2deg(sdt_hour, sdt_minute, sdt_second))

    ! 方向余弦
    l = cos(dc_rad) * cos(ra_rad)
    m = cos(dc_rad) * sin(ra_rad)
    n = sin(dc_rad)

    ma(1, 1:3) = (/sin(la_rad), 0d0, -cos(la_rad)/)
    ma(2, 1:3) = (/0d0,         1d0,  0d0/)
    ma(3, 1:3) = (/cos(la_rad), 0d0,  sin(la_rad)/)

    mb(1, 1:3) = (/ cos(lsdt_rad),  sin(lsdt_rad), 0d0/)
    mb(2, 1:3) = (/-sin(lsdt_rad),  cos(lsdt_rad), 0d0/)
    mb(3, 1:3) = (/ 0d0,            0d0,           1d0/)

    mc(1, 1) = l
    mc(2, 1) = m
    mc(3, 1) = n

    me = matmul(matmul(ma, mb), mc)
    l = me(1, 1)
    m = me(2, 1)
    n = me(3, 1)

    ! 出力
    dfmt = '(a16, "      ", f11.8, "     ",  f11.8, "     ", f11.8, "    ", f11.8)'
    write(*, *)
    write(*, *) '星名                      L               M               N            二乗和'
    write(*, *) '-------------------------------------------------------------------------------'
    write(*, dfmt) SNM, l, m, n, l**2 + m**2 + n**2
    write(*, *)

    stop
end program matrix

コンパイル

gfortran pcc_lib.f90 pcc_matrix_2.f90

実行

./a.out

実行結果

DATE AND TIME(JST) ? 19780620,223217

 星名                      L               M               N            二乗和
 -------------------------------------------------------------------------------
α CMa  Sirius        -0.25252150     -0.47494142     -0.84300862     1.00000000