CelestialCalendar 1.0.0 · unreleased development @ 67a7c4c79a4a4a6aa7e703c9e6f0039ae34bee82
Loading...
Searching...
No Matches
astro::rise_set::detail Namespace Reference

Classes

struct  BodyLocal
 A body's local hour angle and equatorial position at one instant. More...
struct  AltitudeExtremum
 A refined local extremum of the altitude curve: its instant, kind, and value. More...
struct  Solved
 A refined crossing and the |altitude − h₀| residual it left, in degrees. More...
struct  DayWindow
 The TT endpoints of one half-open UT1 calendar day. More...

Typedefs

using AltitudeGrid

Functions

auto validate (const GeoLocation &location) -> void
 Validate an observer location, throwing on out-of-range or non-finite coordinates.
auto jde_tt_to_jd_ut1 (const double jde_tt) -> double
 Convert a JDE (TT) to the JD (UT1) of the same instant.
template<BodyProvider P>
auto body_local (const double jde_tt, const GeoLocation &location, const P &provider) -> BodyLocal
 Compute a body's local hour angle and equatorial coordinates for an observer.
template<BodyProvider P>
auto altitude (const double jde_tt, const GeoLocation &location, const P &provider) -> toolbox::AngleDeg
 Compute a body's geometric altitude for an observer at one instant.
template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto golden_section_argmin (const Func &f, const double a, const double b, const double tolerance=EXTREMUM_SEARCH_TOLERANCE_DAYS) -> double
 Find the argmin of a unimodal function on [a, b] by golden-section search.
template<typename Func>
auto altitude_grid (const Func &f, const double start_jde_tt, const double step_days) -> AltitudeGrid
 Sample every grid endpoint in increasing TT order, including both window ends.
template<typename Func>
auto interior_extrema (const Func &f, const double start_jde_tt, const double step_days, const AltitudeGrid &values) -> std::vector< AltitudeExtremum >
 Refine strict direction changes; a flat plateau does not define an interior extremum.
template<typename Func>
auto append_edge_extrema (const Func &f, const double lo_jde_tt, const double hi_jde_tt, std::vector< AltitudeExtremum > &extrema) -> void
 Probe a cell with a missing outer grid neighbor for an interior minimum and maximum.
template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto find_extrema (const Func &f, const double a, const double b) -> std::vector< AltitudeExtremum >
 Find every local extremum of the altitude curve on [a, b], in time order.
template<BodyProvider P>
auto min_altitude_jde (const double transit, const bool before, const GeoLocation &location, const P &provider) -> double
 Find the instant of minimum altitude in the half-arc adjacent to a transit.
auto validate_pm90 (const char *name, const double angle_deg) -> void
 Reject a named non-finite angle or one outside [-90°, 90°].
auto validate_rise_set_inputs (const double transit_jde_tt, const GeoLocation &location, const toolbox::AngleDeg &h0) -> void
 Validate rise_set_jde's inputs.
template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto crossing_in_bracket (const Func &f, const double lo_jde, const double hi_jde, const bool rising) -> std::optional< Solved >
 Try to solve one altitude crossing inside a bracket.
template<BodyProvider P>
auto polish_transit (const double estimate_jde, const GeoLocation &location, const P &provider) -> double
 Polish a transit estimate into the instant of upper culmination (H = 0).
auto day_window (const std::chrono::year_month_day &ymd_ut1) -> DayWindow
 Convert both UT1 midnights independently; a UT1 day is not exactly one TT day.
auto crossing_error (const std::string_view caller, const bool rising, const Solved &solved, const double lo_jde_tt, const double hi_jde_tt) -> std::runtime_error
 Describe a bracketed altitude crossing that failed its caller's residual guard.
template<typename Func>
auto scan_day_crossings (const Func &f, const DayWindow &window, const std::vector< AltitudeExtremum > &extrema, Result &result) -> void
 Scan monotone segments in time order, trying rise before set and keeping later crossings.
template<typename Func>
auto day_polar (const Func &h, const DayWindow &window, const std::vector< AltitudeExtremum > &extrema, const toolbox::AngleDeg &h0) -> Polar
 Classify a crossing-free day from its global altitude bounds, including the window ends.

Variables

constexpr std::size_t EXTREMUM_SCAN_CELLS

Typedef Documentation

◆ AltitudeGrid

Function Documentation

◆ altitude()

template<BodyProvider P>
auto astro::rise_set::detail::altitude ( const double jde_tt,
const GeoLocation & location,
const P & provider )->toolbox::AngleDeg
inlinenodiscard

