Skip to content

JuliaAstro/SolarPosition.jl

Repository files navigation

Gemini_Generated_Image_mctn28mctn28mctn

SolarPosition.jl

Stable Development documentation

Test workflow status Coverage Lint workflow Status Docs workflow Status Aqua QA tested with JET.jl

SolarPosition.jl provides a simple, unified interface to a collection of validated solar position algorithms written in pure, performant julia.

Solar positioning algorithms are commonly used to calculate the solar zenith and azimuth angles, which are essential for various applications where the sun is important, such as:

  • Solar energy systems
  • Building design
  • Climate studies
  • Astronomy

Acknowledgement

This package is based on the work done by researchers in the field of solar photovoltaics in the packages solposx and pvlib-python. In particular the positioning and refraction methods have been adapted from solposx, while the SPA algorithm and the deltat calculation are ported from pvlib-python. These packages also provide validation data necessary to ensure correctness of the algorithm implementations.

Example Usage

julia> using SolarPosition, Dates, TimeZones

# define observer location (latitude, longitude, altitude in meters)
julia> obs = Observer(52.35888, 4.88185, 100.0)  # Van Gogh Museum, Amsterdam
Observer(latitude=52.35888°, longitude=4.88185°, altitude=100.0m)

julia> tz = TimeZone("Europe/Brussels")
Europe/Brussels (UTC+1/UTC+2)

# a few hours of timestamps
julia> times = collect(DateTime(2023, 6, 21, 10):Hour(1):DateTime(2023, 6, 21, 15));

# compute solar positions for all timestamps
julia> positions = solar_position(obs, times)
6-element StructArray(::Vector{Float64}, ::Vector{Float64}, ::Vector{Float64}) with eltype SolPos{Float64}:
 SolPos(azimuth=136.1908215897601°, elevation=55.13208390809107°, zenith=34.86791609190893°)
 SolPos(azimuth=160.3753655770986°, elevation=59.974081481305134°, zenith=30.025918518694862°)
 SolPos(azimuth=188.3992597996431°, elevation=60.87918930278924°, zenith=29.120810697210757°)
 SolPos(azimuth=214.62987222053295°, elevation=57.493462259959394°, zenith=32.5065377400406°)
 SolPos(azimuth=235.5258846451899°, elevation=50.992647293443966°, zenith=39.007352706556034°)
 SolPos(azimuth=251.77304757136397°, elevation=42.790197455865076°, zenith=47.209802544134924°)

Sunrise and Sunset Calculations

Calculate sunrise, sunset, and solar noon for a specific date with timezone:

julia> result = transit_sunrise_sunset(obs, ZonedDateTime(2023, 6, 21, tz))
TransitSunriseSunset{ZonedDateTime}(
    transit=2023-06-21T13:42:15+02:00,
    sunrise=2023-06-21T05:18:05+02:00,
    sunset=2023-06-21T22:06:24+02:00
)

Find the next sunrise from a specific time in UTC:

julia> next_sunrise(obs, DateTime(2023, 6, 21, 12, 30))
2023-06-22T03:18:19

Find the next sunset in UTC:

julia> next_sunset(obs, DateTime(2023, 6, 21, 12, 30))
2023-06-21T20:06:24

Solar positioning algorithms

Here we provide an overview of the solar positioning algorithms currently implemented in SolarPosition.jl. Each algorithm is described with its reference paper, claimed accuracy and implementation status.

Algorithm Reference Accuracy Default Refraction Status
PSA Blanco-Muriel et al. ±0.0083° None
NOAA Global Monitoring Laboratory ±0.0167° HUGHES
Walraven Walraven, 1978 ±0.0100° None
USNO U.S. Naval Observatory ±0.0500° None
SPA Reda & Andreas, 2004 ±0.0003° Built-in

Numeric precision

The computation runs at the precision of the Observer{T} element type, so Observer{Float32}(45.0, 10.0) computes in Float32 and Observer{BigFloat}(45.0, 10.0) computes in BigFloat. A magnitude-safe time base keeps full intra-day resolution at every precision instead of riding on the ~2.45e6 Julian Date. Float64 is the default and the reference. Float32 trades a little accuracy for a modest speedup and stays within the algorithms' own claimed accuracy. Float128 from Quadmath.jl and BigFloat give genuine extended precision at a large runtime cost. Float16 is not supported because the algorithm coefficients overflow its range.

The table below lists the maximum error against a 256-bit BigFloat reference and the runtime relative to Float64, measured over a grid of dates from 2015 to 2035 and latitudes from 70°N to 60°S:

Algorithm Float32 error Float32 runtime Float64 error Float128 error Float128 runtime BigFloat runtime
PSA 0.011° 1.3× faster 1.3e-11° 7.1e-30° 93× slower 500× slower
NOAA 0.0019° 1.2× faster 3.5e-12° broken1 n/a 330× slower
Walraven 0.0040° 1.3× faster 6.4e-12° 8.6e-30° 74× slower 400× slower
USNO 0.0036° 1.2× faster 9.5e-12° broken1 n/a 300× slower
SPA 0.012° 1.5× faster 1.8e-11° 1.1e-29° 118× slower 330× slower

Refraction correction algorithms

Atmospheric refraction correction algorithms available in SolarPosition.jl.

Algorithm Reference Atmospheric Parameters Status
HUGHES Hughes, 1985 Pressure, Temperature
ARCHER Archer et al., 1980 None
BENNETT Bennett, 1982 Pressure, Temperature
MICHALSKY Michalsky, 1988 None
SG2 Blanc & Wald, 2012 Pressure, Temperature
SPA Reda & Andreas, 2004 Pressure, Temperature

Extensions

SolarPosition.jl provides optional extensions that are automatically loaded when you import the corresponding packages:

Extension Trigger Package Features
Makie Makie.jl Plotting recipes for solar position visualization
OhMyThreads OhMyThreads.jl Parallel computation of solar positions
ModelingToolkit ModelingToolkit.jl Symbolic solar position models for simulations

How to Cite

If you use SolarPosition.jl in your work, please cite using the reference given in CITATION.cff.

Contributing

If you want to make contributions of any kind, please first that a look into our contributing guide directly on GitHub or the contributing page on the website

Footnotes

  1. Quadmath.jl v1.0.1 implements rem with round-to-nearest instead of truncated semantics, which breaks the degree reduction in Base's sind and cosd, so NOAA and USNO give wrong results at Float128 until that is fixed upstream. 2