sagittariusas 0.0.1

Simulation engine for Sagittarius A* — Kerr spacetime, accretion, jets, lensing, and shadow observables
Documentation
use sciforge::hub::prelude::maths::vector::Vec3;

pub fn lerp(a: f64, b: f64, t: f64) -> f64 {
    a + (b - a) * t
}

pub fn clamp(val: f64, min: f64, max: f64) -> f64 {
    val.max(min).min(max)
}

pub fn rk4_step<F>(y: f64, dy: f64, dt: f64, f: F) -> (f64, f64)
where
    F: Fn(f64, f64) -> f64,
{
    let k1 = f(y, dy);
    let k2 = f(y + 0.5 * dt * dy, dy + 0.5 * dt * k1);
    let k3 = f(y + 0.5 * dt * (dy + 0.5 * dt * k1), dy + 0.5 * dt * k2);
    let k4 = f(y + dt * (dy + 0.5 * dt * k2), dy + dt * k3);
    let new_dy = dy + dt / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
    let new_y = y + dt * dy + dt * dt / 6.0 * (k1 + k2 + k3);
    (new_y, new_dy)
}

pub fn simpson_integrate<F>(f: F, a: f64, b: f64, n: usize) -> f64
where
    F: Fn(f64) -> f64,
{
    sciforge::hub::prelude::maths::integration::composite_simpson(f, a, b, n)
}

pub fn log_range(start: f64, end: f64, n: usize) -> Vec<f64> {
    let log_start = start.ln();
    let log_end = end.ln();
    (0..n)
        .map(|i| (log_start + (log_end - log_start) * i as f64 / (n - 1).max(1) as f64).exp())
        .collect()
}

pub fn spherical_to_cartesian(r: f64, theta: f64, phi: f64) -> Vec3 {
    Vec3::new(
        r * theta.sin() * phi.cos(),
        r * theta.sin() * phi.sin(),
        r * theta.cos(),
    )
}

pub fn cartesian_to_spherical(v: &Vec3) -> (f64, f64, f64) {
    let r = v.magnitude();
    let theta = if r > 0.0 { (v.z / r).acos() } else { 0.0 };
    let phi = v.y.atan2(v.x);
    (r, theta, phi)
}