Add an Interpolated algorithm for fast repeated evaluation - #117
Conversation
Pure code motion: _spa_topocentric now holds the hour angle, parallax, elevation, and azimuth steps so another algorithm can reconstruct positions from a given geocentric state through the exact same code. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Interpolated wraps SPA with cubic B-splines of its geocentric right ascension, declination, radius vector, and equation of the equinoxes on a uniform time grid, then reconstructs topocentric positions through the shared _spa_topocentric path. Sidereal time stays closed form, so the only error is the spline error of four smooth series, about 1e-10 degrees at the default one hour step, and one interpolant serves every observer. Scalar evaluation is allocation free and about 10x faster than direct SPA. Construction lives in a new Interpolations.jl package extension; the struct, evaluation, out_of_range handling (:error or :fallback), and the finite difference solar_rate live in the core package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Adds a guide with executed construction, accuracy, benchmark, and solar_rate examples, registers it in the docs pages, and lists the wrapper on the positioning page with docstring entries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Benchmark Results (Julia vlts)Time benchmarks
Memory benchmarks
|
Benchmark Results (Julia vpre)Time benchmarks
Memory benchmarks
|
Benchmark Results (Julia v1)Time benchmarks
Memory benchmarks
|
The block test asserts the interpolant is a drop in replacement for the wrapped SPA with both NoRefraction and DefaultRefraction, and the guide gains a section on using Interpolated as a high accuracy forcing, including span sizing and the :fallback recommendation inside solvers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
|
Added ModelingToolkit coverage in 7a0dccb: The block default stays |
Measured against direct SPA the interpolation error crosses SPA's own 3e-4 degree accuracy between 3 and 5 day steps, so steps above 3 days now warn at construction. The docstring lists the measured error at several steps and the 30 day hard cap stays as the unwrap safety limit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #117 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 18 19 +1
Lines 683 735 +52
=========================================
+ Hits 683 735 +52 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The step now prints as 1 hour instead of 3600000 milliseconds. New tests hit the extension missing stub through a non SPA algorithm and the ApparentSolPos result type through the default refraction batch path, which were the three uncovered lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Adds cross references at the first prose mention of Observer, the five algorithms, DefaultRefraction, and PSA and SPA in the new MTK section. The README Quadmath footnote becomes a one line pointer to the precision guide, which keeps the full explanation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Explains that saveat controls recording rather than stepping, shows the exact post hoc query of observed sun angles through the solution object, and covers the two error controller failure modes with a runnable example: sunrise and sunset from transit_sunrise_sunset as d_discontinuities, and an insolation quadrature state that puts the forcing in the error budget. Closes with the reference solve check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
The guide is not in a stable release yet, so the stable URL 404s in the link checker. The dev URL resolves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
A small autodiff guide section runs the same gradient through the ForwardDiff and finite difference backends and prints their agreement, demonstrating that backend agnostic tooling works without any AD hooks in the package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wg3j4XXUooMvDgUpRajxTq
Summary
Dense time series are the common case in PV work, and SPA spends about 2 µs per query. This PR adds an
Interpolatedwrapper that precomputes cubic B-splines of SPA's geocentric solar coordinates over a fixed time span and reconstructs topocentric positions analytically, giving a ~10x speedup at ~1e-10° accuracy with zero allocations per query.Design in brief:
mean_sidereal_time, and the topocentric half runs through_spa_topocentric, extracted verbatim from SPA in the first commit, so both paths share the exact same code (the:fallbacktest asserts bit equality).out_of_rangehandling, andsolar_ratelive in the core package with no new hard dependencies. Constructing without the extension loaded gives a clear error.out_of_range = :error(default) throws on queries outsidetspanbecause a silent fallback would be a hard to notice 10x slowdown;:fallbackopts into calling the wrapped SPA instead.solar_ratereturns d(azimuth)/dt and d(elevation)/dt in degrees per hour via a wrap aware central finite difference over the fast path, for tracker control and slew rate limits.Measured (Ryzen 7 8845HS, 16 threads)
Hour(1)solar_ratevs SPA finite differenceDocs
New guide
guides/interpolation.mdwith executed construction, accuracy, benchmark, andsolar_rateexamples, plus docstring entries and a note on the positioning page.Test plan
test/extensions/test-interpolations.jl: accuracy vs direct SPA over 1 y and 10 y spans (measured maxima logged), refraction parity, out of range:error/:fallback, batch/in-place/table/OhMyThreads paths, ZonedDateTime tspan and queries,solar_ratevs finite difference of direct SPA, zero allocation and@inferredchecks,Observer{Float32}result typePkg.test()green locally, including Aqua, JET, and type stabilityjulia --project=docs docs/make.jlbuilds clean🤖 Generated with Claude Code