Sun and Moon phase
John D. Ramsdell
ramsdell at linus.UUCP
Mon Aug 26 21:21:04 AEST 1985
;;; -*- Mode: LISP; Base: 10; Package: COMMON-LISP-GLOBAL; Syntax: Common-lisp -*-
; Functions that compute the Julian date
; and the position of the sun and moon.
; Use print-julian-date and print-astro-time.
(provide 'astro-time)
(in-package 'astro-time)
(export '(print-julian-date print-astro-time))
;J2000.0 = January 1, 2000; Noon GMT.
(defconstant J2000.0 (encode-universal-time 0 0 12 1 1 2000 0))
(defconstant julian-date-at-j2000.0 2451545.0d0)
(defconstant time-units-per-day (* 60 60 24))
(defconstant days-per-time-unit (/ (float time-units-per-day)))
(defconstant days-per-julian-century 36525.0)
(defun time-units-from-j2000.0 (ut) ; Should be declared inline.
(float (- ut j2000.0)))
(defun ut->jd (ut) ; => Julian date as a dfloat.
(+ julian-date-at-j2000.0
(float (* days-per-time-unit
(time-units-from-j2000.0 ut))
0.0d0)))
(defun print-julian-date (&optional (ut (get-universal-time))
(stream *standard-output*))
(format stream "JD~2,7,,$" (ut->jd ut)))
; Radians and degrees.
(defconstant -pi (- pi))
(defconstant 2pi (* 2.0 pi))
(defconstant radians-per-degree (/ pi 180.0))
; Reduce an angle so that -pi < angle <= pi.
(defun normalize-angle (angle)
(if (> angle pi)
(loop while (> angle pi) do (setq angle (- angle 2pi)))
(loop while (<= angle -pi) do (setq angle (+ angle 2pi))))
angle)
; Astronomical almanac
; All formulas from
; The Astronomical Almanac for the Year 1984,
; US Naval Observatory and Royal Greenwich Observatory,
; US Goverment Printing Office, Washington DC, 1984.
; Position of the sun. (Page C24).
; Convert degrees to radians at compile time.
(defconstant sun0 (* radians-per-degree 280.460)) ; for mean longitude
(defconstant sun1 (* radians-per-degree 0.9856474 days-per-time-unit))
(defconstant sun2 (* radians-per-degree 357.528)) ; for mean anomaly
(defconstant sun3 (* radians-per-degree 0.9856003 days-per-time-unit))
(defconstant sun4 (* radians-per-degree 1.915)) ; for eliptic longitude
(defconstant sun5 (* radians-per-degree 0.020))
(defun sun-position (ut) ; Input: universal time.
"Returns the ecliptic longitude and the mean anomaly of the sun."
(let* ((time (time-units-from-j2000.0 ut))
(mean-longitude-of-sun (normalize-angle (+ sun0 (* sun1 time))))
(mean-anomaly (normalize-angle (+ sun2 (* sun3 time))))
(eliptic-longitude
(normalize-angle
(+ mean-longitude-of-sun
(* sun4 (sin mean-anomaly))
(* sun5 (sin (* 2.0 mean-anomaly)))))))
(values eliptic-longitude mean-anomaly)))
; Position of the moon (Page D46).
(defconstant julian-centuries-per-time-unit
(/ days-per-time-unit days-per-julian-century))
(defconstant moon0 (* radians-per-degree 218.32))
(defconstant moon1 (* radians-per-degree 481267.883 julian-centuries-per-time-unit))
(defconstant moon2a (* radians-per-degree 6.29))
(defconstant moon2b (* radians-per-degree 134.9))
(defconstant moon2c (* radians-per-degree 477198.85 julian-centuries-per-time-unit))
(defconstant moon3a (* radians-per-degree -1.27))
(defconstant moon3b (* radians-per-degree 259.2))
(defconstant moon3c (* radians-per-degree -413335.38 julian-centuries-per-time-unit))
(defconstant moon4a (* radians-per-degree 0.66))
(defconstant moon4b (* radians-per-degree 235.7))
(defconstant moon4c (* radians-per-degree 890534.23 julian-centuries-per-time-unit))
(defconstant moon5a (* radians-per-degree 0.21))
(defconstant moon5b (* radians-per-degree 269.9))
(defconstant moon5c (* radians-per-degree 954397.70 julian-centuries-per-time-unit))
(defconstant moon6a (* radians-per-degree -0.19))
(defconstant moon6b (* radians-per-degree 357.5))
(defconstant moon6c (* radians-per-degree 035999.05 julian-centuries-per-time-unit))
(defconstant moon7a (* radians-per-degree -0.11))
(defconstant moon7b (* radians-per-degree 186.6))
(defconstant moon7c (* radians-per-degree 966404.05 julian-centuries-per-time-unit))
(defun moon-position (ut) ; Input: universal time.
"Returns the eliptic longitude of the moon."
(let ((time (time-units-from-j2000.0 ut)))
(normalize-angle
(+ moon0
(* moon1 time)
(* moon2a (sin (+ moon2b (* moon2c time))))
(* moon3a (sin (+ moon3b (* moon3c time))))
(* moon4a (sin (+ moon4b (* moon4c time))))
(* moon5a (sin (+ moon5b (* moon5c time))))
(* moon6a (sin (+ moon6b (* moon6c time))))
(* moon7a (sin (+ moon7b (* moon7c time))))))))
(defun moon-and-sun-position (ut)
" => moon and sun position, mean-anomaly in radians."
(multiple-value-bind (sun-eliptic-longitude mean-anomaly)
(sun-position ut)
(let ((relative-moon-eliptic-longitude
(normalize-angle (- (moon-position ut)
sun-eliptic-longitude))))
(values relative-moon-eliptic-longitude
sun-eliptic-longitude
mean-anomaly))))
; Prints the Julian date and the position of the sun and moon.
(defun print-astro-time (&optional (ut (get-universal-time))
(stream *standard-output*))
(multiple-value-bind (relative-moon-eliptic-longitude sun-eliptic-longitude mean-anomaly)
(moon-and-sun-position ut)
(format stream
"~&Date JD~1,7,,$,
Moon phase ~1,2,6,$% (0.0% at new moon),
Sun phase ~1,2,6,$% (0.0% at spring equinox),
Sun anomaly ~1,2,6,$% (0.0% at perigee)."
(ut->jd ut)
(* (/ relative-moon-eliptic-longitude pi) 100.0)
(* (/ sun-eliptic-longitude pi) 100.0)
(* (/ mean-anomaly pi) 100.0))))
More information about the Comp.sources.unix
mailing list