> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plantpredict.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Solar Position Algorithm

export const DeclinationCap = () => <Tooltip tip="Angular distance of the sun north or south of the celestial equator (±23.45°).">
    Declination
  </Tooltip>;

export const RightAscensionCap = () => <Tooltip tip="Angular distance measured eastward along the celestial equator from the vernal equinox.">
    Right ascension
  </Tooltip>;

export const EquatorialReferenceFrame = () => <Tooltip tip="Coordinate system based on earth's equatorial plane.">
    equatorial reference frame
  </Tooltip>;

export const EclipticReferenceFrame = () => <Tooltip tip="Coordinate system based on the ecliptic plane (earth's orbital plane).">
    ecliptic reference frame
  </Tooltip>;

export const GASTFull = () => <Tooltip tip="earth's rotational position relative to the true vernal equinox, measured at Greenwich.">
    Greenwich Apparent Sidereal Time
  </Tooltip>;

export const LocalHourAngle = () => <Tooltip tip="Angular distance of the sun from the observer's meridian; measures how far the sun has traveled past local noon.">
    local hour angle
  </Tooltip>;

export const OrbitalPlane = () => <Tooltip tip="The flat plane in which earth orbits the sun; defines the ecliptic.">
    orbital plane
  </Tooltip>;

export const EquatorialCoordinates = () => <Tooltip tip="Coordinate system based on earth's equatorial plane with right ascension and declination.">
    equatorial coordinates
  </Tooltip>;

export const VernalEquinox = () => <Tooltip tip="The point where the sun crosses the celestial equator moving northward (around March 20); zero point for celestial longitude.">
    vernal equinox
  </Tooltip>;

export const AstronomicalUnits = () => <Tooltip tip="Mean earth-sun distance, approximately 149.6 million km.">
    astronomical units
  </Tooltip>;

export const Ecliptic = () => <Tooltip tip="The plane of earth's orbit around the sun; the apparent path of the sun across the sky over a year.">
    ecliptic
  </Tooltip>;

export const VSOP87 = () => <Tooltip tip="Planetary theory providing high-accuracy positions of planets; used in SPA for earth's heliocentric coordinates.">
    VSOP87
  </Tooltip>;

export const EphemerisTimeCap = () => <Tooltip tip="Uniform time scale based on celestial mechanics, independent of earth's variable rotation.">
    Ephemeris Time
  </Tooltip>;

export const UniversalTimeCap = () => <Tooltip tip="Time standard based on earth's rotation, approximating mean solar time at the Prime Meridian.">
    Universal Time
  </Tooltip>;

export const TerrestrialTimeCap = () => <Tooltip tip="Uniform time scale based on celestial mechanics, independent of earth's variable rotation.">
    Terrestrial Time
  </Tooltip>;

export const ParallaxCap = () => <Tooltip tip="Apparent shift in sun's position due to observer being on earth's surface rather than at its center.">
    Parallax
  </Tooltip>;

export const Parallax = () => <Tooltip tip="Apparent shift in sun's position due to observer being on earth's surface rather than at its center.">
    parallax
  </Tooltip>;

export const Refraction = () => <Tooltip tip="Bending of light as it passes through earth's atmosphere, making the sun appear higher than its true position.">
    refraction
  </Tooltip>;

export const Obliquity = () => <Tooltip tip="Angle between earth's rotational axis and its orbital plane (~23.44°).">
    obliquity
  </Tooltip>;

export const Julian = () => <Tooltip tip="Refers to Julian Day Number: continuous count of days since January 1, 4713 BC.">
    Julian
  </Tooltip>;

export const AberrationCap = () => <Tooltip tip="Apparent displacement of a celestial object due to the finite speed of light and earth's orbital motion.">
    Aberration
  </Tooltip>;

export const Aberration = () => <Tooltip tip="Apparent displacement of a celestial object due to the finite speed of light and earth's orbital motion.">
    aberration
  </Tooltip>;

export const NutationCap = () => <Tooltip tip="Short-period oscillations in earth's axis caused by gravitational torques from sun and moon.">
    Nutation
  </Tooltip>;

export const Nutation = () => <Tooltip tip="Short-period oscillations in earth's axis caused by gravitational torques from sun and moon.">
    nutation
  </Tooltip>;

export const Heliocentric = () => <Tooltip tip="Measured from the center of the sun; describes earth's position in its orbit.">
    heliocentric
  </Tooltip>;

export const Azimuth = () => <Tooltip tip="Horizontal angle measured clockwise from north; applies to sun direction or surface orientation.">
    azimuth
  </Tooltip>;

export const Zenith = () => <Tooltip tip="Angle between the local vertical and the sun (0° = overhead, 90° = horizon).">
    zenith
  </Tooltip>;

export const Geocentric = () => <Tooltip tip="Measured from earth's center, as opposed to topocentric (from a point on earth's surface).">
    geocentric
  </Tooltip>;

export const Topocentric = () => <Tooltip tip="Measured from a specific point on earth's surface, as opposed to geocentric (from earth's center).">
    topocentric
  </Tooltip>;

