use crate::kepler::UniversalKeplerParams;
pub fn prelim_hyperbolic(params: &UniversalKeplerParams) -> f64 {
let semi_major_axis = -1.0 / params.alpha;
let mean_motion = params.mu.sqrt() * params.alpha.powi(3).sqrt();
let initial_hyperbolic_anomaly = initial_hyperbolic_anomaly_from_geometry(
params.r0,
semi_major_axis,
params.e0,
params.sig0,
);
let mean_anomaly_at_epoch =
params.e0 * initial_hyperbolic_anomaly.sinh() - initial_hyperbolic_anomaly;
let target_mean_anomaly = mean_anomaly_at_epoch + mean_motion * params.dt;
let updated_hyperbolic_anomaly = solve_hyperbolic_kepler_equation(
target_mean_anomaly,
params.e0,
params.solver_type.params.convergency,
params.solver_type.params.max_iter_prelim_kepuni,
);
(updated_hyperbolic_anomaly - initial_hyperbolic_anomaly) / params.alpha.sqrt()
}
fn initial_hyperbolic_anomaly_from_geometry(
radial_distance: f64,
semi_major_axis: f64,
eccentricity: f64,
radial_velocity_proxy: f64,
) -> f64 {
let hyperbolic_cosine_of_anomaly = (1.0 - radial_distance / semi_major_axis) / eccentricity;
let mut hyperbolic_anomaly = if hyperbolic_cosine_of_anomaly > 1.0 {
(hyperbolic_cosine_of_anomaly + (hyperbolic_cosine_of_anomaly.powi(2) - 1.0).sqrt()).ln()
} else {
0.0 };
if radial_velocity_proxy < 0.0 {
hyperbolic_anomaly = -hyperbolic_anomaly;
}
hyperbolic_anomaly
}
fn solve_hyperbolic_kepler_equation(
target_mean_anomaly: f64,
eccentricity: f64,
convergence_threshold: f64,
max_iter: usize,
) -> f64 {
let mut hyperbolic_anomaly: f64 = 0.0;
for _ in 0..max_iter {
if hyperbolic_anomaly.abs() < 15.0 {
let residual =
eccentricity * hyperbolic_anomaly.sinh() - hyperbolic_anomaly - target_mean_anomaly;
let residual_derivative = eccentricity * hyperbolic_anomaly.cosh() - 1.0;
let newton_step = -residual / residual_derivative;
let candidate_anomaly = hyperbolic_anomaly + newton_step;
hyperbolic_anomaly = if hyperbolic_anomaly * candidate_anomaly < 0.0 {
hyperbolic_anomaly / 2.0
} else {
candidate_anomaly
};
} else {
hyperbolic_anomaly /= 2.0;
}
if hyperbolic_anomaly.abs() < convergence_threshold * 1e3 {
break;
}
}
hyperbolic_anomaly
}