Skip to content

Repository files navigation

Solar Maximum Engine ("Sol")

CI Coverage Docs Ephemeris accuracy crates.io

Live app: https://protonmatter.github.io/sol/

A deterministic, math-first solar-cycle / space-weather simulation engine and a layered learning + research web app built on top of it. Sol is Latin for the Sun — this is not a file explorer.

The design goal is a state-estimation engine, not a shader: a reduced solar-surface physics model produces immutable, versioned SolarState snapshots, and the renderer only ever consumes those snapshots. The UI never invents physical values.

Product north star: See the real Sun → understand what's happening on it → then see exactly what the model knows, how it knows it, and what it still can't claim.


Two layers

  1. Engine + data pipeline (Rust + Python)

    • Rust workspace: solar-core (reduced flux-transport model + diagonal Kalman-style assimilation primitive), solar-ingest, solar-cli, and solar-ephemeris — a zero-dependency VSOP2013 / ELP-MPP02 / TOP2013 ephemeris + topocentric sky engine, published on crates.io.
    • Python tooling for deterministic fixtures, public-data ingest (NOAA/SWPC, Helioviewer, JPL Horizons), snapshot-series generation, and validation.
    • Versioned JSON contracts: solar-state-snapshot.v2, ephemeris-snapshot.v2, observation-frame.v1, model-run-manifest.v1, operational-readiness.v1, plus series-manifest.v1. The snapshot shapes are each defined once — docs/solar-state-snapshot-v2.schema.json and docs/ephemeris-snapshot-v2.schema.json — and enforced across Rust, Python, and the browser via tools/validate_snapshot.py and tools/validate_ephemeris_snapshot.py.
  2. Web app (apps/web/) — a dependency-free, no-build static app that renders the snapshots (the redesign is merged; master is the only branch and deploys to GitHub Pages):

    • Real NASA SDO/HMI imagery as the observed photosphere, with the model's active-regions / magnetic field / confidence composited on top (observed-vs-model always labelled).
    • A real star catalogue everywhere stars appear: the naked-eye Hipparcos catalogue (8,867 stars, V ≤ 6.5 — true positions, parallax distances, B−V colours) backs the Solar-System view's sky, the Milky-Way view, and a light-year-scale Solar neighbourhood view; the on-device engine reduces 108 bright stars with proper motion for My Sky.
    • Three destinations (The Sun · My Sky · Solar System), with the Sun surface layered through progressive-disclosure drawers (layers & region inspection → space-weather impact → the model under the hood); a beginner "glance" by default, research depth on request.
    • Onboarding tour, a glossary of every science term, an interactive cycle stage rail, a time scrubber / playback of an idealized 11-year cycle, and a real butterfly diagram (sunspot latitude vs. time).
    • The real engine in the browser: solar-core is compiled to WebAssembly (crates/solar-wasm) and loaded as an ES module, so a "Run the engine live" control re-solves the actual model in ~2 ms — same validated snapshot contract, no Node/bundler.

See docs/STATUS.md for exactly what's done and what's left, and docs/WEB_REDESIGN_SPEC.md for the full redesign plan. A proposed next direction — a solar-system + local-sky (ephemeris) engine, "NASA Eyes meets SkyView, grounded in facts" — is specced in docs/SOLAR_SYSTEM_SPEC.md.


Quick start

Run the web app

# Serve it (required — the app is native ES modules, which browsers block over file://)
python -m http.server 8000 --directory apps/web
# then open http://localhost:8000

My Sky, Solar System, and the "Run the engine live" control run the real Rust engines compiled to WebAssembly. The .wasm binaries are not committed (they are built from source at deploy); build them once locally or those surfaces will explain they're unavailable and fall back:

rustup target add wasm32-unknown-unknown   # one-time
python tools/build_wasm.py                 # stages apps/web/pkg/*.wasm

The 3-D View draws its surfaces from three sources, in priority order:

  1. Real photographic maps (NASA Blue Marble + Solar System Scope CC-BY + USGS moon mosaics) for every body that has one. They are a COMMITTED baseline — deploys must not depend on a third-party host being up — and refreshed, not obtained, by:

    python tools/fetch_textures.py     # ~6 MB, refresh only
  2. Committed vector geography, which ships with the repository and needs no download: Earth's real coastlines, lakes and permanent ice (Natural Earth 1:110m, public domain) and the Moon's maria at their IAU/USGS coordinates. Generated by tools/generate_geography.py and rasterised in the browser, so every deployment shows real geography rather than noise.

  3. Procedural shaders for the bodies neither of the above covers — Mars and Mercury, whose catalogued features have real positions but no published albedo. See tools/ephemeris-data/geography/README.md for why guessing was rejected.

The view also draws the 21 major moons of Mars, Jupiter, Saturn, Uranus and Neptune from JPL Horizons elements (tools/ephemeris-data/moons/), validated in CI against Horizons state vectors to within 0.139° angular and 0.19% radial error across 11,985 interleaved checks. They are shown only from January 2021 through December 2030, the exact interval independently checked for every moon. Ten of them wear committed USGS global mosaics and all are shaded at their published geometric albedo; a transiting moon casts its real umbra/penumbra on the planet's disc, computed from physical positions (never the inflated display orbits), and a moon inside its planet's shadow cone goes eclipse-dark.

