Astro.Lunar.Eclipse (Astro v2.11.0)

Copy Markdown View Source

Finds lunar eclipses and computes their circumstances.

This module is the implementation behind Astro.lunar_eclipse_at_or_after/2 and Astro.lunar_eclipse_before/2, and works in moments (see Astro.Time.moment/0).

The Earth's shadow

The Earth casts two shadows away from the Sun. The umbra is the cone in which the Sun is wholly hidden by the Earth; the penumbra is the wider cone in which it is partly hidden. At the Moon's distance both are circles centred on the shadow axis, the point opposite the Sun, and a lunar eclipse is the Moon passing through them. It can only happen at a full moon, and only near a node of the Moon's orbit, because otherwise the Moon passes north or south of both circles.

Seen from the centre of the Earth, the radii of the two circles are

penumbra  Rp = 1.01 πm + ss + πs
umbra     Ru = 1.01 πm − ss + πs

where πm and πs are the Moon's and the Sun's equatorial horizontal parallaxes, the angles the Earth's equatorial radius subtends at each, and ss is the Sun's angular semi-diameter. The factor 1.01 is Danjon's enlargement of the shadows for the Earth's atmosphere, a layer about 75 km deep that stops sunlight as the solid Earth does, 1 + 1/85 − 1/594, the last term for the Earth's flattening at 45°. This is the convention of NASA's eclipse catalogues. The older almanac convention, Chauvenet's, multiplies the radii by 1.02 instead,

penumbra  Rp = 1.02 (0.99834 πm + ss + πs)
umbra     Ru = 1.02 (0.99834 πm − ss + πs)

which makes the umbral magnitude about 0.006 larger and can make an eclipse at the limit total where Danjon's makes it partial.

Greatest eclipse, gamma and magnitude

The Moon's angular distance σ from the shadow axis is least at greatest eclipse. Gamma is that least distance in equatorial radii of the Earth, positive when the Moon passes north of the axis. The penumbral and umbral magnitudes are the fractions of the Moon's diameter inside each shadow at greatest eclipse,

penumbral magnitude = (Rp + sm − σ) / 2sm
umbral magnitude    = (Ru + sm − σ) / 2sm

where sm is the Moon's angular semi-diameter. An eclipse is total when the umbral magnitude is at least 1, partial when it is between 0 and 1, and penumbral when only the penumbral magnitude is positive.

The contacts

The eclipse begins when the Moon's limb first touches the penumbra (P1) and ends when it leaves it (P4). A partial or total eclipse has two more contacts with the umbra, U1 and U4, and a total eclipse two more, U2 and U3, between which the Moon is wholly inside the umbra. Each is the instant σ equals a shadow's radius plus or minus sm, found by bisection either side of greatest eclipse.

The contacts happen at the same instants wherever the Moon is seen; Astro.Lunar.Eclipse.Local gives the Moon's altitude at each from a place, and whether the eclipse is seen there.

Positions

The Sun's and the Moon's apparent geocentric positions and distances are those of Astro.sun_position_at/1 and Astro.moon_position_at/1: from the JPL ephemeris where the loaded kernel covers the moment, and from the analytical series elsewhere.

Summary

Types

The kind of lunar eclipse: the Moon passes through the penumbra only, partly into the umbra, or wholly into it.

The convention for enlarging the Earth's shadows: Danjon's, used by NASA's catalogues, or Chauvenet's, the older almanac convention.

t()

A lunar eclipse. Every instant is a UTC DateTime.t/0; the umbral contacts are nil for an eclipse that does not reach them, and the Saros series is numbered as NASA numbers it (Astro.Saros).

Functions

Returns the circumstances of the first lunar eclipse whose greatest eclipse is at or after a moment.

Returns the circumstances of the last lunar eclipse whose greatest eclipse is before a moment.

Returns the geometry of the Earth's shadow and the Moon at a moment.

Types

eclipse_type()

@type eclipse_type() :: :penumbral | :partial | :total

The kind of lunar eclipse: the Moon passes through the penumbra only, partly into the umbra, or wholly into it.

shadow()

@type shadow() :: :danjon | :chauvenet

The convention for enlarging the Earth's shadows: Danjon's, used by NASA's catalogues, or Chauvenet's, the older almanac convention.

t()

@type t() :: %Astro.Lunar.Eclipse{
  gamma: float(),
  greatest: DateTime.t(),
  partial_begins: DateTime.t() | nil,
  partial_ends: DateTime.t() | nil,
  penumbral_begins: DateTime.t(),
  penumbral_ends: DateTime.t(),
  penumbral_magnitude: float(),
  saros: integer(),
  total_begins: DateTime.t() | nil,
  total_ends: DateTime.t() | nil,
  type: eclipse_type(),
  umbral_magnitude: float()
}

A lunar eclipse. Every instant is a UTC DateTime.t/0; the umbral contacts are nil for an eclipse that does not reach them, and the Saros series is numbered as NASA numbers it (Astro.Saros).

Functions

eclipse_at_or_after(t, shadow)

@spec eclipse_at_or_after(Astro.Time.moment(), shadow()) ::
  {:ok, map()} | {:error, :no_eclipse}

Returns the circumstances of the first lunar eclipse whose greatest eclipse is at or after a moment.

Arguments

  • t is a Astro.Time.moment/0 within 50,000 years of J2000.

  • shadow is the enlargement convention, :danjon or :chauvenet.

Returns

  • {:ok, circumstances}, a map with the keys of t/0, every instant a moment and every missing contact nil.

  • {:error, :no_eclipse} if none is found within 13 lunations, which does not happen.

Examples

iex> {:ok, eclipse} = Astro.Lunar.Eclipse.eclipse_at_or_after(739_600.0, :danjon)
iex> {eclipse.type, Float.round(eclipse.umbral_magnitude, 3)}
{:total, 1.178}

eclipse_before(t, shadow)

@spec eclipse_before(Astro.Time.moment(), shadow()) ::
  {:ok, map()} | {:error, :no_eclipse}

Returns the circumstances of the last lunar eclipse whose greatest eclipse is before a moment.

Arguments

  • t is a Astro.Time.moment/0 within 50,000 years of J2000.

  • shadow is the enlargement convention, :danjon or :chauvenet.

Returns

  • {:ok, circumstances}, a map with the keys of t/0, every instant a moment and every missing contact nil.

  • {:error, :no_eclipse} if none is found within 13 lunations, which does not happen.

Examples

iex> {:ok, eclipse} = Astro.Lunar.Eclipse.eclipse_before(739_700.0, :danjon)
iex> eclipse.type
:total

geometry(t, shadow)

@spec geometry(Astro.Time.moment(), shadow()) :: %{
  distance: float(),
  penumbra: float(),
  umbra: float(),
  semi_diameter: float(),
  gamma: float()
}

Returns the geometry of the Earth's shadow and the Moon at a moment.

Arguments

Returns

  • A map with these keys, every angle in degrees:
    • :distance — the Moon's angular distance from the shadow axis, σ.

    • :penumbra and :umbra — the radii of the shadows at the Moon, Rp and Ru.

    • :semi_diameter — the Moon's angular semi-diameter, sm.

    • :gamma — σ in equatorial radii of the Earth at the Moon's distance, positive when the Moon is north of the axis.

Examples

iex> geometry = Astro.Lunar.Eclipse.geometry(739_689.2917, :danjon)
iex> Float.round(geometry.gamma, 3)
0.349