Compute a body's geometric altitude for an observer at one instant.

Parameters
jde_ttThe instant, as a julian ephemeris day on the TT scale.
locationThe observer's location.
providerThe body's position provider.
Returns
The body's altitude, in [-90°, 90°]. Purely geometric — refraction enters only through the h₀ convention, not through this function.

◆ altitude_grid()

template<typename Func>
auto astro::rise_set::detail::altitude_grid ( const Func & f,
const double start_jde_tt,
const double step_days )->AltitudeGrid
inlinenodiscard

Sample every grid endpoint in increasing TT order, including both window ends.

◆ append_edge_extrema()

template<typename Func>
auto astro::rise_set::detail::append_edge_extrema ( const Func & f,
const double lo_jde_tt,
const double hi_jde_tt,
std::vector< AltitudeExtremum > & extrema )->void
inline

Probe a cell with a missing outer grid neighbor for an interior minimum and maximum.

Note
A candidate must beat both endpoints. Only same-kind extrema within the endpoint exclusion distance count as duplicates; distinct extrema may share a cell.

◆ body_local()

template<BodyProvider P>
auto astro::rise_set::detail::body_local ( const double jde_tt,
const GeoLocation & location,
const P & provider )->BodyLocal
inlinenodiscard

Compute a body's local hour angle and equatorial coordinates for an observer.

Parameters
jde_ttThe instant, as a julian ephemeris day on the TT scale.
locationThe observer's location.
providerThe body's position provider.
Returns
The hour angle (unwrapped to [-180°, 180°)) and the equatorial coordinates.
Note
The sidereal time is evaluated on the UT1 scale (pitfall: feeding TT would shift the result by ΔT ≈ 69 s); the body's position and the nutation terms are evaluated on TT.

◆ crossing_error()

auto astro::rise_set::detail::crossing_error ( const std::string_view caller,
const bool rising,
const Solved & solved,
const double lo_jde_tt,
const double hi_jde_tt )->std::runtime_error
inlinenodiscard

Describe a bracketed altitude crossing that failed its caller's residual guard.

◆ crossing_in_bracket()

template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto astro::rise_set::detail::crossing_in_bracket ( const Func & f,
const double lo_jde,
const double hi_jde,
const bool rising )->std::optional< Solved >
inlinenodiscard

Try to solve one altitude crossing inside a bracket.

Parameters
fThe residual function (altitude − h₀), in degrees, over JDE (TT).
lo_jdeThe left bracket end, inclusive.
hi_jdeThe right bracket end, exclusive.
risingTrue for an upward crossing (rise side), false for a downward one.
Returns
nullopt when the bracket ends do not straddle a crossing in the required direction (a plain sign change is not enough — direction is what rejects event-free brackets); otherwise the refined root plus its residual. The residual verdict is the caller's: a straddle proves a root exists, so what a rejection means depends on the bracket.

◆ day_polar()

template<typename Func>
auto astro::rise_set::detail::day_polar ( const Func & h,
const DayWindow & window,
const std::vector< AltitudeExtremum > & extrema,
const toolbox::AngleDeg & h0 )->Polar
inlinenodiscard

Classify a crossing-free day from its global altitude bounds, including the window ends.

Exceptions
std::runtime_errorIf the bounds straddle h₀ despite the absence of a solved crossing.

◆ day_window()

auto astro::rise_set::detail::day_window ( const std::chrono::year_month_day & ymd_ut1) ->DayWindow
inlinenodiscard

Convert both UT1 midnights independently; a UT1 day is not exactly one TT day.

Note
Adding 86400 TT seconds would leave gaps or overlaps as ΔT changes between adjacent dates.

◆ find_extrema()

template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto astro::rise_set::detail::find_extrema ( const Func & f,
const double a,
const double b )->std::vector< AltitudeExtremum >
inlinenodiscard

Find every local extremum of the altitude curve on [a, b], in time order.

Note
Grid scan for direction changes (15-min cells on a 1-day window) plus a direct probe of each edge cell, then golden-section refinement per candidate. The window must be partitioned at ALL of these, not just at the global minimum and maximum: the global extremum need not be a monotone cut (2026-06-18 Tromsø: the window's end dips below the interior minimum, and partitioning at the global minimum hid that day's only rise inside a non-monotone segment — pinned by a golden row).

◆ golden_section_argmin()