Regenerate the data the app reads (Python stdlib only)

# The live "today" snapshot — a deterministic ILLUSTRATIVE fixture (static bipole
# painting; its manifest says so). The real flux-transport engine is `solar-cli simulate`
# (below) and the in-browser WASM run.
python tools/generate_fixture_snapshot.py \
  --out apps/web/data/latest-state.json \
  --observations-out tests/fixtures/live-swpc-normalized.json --seed 42

# The solar-cycle series for timeline playback + the butterfly diagram
python tools/generate_series.py

# Validate everything
python tools/validate_snapshot.py apps/web/data/latest-state.json
python tools/validate_operational_readiness.py apps/web/data/latest-state.json
python tools/validate_web_static.py --root apps/web

Rust engine (requires a local Rust toolchain)

cargo test --workspace
cargo run -p solar-cli -- simulate --steps 48 --dt-hours 1 --seed 42 \
  --out apps/web/data/latest-state.json

Use the ephemeris as a library

The solar-ephemeris engine (zero-dependency positions + topocentric sky) is published on crates.io:

cargo add solar-ephemeris    # https://crates.io/crates/solar-ephemeris

See crates/solar-ephemeris/README.md for install and usage.

Full developer instructions: docs/INSTRUCTIONS.md.

Validate a change

Install the locked JavaScript validation tools, then run the fast cross-language contract:

npm ci --ignore-scripts
python tools/validate_sdlc.py
python tools/validate_docs.py
python tools/validate_ux_contract.py
PYTHONPATH=tools python -m unittest discover -s tests/python -p 'test_*.py' -v
npm test
python tools/typecheck_web.py
python tools/validate_web_static.py

The full CI additionally builds/tests Rust and WASM, runs the real app in Chromium with WebGL visual assertions, compares deterministic snapshots across Linux/macOS/Windows, and enforces at least 90% Rust, Python, and denominator-complete web line coverage. See CONTRIBUTING.md and docs/VALIDATION_PLAN.md.


Repository layout

apps/web/            Static web app (index.html, app.js, styles.css)
apps/web/data/       Snapshots the app reads: latest-state.json, feed-status.json,
                     latest-observations.json, series/ (cycle frames + manifest)
crates/              Rust workspace (solar-core, solar-ingest, solar-cli, …)
python/              Runnable prototype (synthetic solar maximum image)
tools/               Python generators, ingest, validators + shell helpers (watch-ci.sh)
docs/                Specs, requirements, RFCs/ADRs, UX, validation, status + operations
tests/               Fixtures and golden snapshots

Specification-driven development

Behavior starts with a stable requirement in docs/requirements.json, links to the governing specification, and ends with implementation, verification, and a named CI gate. Material contract, privacy, UX-workflow, architecture, or release-policy changes use the docs/rfcs/ process; durable architecture decisions use docs/adr/.

The lifecycle is documented in docs/SDLC.md, the standards boundary in docs/STANDARDS.md, and the progressive-disclosure/accessibility contract in docs/UX_GUIDELINES.md. CI validates all of them before the tested SHA can deploy.


Modes (engine)

Synthetic mode

A reproducible solar-maximum state from a solar-cycle activity index, a bipolar active-region birth model, differential rotation, surface flux transport, and probabilistic flare/CME hazard fields.

Assimilation mode (scalar activity, v1 scope)

solar-cli simulate --observations <report.json> corrects the scalar activity forecast with the daily pipeline's observed activity index through the diagonal Kalman-style update below — freshness-damped from the report's own staleness evaluation, and gated on attributable provenance (frames without a source are disclosed, not embedded). The snapshot is emitted in Assimilation mode with the evidence frames attached; the Br grid remains synthetic and says so — spatial assimilation waits for real magnetogram frames (ROADMAP v0.4). Unusable observations leave the run Synthetic with a warning saying why; degraded inputs never inflate the mode. See ADR 0005.

forecast  x_f = M(x_t)
residual  r   = y - H(x_f)
gain      K   = P_f / (P_f + R)
analysis  x_a = x_f + freshness_gain * K * r
variance  P_a = (1 - K) * P_f

Operational boundary (read this)

This app is operational for deterministic research and learning workflows only. It is not operational space-weather forecasting. operational_readiness.space_weather_operational stays false until calibrated physical units, historical validation, comparison against operational SWPC products, adapter-freshness monitoring, alerting, and approval evidence exist. Normalized magnetic values are labelled normalized — never asserted as Gauss/Mx.

Public-method anchors

Claims are anchored to public, inspectable products: NOAA SWPC, Helioviewer, NASA SDO browse imagery, JPL/NAIF SPICE, and NN/g progressive disclosure. No SpaceX equivalence or proprietary internal JPL/SpaceX algorithm is claimed. See docs/STANDARDS.md for exact IETF, W3C, NIST, OWASP, and usability-guidance scope; no blanket certification or conformance is claimed.

License

MIT OR Apache-2.0.

About

Deterministic solar-cycle engine + arcsecond-class ephemeris (Rust→WASM), rendered as a no-build web app — validated weekly against JPL Horizons

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages