New equatorial type (24 bytes: RA/Dec/distance) captures apparent coordinates of date — what the observation pipeline computes at precession step 3 but was discarding before hour angle conversion. Matches telescope GoTo mount conventions. 24 new SQL functions (82 → 106 total): - equatorial type I/O + 3 accessors (eq_ra, eq_dec, eq_distance) - Satellite RA/Dec: eci_to_equatorial (topocentric), eci_to_equatorial_geo (geocentric) - Solar system equatorial: planet/sun/moon/small_body_equatorial - Atmospheric refraction: Bennett (1982) with domain clamp at -1 deg - Refracted pass prediction: predict_passes_refracted (horizon at -0.569 deg) - Stellar proper motion: star_observe_pm, star_equatorial_pm (Hipparcos/Gaia convention) - Light-time correction: planet/sun/small_body_observe_apparent, *_equatorial_apparent - DE equatorial variants: planet_equatorial_de, moon_equatorial_de Also includes v0.8.0 orbital_elements type (MPC parser, small_body_observe), GiST 0-based indexing fix, llms.txt updates, and doc improvements. All 18 regression suites pass. Zero build warnings (GCC + Clang).
140 lines
6.8 KiB
SQL
140 lines
6.8 KiB
SQL
-- refraction regression tests
|
|
--
|
|
-- Tests atmospheric refraction (Bennett 1982), pressure/temperature
|
|
-- correction, apparent elevation, and refracted pass prediction.
|
|
|
|
\set boulder '''40.015N 105.270W 1655m'''::observer
|
|
|
|
-- ISS TLE for pass prediction tests (inline in CTEs below)
|
|
|
|
-- ============================================================
|
|
-- Test 1: Refraction at horizon (0 deg) ~ 0.57 deg
|
|
-- Bennett: R = 1/tan(0 + 7.31/4.4) arcmin ~ 34.5 arcmin ~ 0.575 deg
|
|
-- ============================================================
|
|
SELECT 'refr_horizon' AS test,
|
|
round(atmospheric_refraction(0.0)::numeric, 2) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 2: Refraction at 30 deg ~ 0.03 deg
|
|
-- ============================================================
|
|
SELECT 'refr_30deg' AS test,
|
|
round(atmospheric_refraction(30.0)::numeric, 3) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 3: Refraction at zenith (90 deg) ~ 0 deg
|
|
-- ============================================================
|
|
SELECT 'refr_zenith' AS test,
|
|
round(atmospheric_refraction(90.0)::numeric, 4) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 4: Refraction at 10 deg ~ 0.09 deg
|
|
-- ============================================================
|
|
SELECT 'refr_10deg' AS test,
|
|
round(atmospheric_refraction(10.0)::numeric, 3) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 5: Domain guard - refraction at -5 deg should return 0
|
|
-- (below -1 deg validity range)
|
|
-- ============================================================
|
|
SELECT 'refr_below_range' AS test,
|
|
atmospheric_refraction(-5.0) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 6: Domain guard - refraction at -10 deg returns 0 (no NaN)
|
|
-- ============================================================
|
|
SELECT 'refr_deep_neg' AS test,
|
|
atmospheric_refraction(-10.0) AS refr_deg,
|
|
atmospheric_refraction(-10.0) = atmospheric_refraction(-10.0) AS is_finite;
|
|
|
|
-- ============================================================
|
|
-- Test 7: Refraction at exactly -1 deg (edge of domain)
|
|
-- Should return a small positive value
|
|
-- ============================================================
|
|
SELECT 'refr_minus1' AS test,
|
|
atmospheric_refraction(-1.0) > 0 AS positive;
|
|
|
|
-- ============================================================
|
|
-- Test 8: Extended refraction with P/T correction
|
|
-- Standard: P=1010, T=10 should match basic function
|
|
-- ============================================================
|
|
SELECT 'refr_ext_standard' AS test,
|
|
round(atmospheric_refraction_ext(0.0, 1010.0, 10.0)::numeric, 2) AS refr_deg,
|
|
round(atmospheric_refraction(0.0)::numeric, 2) AS refr_basic,
|
|
round(atmospheric_refraction_ext(0.0, 1010.0, 10.0)::numeric, 4) =
|
|
round(atmospheric_refraction(0.0)::numeric, 4) AS match;
|
|
|
|
-- ============================================================
|
|
-- Test 9: Extended refraction - cold high-altitude
|
|
-- At P=700 mbar, T=-20 C, refraction should be reduced
|
|
-- ============================================================
|
|
SELECT 'refr_ext_cold' AS test,
|
|
round(atmospheric_refraction_ext(0.0, 700.0, -20.0)::numeric, 2) AS refr_deg,
|
|
atmospheric_refraction_ext(0.0, 700.0, -20.0) <
|
|
atmospheric_refraction(0.0) AS less_than_standard;
|
|
|
|
-- ============================================================
|
|
-- Test 10: Extended refraction - hot sea level
|
|
-- At P=1013, T=35 C, refraction should be slightly different
|
|
-- ============================================================
|
|
SELECT 'refr_ext_hot' AS test,
|
|
round(atmospheric_refraction_ext(0.0, 1013.0, 35.0)::numeric, 2) AS refr_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 11: Apparent elevation for a topocentric observation
|
|
-- Sun near horizon: geometric el small -> apparent el higher
|
|
-- ============================================================
|
|
SELECT 'apparent_el' AS test,
|
|
round(topo_elevation(sun_observe(:boulder, '2024-03-20 00:30:00+00'))::numeric, 1) AS geometric,
|
|
round(topo_elevation_apparent(sun_observe(:boulder, '2024-03-20 00:30:00+00'))::numeric, 1) AS apparent,
|
|
topo_elevation_apparent(sun_observe(:boulder, '2024-03-20 00:30:00+00')) >
|
|
topo_elevation(sun_observe(:boulder, '2024-03-20 00:30:00+00')) AS refraction_positive;
|
|
|
|
-- ============================================================
|
|
-- Test 12: Apparent elevation for star high up (refraction small)
|
|
-- Polaris from Boulder has el ~49 deg; refraction ~0.01 deg
|
|
-- ============================================================
|
|
SELECT 'apparent_el_high' AS test,
|
|
round(topo_elevation_apparent(
|
|
star_observe(2.530303, 89.2641, :boulder, '2024-06-15 04:00:00+00'))::numeric, 1) AS apparent_deg;
|
|
|
|
-- ============================================================
|
|
-- Test 13: Refracted pass prediction returns results
|
|
-- Using the ISS TLE, should find passes in a week window
|
|
-- ============================================================
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
)
|
|
SELECT 'refracted_passes' AS test,
|
|
count(*) > 0 AS has_passes
|
|
FROM iss, predict_passes_refracted(
|
|
t, :boulder,
|
|
'2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00');
|
|
|
|
-- ============================================================
|
|
-- Test 14: Refracted passes find at least as many as standard
|
|
-- Because refracted horizon is -0.569 deg, satellites visible ~35s earlier
|
|
-- ============================================================
|
|
SELECT 'refracted_more_passes' AS test,
|
|
(SELECT count(*) FROM predict_passes_refracted(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
:boulder,
|
|
'2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00'))
|
|
>=
|
|
(SELECT count(*) FROM predict_passes(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle,
|
|
:boulder,
|
|
'2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00'))
|
|
AS refracted_ge_standard;
|
|
|
|
-- ============================================================
|
|
-- Test 15: Monotonicity - refraction decreases with elevation
|
|
-- ============================================================
|
|
SELECT 'refr_monotonic' AS test,
|
|
atmospheric_refraction(0.0) > atmospheric_refraction(10.0) AS r0_gt_r10,
|
|
atmospheric_refraction(10.0) > atmospheric_refraction(30.0) AS r10_gt_r30,
|
|
atmospheric_refraction(30.0) > atmospheric_refraction(60.0) AS r30_gt_r60,
|
|
atmospheric_refraction(60.0) > atmospheric_refraction(90.0) AS r60_gt_r90;
|