template<typename Func>
requires std::invocable<const Func&, double> and std::convertible_to<std::invoke_result_t<const Func&, double>, double>
auto astro::rise_set::detail::golden_section_argmin ( const Func & f,
const double a,
const double b,
const double tolerance = EXTREMUM_SEARCH_TOLERANCE_DAYS )->double
inlinenodiscard

Find the argmin of a unimodal function on [a, b] by golden-section search.

Note
Derivative-free; a monotone objective contracts toward an endpoint, as on polar-boundary arcs.
At |JDE| >= 2²³ the double ULP exceeds the default tolerance, so contraction can stall. The 64-update cap still terminates and returns (lower + upper) / 2 for the final bracket.

◆ interior_extrema()

template<typename Func>
auto astro::rise_set::detail::interior_extrema ( const Func & f,
const double start_jde_tt,
const double step_days,
const AltitudeGrid & values )->std::vector< AltitudeExtremum >
inlinenodiscard

Refine strict direction changes; a flat plateau does not define an interior extremum.

◆ jde_tt_to_jd_ut1()

auto astro::rise_set::detail::jde_tt_to_jd_ut1 ( const double jde_tt) ->double
inlinenodiscard

Convert a JDE (TT) to the JD (UT1) of the same instant.

Parameters
jde_ttThe julian ephemeris day, on the TT scale.
Returns
The julian day number, on the UT1 scale.

◆ min_altitude_jde()

template<BodyProvider P>
auto astro::rise_set::detail::min_altitude_jde ( const double transit,
const bool before,
const GeoLocation & location,
const P & provider )->double
inlinenodiscard

Find the instant of minimum altitude in the half-arc adjacent to a transit.

Parameters
transitThe upper-culmination instant (JDE, TT scale).
beforeTrue for the half-arc preceding the transit, false for the following one.
locationThe observer's location.
providerThe body's position provider.
Returns
The argmin instant (JDE, TT scale).
Note
Golden-section search around the nominal lower culmination — NOT a solve of H = ±180°. With dδ/dt ≠ 0 the true altitude minimum wanders off the lower culmination (for the Moon, degrees of hour angle); the existence check must anchor on the true minimum, or grazing days fall into a blind band and read as polar (#62).

◆ polish_transit()

template<BodyProvider P>
auto astro::rise_set::detail::polish_transit ( const double estimate_jde,
const GeoLocation & location,
const P & provider )->double
inlinenodiscard

Polish a transit estimate into the instant of upper culmination (H = 0).

Parameters
estimate_jdeThe estimated transit instant, as a julian ephemeris day on the TT scale. Must lie within TRANSIT_BRACKET_HALF_WIDTH_DAYS of the true transit.
locationThe observer's location.
providerThe body's position provider.
Returns
The transit instant (JDE, TT scale).
Exceptions
std::invalid_argumentIf location is out of range.
Note
The root of H = 0 is found with toolbox::newton_method on the unwrapped hour angle.

◆ scan_day_crossings()

template<typename Func>
auto astro::rise_set::detail::scan_day_crossings ( const Func & f,
const DayWindow & window,
const std::vector< AltitudeExtremum > & extrema,
Result & result )->void
inline

Scan monotone segments in time order, trying rise before set and keeping later crossings.

Note
Extrema must already be sorted. Residual rejection here uses > guard; the transit-centered fallback accepts with <= guard, which rejects NaN where this scan retains it.

◆ validate()

auto astro::rise_set::detail::validate ( const GeoLocation & location) ->void
inline

Validate an observer location, throwing on out-of-range or non-finite coordinates.

Parameters
locationThe location to validate.
Exceptions
std::invalid_argumentIf latitude ∉ [-90°, 90°] or longitude ∉ [-180°, 180°], or either is not finite.

◆ validate_pm90()

auto astro::rise_set::detail::validate_pm90 ( const char * name,
const double angle_deg )->void
inline

Reject a named non-finite angle or one outside [-90°, 90°].

◆ validate_rise_set_inputs()

auto astro::rise_set::detail::validate_rise_set_inputs ( const double transit_jde_tt,
const GeoLocation & location,
const toolbox::AngleDeg & h0 )->void
inline

Validate rise_set_jde's inputs.

Exceptions
std::invalid_argumentIf transit_jde_tt is not finite, location is out of range, or h0 is not finite or outside [-90°, 90°].

Variable Documentation

◆ EXTREMUM_SCAN_CELLS

std::size_t astro::rise_set::detail::EXTREMUM_SCAN_CELLS
inlineconstexpr