Functions: Atmospheric Refraction
Functions for computing atmospheric refraction corrections using Bennett’s (1982) empirical formula. Earth’s atmosphere bends light from celestial objects, making them appear higher above the horizon than their true geometric position. Near the horizon, refraction is approximately 0.57 degrees --- enough to extend satellite visibility windows by roughly 35 seconds at AOS and LOS, and to make the Sun appear above the horizon when it has already geometrically set.
atmospheric_refraction
Section titled “atmospheric_refraction”Computes the atmospheric refraction correction in degrees for a given geometric elevation using Bennett’s (1982) formula under standard atmosphere conditions (pressure 1010 mbar, temperature 10 C). The domain is clamped at -1 degree to avoid singularity in the cotangent term.
Signature
Section titled “Signature”atmospheric_refraction(elevation_deg float8) → float8Parameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
elevation_deg | float8 | degrees | Geometric elevation of the object above the horizon |
Returns
Section titled “Returns”Refraction correction in degrees. Always positive --- add this value to the geometric elevation to get the apparent elevation. At the horizon (0 degrees), refraction is approximately 0.57 degrees. It drops rapidly with increasing elevation and is negligible above 45 degrees.
Example
Section titled “Example”-- Refraction at various elevationsSELECT elevation, round(atmospheric_refraction(elevation)::numeric, 4) AS refraction_degFROM unnest(ARRAY[-1, 0, 5, 10, 20, 45, 90]) AS elevation;-- How much does refraction shift the Sun at sunset?SELECT round(atmospheric_refraction(0)::numeric, 4) AS horizon_refraction_deg;atmospheric_refraction_ext
Section titled “atmospheric_refraction_ext”Computes atmospheric refraction with a pressure and temperature correction factor applied to Bennett’s formula, following the Meeus formulation. Useful for high-altitude observatories or extreme weather conditions where standard atmosphere assumptions break down.
Signature
Section titled “Signature”atmospheric_refraction_ext(elevation_deg float8, pressure_mbar float8, temp_celsius float8) → float8Parameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
elevation_deg | float8 | degrees | Geometric elevation of the object above the horizon |
pressure_mbar | float8 | mbar | Atmospheric pressure at the observer |
temp_celsius | float8 | C | Air temperature at the observer |
Returns
Section titled “Returns”Refraction correction in degrees, adjusted for the given pressure and temperature. The correction factor is (P / 1010) * (283 / (273 + T)) applied to the standard Bennett formula result.
Example
Section titled “Example”-- Refraction at Mauna Kea summit (4205m, ~620 mbar, -2C)SELECT round(atmospheric_refraction_ext(5.0, 620.0, -2.0)::numeric, 4) AS refraction_mauna_kea, round(atmospheric_refraction(5.0)::numeric, 4) AS refraction_standard;-- Compare standard vs corrected refraction across a range of elevationsSELECT elevation, round(atmospheric_refraction(elevation)::numeric, 4) AS standard, round(atmospheric_refraction_ext(elevation, 850.0, -10.0)::numeric, 4) AS high_altitude_coldFROM unnest(ARRAY[0, 2, 5, 10, 30]) AS elevation;topo_elevation_apparent
Section titled “topo_elevation_apparent”Convenience function that returns the apparent elevation of an object by adding the atmospheric refraction correction to the geometric elevation stored in a topocentric value. The result is in degrees.
Signature
Section titled “Signature”topo_elevation_apparent(topocentric) → float8Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
| (unnamed) | topocentric | A topocentric observation result from any *_observe function |
Returns
Section titled “Returns”Apparent elevation in degrees --- the geometric elevation plus the Bennett refraction correction under standard atmosphere. Always higher than the geometric topo_elevation() value.
Example
Section titled “Example”-- Compare geometric vs apparent elevation for the MoonSELECT round(topo_elevation(t)::numeric, 3) AS geometric_el, round(topo_elevation_apparent(t)::numeric, 3) AS apparent_el, round(topo_elevation_apparent(t) - topo_elevation(t)::numeric, 4) AS refraction_correctionFROM moon_observe('40.0N 105.3W 1655m'::observer, now()) AS t;-- Find objects that are geometrically below horizon but visible due to refractionSELECT norad_id, round(topo_elevation(o)::numeric, 3) AS geometric_el, round(topo_elevation_apparent(o)::numeric, 3) AS apparent_elFROM satellite_catalog, observe_safe(tle, '40.0N 105.3W 1655m'::observer, now()) AS oWHERE o IS NOT NULL AND topo_elevation(o) < 0 AND topo_elevation_apparent(o) > 0;predict_passes_refracted
Section titled “predict_passes_refracted”Predicts satellite passes using a refracted horizon threshold instead of the geometric horizon. The geometric threshold is set to -0.569 degrees, which corresponds to the apparent horizon after atmospheric refraction. This means satellites become visible approximately 35 seconds earlier at AOS and remain visible approximately 35 seconds later at LOS compared to predict_passes.
Signature
Section titled “Signature”predict_passes_refracted( tle tle, obs observer, start_time timestamptz, end_time timestamptz, min_el float8 DEFAULT 0.0) → SETOF pass_eventParameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
tle | tle | Satellite TLE | |
obs | observer | Observer location | |
start_time | timestamptz | Start of the search window | |
end_time | timestamptz | End of the search window | |
min_el | float8 | 0.0 | Minimum peak elevation in degrees. Passes whose maximum elevation is below this threshold are excluded. |
Returns
Section titled “Returns”A set of pass_event records, ordered by AOS time. Each pass will show slightly earlier AOS and later LOS times compared to predict_passes due to the refracted horizon.
Example
Section titled “Example”-- Compare geometric vs refracted pass predictions for the ISSWITH iss AS ( SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 90252 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS tle)SELECT pass_aos_time(p) AS rise, pass_max_elevation(p) AS max_el, pass_los_time(p) AS set, pass_duration(p) AS durFROM iss, predict_passes_refracted(tle, '40.0N 105.3W 1655m'::observer, now(), now() + interval '24 hours', 10.0) AS p;-- How much extra visibility does refraction add?WITH iss AS ( SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 90252 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS tle),geo AS ( SELECT pass_duration(p) AS dur FROM iss, predict_passes(tle, '40.0N 105.3W 1655m'::observer, now(), now() + interval '24 hours') AS p LIMIT 1),refr AS ( SELECT pass_duration(p) AS dur FROM iss, predict_passes_refracted(tle, '40.0N 105.3W 1655m'::observer, now(), now() + interval '24 hours') AS p LIMIT 1)SELECT geo.dur AS geometric_duration, refr.dur AS refracted_durationFROM geo, refr;