## Summary

PlantPredict implements the **NREL Solar Position Algorithm (SPA)**, a high-accuracy algorithm for computing the sun's apparent position in the sky. The algorithm achieves uncertainties of ±0.0003° for the period −2000 to 6000, making it suitable for precision solar tracking and energy modeling.

The implementation follows the NREL Technical Report TP-560-34302 (Reda & Andreas, 2004) with minor simplifications noted below. Due to the complexity of the algorithm, only its outline is described here for the sake of concision. A full description can be found in the NREL technical report mentioned above.

## Inputs

| Name                        | Symbol    | Units    | Description                                      |
| --------------------------- | --------- | -------- | ------------------------------------------------ |
| **UTC Date–Time**           | —         | datetime | Coordinated Universal Time                       |
| **Latitude**                | $\varphi$ | degrees  | Observer latitude (+north, −south)               |
| **Longitude**               | $\lambda$ | degrees  | Observer longitude (+east, −west)                |
| **Altitude**                | $h$       | m        | Observer elevation above sea level               |
| **Ambient Air Temperature** | $T_a$     | °C       | Ambient temperature (for refraction correction)  |
| **Pressure**                | $P$       | hPa      | Atmospheric pressure (for refraction correction) |

## Outputs

| Name                             | Symbol     | Units   | Description                                          |
| -------------------------------- | ---------- | ------- | ---------------------------------------------------- |
| **Apparent Solar Zenith Angle**  | $\theta_z$ | degrees | Angle from vertical to sun, corrected for refraction |
| **Apparent Solar Azimuth Angle** | $\gamma_s$ | degrees | Horizontal angle from North (clockwise)              |

***

## Detailed Description

The SPA proceeds through these major steps:

### 1. Time Calculations

Convert the input UTC datetime to <Julian /> Day (JD) and Julian Ephemeris Day (JDE) for planetary calculations.
SPA intentionally uses two time scales:

* <TerrestrialTimeCap /> (TT), also referred to as <EphemerisTimeCap /> (ET), a uniform time scale independent of variations in earth rotation speed, used for orbital mechanics. In this time scale, a day is always exactly 24 hours.
* <UniversalTimeCap /> (UT, approximated here by UTC), a time scale synchronized to the earth's variable rotation speed. In this time scale, a day is not always exactly 24 hours.

TT and, thus, JDE are used for the relative positions of the sun and earth independent of the rotation of earth. UT and, thus, JD are used to calculate the position of the sun in the sky from the point of view of an observer located on the (rotating) surface of the earth. The offset between these two timescales is ΔT = TT − UT and slowly varies over time (\<1 second per year).

**PlantPredict uses a fixed ΔT of 67 seconds** (corresponding to \~2013–2014). This approximation introduces negligible error for typical PV modeling horizons (\<30 seconds difference over a 30-year period).

### 2. Earth's Heliocentric Position

Calculate earth's position relative to the sun using the **<VSOP87 /> theory**—a set of polynomial and periodic series that model planetary orbits. This yields:

* **Heliocentric longitude** $L$ — earth's angular position in its orbital plane
* **Heliocentric latitude** $B$ — earth's position above/below the <Ecliptic />
* **Radius vector** $R$ — earth-sun distance in <AstronomicalUnits />

### 3. Geocentric Sun Position

Invert the <Heliocentric /> earth position to get the <Geocentric /> sun position (as seen from earth's center). This is a simple coordinate transformation: add 180° to longitude ($\lambda_{\text{ecl}} = L + 180°$) and negate latitude ($\beta_{\text{ecl}} = -B$).

### 4. Nutation and Obliquity

<NutationCap /> is the periodic wobble of earth's rotational axis due to gravitational torques from the sun and moon. The algorithm computes:

* **Nutation in longitude** $\Delta\psi$ — change in direction of the tilt of the rotational axis, affects the sun's apparent east-west position
* **Nutation in obliquity** $\Delta\epsilon$ — change in magnitude of the tilt of the rotational axis, affects the tilt of earth's equator relative to the ecliptic

The **true <Obliquity />** $\epsilon$ (tilt of earth's axis, \~23.4°) is then computed by adding nutation in obliquity to the mean obliquity: $\epsilon = \epsilon_0 + \Delta\epsilon$. The nutation in longitude is used to correct the sun apparent coordinates, as detailed below.

### 5. Aberration

<AberrationCap /> ($\Delta\tau$) is the apparent shift in celestial positions caused by earth's orbital velocity (\~30 km/s) combined with the finite speed of light—it takes approximately 8 minutes for light from the sun to reach earth. Light arriving from the sun appears slightly displaced in the direction of earth's motion. In other words, in the earth reference frame, once light from the sun reaches the earth surface, the sun has already moved from where that light was cast. The correction is small (\~20 arcseconds) but significant for high-precision applications.

### 6. Apparent Sun Coordinates

The **apparent sun longitude** is computed by adding <Nutation /> in longitude ($\Delta\psi$) and <Aberration /> ($\Delta\tau$) to the geocentric longitude: $\lambda'_{\text{ecl}} = \lambda_{\text{ecl}} + \Delta\psi + \Delta\tau$. The nutation correction accounts for the shift of the <VernalEquinox />—the zero point for measuring celestial longitude. Because the equinox is defined as the intersection of the ecliptic and equator, and nutation wobbles the equator, the equinox shifts along the ecliptic. Adding $\Delta\psi$ ensures we measure the sun's position relative to the "true equinox" (actual position) rather than the "mean equinox" (averaged position). The sun latitude does not need correction ($\beta'_{\text{ecl}} = \beta_{\text{ecl}}$).

The apparent ecliptic coordinates (longitude $\lambda'_{\text{ecl}}$, latitude $\beta'_{\text{ecl}}$) are then converted to **<EquatorialCoordinates />** using the true <Obliquity /> $\epsilon$. This transformation rotates from the <EclipticReferenceFrame /> (based on earth's <OrbitalPlane />) to the <EquatorialReferenceFrame /> (based on earth's equator). Both nutation components affect the final result: $\Delta\psi$ is incorporated in the apparent longitude, while $\Delta\epsilon$ enters through the true obliquity. The resulting equatorial coordinates are:

* **<RightAscensionCap />** $\alpha$ — celestial "longitude" measured along the equator
* **<DeclinationCap />** $\delta$ — celestial "latitude" above/below the equator

### 7. Local Hour Angle

Calculate the **<LocalHourAngle />** $H$, which measures how far the sun has traveled past the observer's meridian. It is obtained from the **<GASTFull /> (GAST)** corrected for the observer's longitude $\lambda$ and sun's right ascension $\alpha$: $H = \text{GAST} + \lambda - \alpha$.

GAST measures earth's rotational position relative to the stars (specifically, the true vernal equinox), not the sun. A sidereal day (\~23h 56m 4s)—one full 360° rotation relative to the stars—is shorter than a solar day (24h) because earth's orbital motion causes the sun to drift \~1° westward each day, requiring an extra \~4 minutes of rotation to bring the sun back to the same position. GAST is computed from UTC, corrected for the nutation-induced shift of the true equinox (zero reference).

### 8. Topocentric Correction (Parallax)

Convert from <Geocentric /> (earth-center) to <Topocentric /> (observer location) coordinates. <ParallaxCap /> accounts for the observer being on earth's surface rather than at its center—a shift of up to \~9 arcseconds depending on the sun's position and observer location.

The correction adjusts the equatorial coordinates:

* **Hour angle**: $H' = H - \Delta H$ (topocentric hour angle)
* **Declination**: $\delta' = \delta + \Delta\delta$ (topocentric declination)

These corrections depend on:

* Observer's latitude $\varphi$ and altitude $h$ (determines distance from earth's center)
* Local hour angle $H$ (sun's position relative to observer's meridian)
* earth-sun distance $R$ (closer sun = larger parallax)

### 9. Zenith and Azimuth Angles

Calculate the **zenith angle** $\theta_z$ and **azimuth angle** $\gamma_s$ in topocentric coordinates by transforming from topocentric equatorial coordinates ($\delta'$, $H'$) to the local horizon frame using the observer's latitude $\varphi$.

Then apply the atmospheric **<Refraction />** correction to the zenith angle—the atmosphere bends light, making the sun appear higher than it geometrically is (lower zenith angle).

Finally, convert azimuth to PlantPredict's convention, measuring azimuth **clockwise from North**: 0° = North, 90° = East, 180° = South, 270° = West

***

### Implementation Notes

PlantPredict's implementation follows the NREL SPA algorithm. Key implementation details:

| Aspect           | Implementation                                        |
| ---------------- | ----------------------------------------------------- |
| VSOP87 tables    | Full tables from NREL TP-560-34302 (Tables A4.2–A4.3) |
| Nutation terms   | 63-term series from NREL TP-560-34302 (Table A4.1)    |
| ΔT value         | Fixed at 67 seconds                                   |
| Refraction model | Bennett formula with pressure/temperature adjustment  |
| Valid date range | −2000 to 6000 (accuracy ±0.0003°)                     |

***

## References

* Reda, I., & Andreas, A. (2004). *Solar Position Algorithm for Solar Radiation Applications.* NREL Technical Report NREL/TP-560-34302. DOI: [10.2172/15003974](https://doi.org/10.2172/15003974)
* Meeus, J. (1998). *Astronomical Algorithms* (2nd ed.). Willmann-Bell, Inc.
* Bretagnon, P., & Francou, G. (1988). *Planetary theories in rectangular and spherical variables. VSOP 87 solutions.* Astronomy and Astrophysics, 202, 309–315.
* Bennett, G. G. (1982). *The Calculation of Astronomical Refraction in Marine Navigation.* Journal of Navigation, 35(2), 255–259. DOI: [10.1017/S0373463300022037](https://doi.org/10.1017/S0373463300022037)
