sciforge-lib 0.0.4

Scientific computing library — mathematics, physics, chemistry, biology, astronomy, geology, meteorology.
Documentation
use crate::constants::{
    ADIABATIC_INDEX_IDEAL, ADIABATIC_INDEX_RADIATION, AMU_TO_KG, BOLOMETRIC_CORRECTION_CENTER,
    BOLOMETRIC_CORRECTION_OFFSET, BOLOMETRIC_CORRECTION_QUAD, C, CHANDRASEKHAR_LIMIT_SOLAR,
    CNO_CYCLE_ENERGY, G, H_BURNING_EFFICIENCY, HELIUM_FRACTION_SOLAR, HELIUM4_MASS,
    HYDROGEN_FRACTION_SOLAR, K_B, MAGNETAR_B_TYPICAL, MAIN_SEQUENCE_LIFETIME_SCALE_YR,
    METAL_FRACTION_SOLAR, ML_HIGH_COEFF, ML_HIGH_EXPONENT, ML_HIGH_THRESHOLD, ML_LOW_COEFF,
    ML_LOW_EXPONENT, ML_LOW_THRESHOLD, ML_MID_EXPONENT, ML_MID_THRESHOLD, ML_VERY_HIGH_COEFF, MU_0,
    NS_MASS_TYPICAL, NS_RADIUS_TYPICAL, OPACITY_ELECTRON_SCATTERING, PP_CHAIN_ENERGY,
    PROTON_MASS_KG, PULSAR_B_TYPICAL, SIGMA_SB, SOLAR_ABS_MAGNITUDE, SOLAR_MASS, SOLAR_METALLICITY,
    SOLAR_MS_LIFETIME, SOLAR_TEFF, SPECTRAL_INDEX_OFFSET, SPECTRAL_TEMP_SCALE, TOV_LIMIT,
    WD_RADIUS_TYPICAL, WIEN_DISPLACEMENT,
};

pub fn luminosity_from_radius_temp(r: f64, t: f64) -> f64 {
    4.0 * std::f64::consts::PI * r * r * SIGMA_SB * t.powi(4)
}

pub fn absolute_magnitude(apparent_mag: f64, distance_pc: f64) -> f64 {
    apparent_mag - 5.0 * (distance_pc / 10.0).log10()
}

pub fn distance_modulus(apparent_mag: f64, absolute_mag: f64) -> f64 {
    10.0_f64.powf((apparent_mag - absolute_mag + 5.0) / 5.0)
}

pub fn stellar_flux(luminosity: f64, distance: f64) -> f64 {
    luminosity / (4.0 * std::f64::consts::PI * distance * distance)
}

pub fn wien_peak_wavelength(temperature: f64) -> f64 {
    WIEN_DISPLACEMENT / temperature
}

pub fn main_sequence_lifetime(mass_solar: f64, luminosity_solar: f64) -> f64 {
    MAIN_SEQUENCE_LIFETIME_SCALE_YR * mass_solar / luminosity_solar
}

pub fn mass_luminosity_relation(mass_solar: f64) -> f64 {
    if mass_solar < ML_LOW_THRESHOLD {
        ML_LOW_COEFF * mass_solar.powf(ML_LOW_EXPONENT)
    } else if mass_solar < ML_MID_THRESHOLD {
        mass_solar.powf(ML_MID_EXPONENT)
    } else if mass_solar < ML_HIGH_THRESHOLD {
        ML_HIGH_COEFF * mass_solar.powf(ML_HIGH_EXPONENT)
    } else {
        ML_VERY_HIGH_COEFF * mass_solar
    }
}

pub fn schwarzschild_radius(mass: f64) -> f64 {
    2.0 * G * mass / (C * C)
}

pub fn chandrasekhar_limit() -> f64 {
    CHANDRASEKHAR_LIMIT_SOLAR * SOLAR_MASS
}

pub fn chandrasekhar_limit_kg() -> f64 {
    crate::constants::CHANDRASEKHAR_LIMIT
}

pub fn is_above_chandrasekhar(mass_kg: f64) -> bool {
    mass_kg > crate::constants::CHANDRASEKHAR_LIMIT
}

pub fn eddington_luminosity(mass: f64) -> f64 {
    4.0 * std::f64::consts::PI * G * mass * C / OPACITY_ELECTRON_SCATTERING
}

pub fn spectral_type_temperature(spectral_index: f64) -> f64 {
    SPECTRAL_TEMP_SCALE / (spectral_index + SPECTRAL_INDEX_OFFSET)
}

pub fn bolometric_correction(t_eff: f64) -> f64 {
    let log_t = t_eff.log10();
    BOLOMETRIC_CORRECTION_QUAD * (log_t - BOLOMETRIC_CORRECTION_CENTER).powi(2)
        + BOLOMETRIC_CORRECTION_OFFSET
}

pub fn tov_limit() -> f64 {
    TOV_LIMIT
}

pub fn neutron_star_surface_gravity() -> f64 {
    G * NS_MASS_TYPICAL / (NS_RADIUS_TYPICAL * NS_RADIUS_TYPICAL)
}

pub fn neutron_star_mean_density() -> f64 {
    3.0 * NS_MASS_TYPICAL / (4.0 * std::f64::consts::PI * NS_RADIUS_TYPICAL.powi(3))
}

pub fn neutron_star_escape_velocity() -> f64 {
    (2.0 * G * NS_MASS_TYPICAL / NS_RADIUS_TYPICAL).sqrt()
}

pub fn pulsar_spindown_luminosity(period: f64, period_dot: f64) -> f64 {
    let inertia = 0.4 * NS_MASS_TYPICAL * NS_RADIUS_TYPICAL * NS_RADIUS_TYPICAL;
    4.0 * std::f64::consts::PI * std::f64::consts::PI * inertia * period_dot
        / (period * period * period)
}

pub fn pulsar_magnetic_field(period: f64, period_dot: f64) -> f64 {
    let inertia = 0.4 * NS_MASS_TYPICAL * NS_RADIUS_TYPICAL * NS_RADIUS_TYPICAL;
    let r = NS_RADIUS_TYPICAL;
    (3.0 * C * C * C * inertia * period * period_dot
        / (8.0 * std::f64::consts::PI * std::f64::consts::PI * r.powi(6)))
    .sqrt()
}

pub fn pulsar_characteristic_age(period: f64, period_dot: f64) -> f64 {
    period / (2.0 * period_dot)
}

pub fn pulsar_death_line_period(b_field: f64) -> f64 {
    (b_field / PULSAR_B_TYPICAL).sqrt()
}

pub fn magnetar_energy_reservoir(b_field: f64) -> f64 {
    let volume = 4.0 / 3.0 * std::f64::consts::PI * NS_RADIUS_TYPICAL.powi(3);
    b_field * b_field * volume / (2.0 * MU_0)
}

pub fn magnetar_typical_energy() -> f64 {
    let volume = 4.0 / 3.0 * std::f64::consts::PI * NS_RADIUS_TYPICAL.powi(3);
    MAGNETAR_B_TYPICAL * MAGNETAR_B_TYPICAL * volume / (2.0 * MU_0)
}

pub fn radiation_pressure(temperature: f64) -> f64 {
    ADIABATIC_INDEX_RADIATION * SIGMA_SB * temperature.powi(4) / (3.0 * C)
}

pub fn gas_pressure(rho: f64, temperature: f64, mu: f64) -> f64 {
    rho * K_B * temperature / (mu * AMU_TO_KG)
}

pub fn adiabatic_sound_speed(temperature: f64, mu: f64) -> f64 {
    (ADIABATIC_INDEX_IDEAL * K_B * temperature / (mu * AMU_TO_KG)).sqrt()
}

pub fn pp_chain_luminosity(mass_kg: f64, x_hydrogen: f64) -> f64 {
    let n_protons = x_hydrogen * mass_kg / PROTON_MASS_KG;
    let rate_per_proton = H_BURNING_EFFICIENCY * PP_CHAIN_ENERGY;
    n_protons * rate_per_proton / SOLAR_MS_LIFETIME
}

pub fn cno_cycle_luminosity(mass_kg: f64, x_hydrogen: f64, z_metals: f64) -> f64 {
    let n_protons = x_hydrogen * mass_kg / PROTON_MASS_KG;
    let rate_per_proton = H_BURNING_EFFICIENCY * CNO_CYCLE_ENERGY * z_metals / SOLAR_METALLICITY;
    n_protons * rate_per_proton / SOLAR_MS_LIFETIME
}

pub fn kelvin_helmholtz_timescale(mass: f64, radius: f64, luminosity: f64) -> f64 {
    G * mass * mass / (radius * luminosity)
}

pub fn nuclear_timescale(mass: f64, luminosity: f64) -> f64 {
    H_BURNING_EFFICIENCY * HYDROGEN_FRACTION_SOLAR * mass * C * C / luminosity
}

pub fn white_dwarf_radius_from_mass(mass_kg: f64) -> f64 {
    WD_RADIUS_TYPICAL
        * (CHANDRASEKHAR_LIMIT_SOLAR * SOLAR_MASS / mass_kg).powf(1.0 / 3.0)
        * (1.0 - (mass_kg / (CHANDRASEKHAR_LIMIT_SOLAR * SOLAR_MASS)).powf(4.0 / 3.0)).sqrt()
}

pub fn eddington_luminosity_numerical(mass_solar: f64) -> f64 {
    crate::constants::EDDINGTON_PREFACTOR * mass_solar * crate::constants::SOLAR_LUMINOSITY
}

pub fn helium_mass() -> f64 {
    HELIUM4_MASS
}

pub fn solar_composition() -> (f64, f64, f64) {
    (
        HYDROGEN_FRACTION_SOLAR,
        HELIUM_FRACTION_SOLAR,
        METAL_FRACTION_SOLAR,
    )
}

pub fn solar_effective_temperature() -> f64 {
    SOLAR_TEFF
}

pub fn solar_absolute_magnitude() -> f64 {
    SOLAR_ABS_MAGNITUDE
}

pub fn solar_metallicity() -> f64 {
    SOLAR_METALLICITY
}

pub fn solar_main_sequence_lifetime() -> f64 {
    SOLAR_MS_LIFETIME
}

pub fn hydrogen_burning_energy_per_kg() -> f64 {
    H_BURNING_EFFICIENCY * C * C
}

pub fn eddington_ratio(luminosity: f64, mass: f64) -> f64 {
    luminosity * OPACITY_ELECTRON_SCATTERING * C / (4.0 * std::f64::consts::PI * G * mass * C * C)
}

pub fn sun_core_temperature() -> f64 {
    crate::constants::SUN_CORE_TEMPERATURE
}

pub fn sun_surface_temperature() -> f64 {
    crate::constants::SUN_SURFACE_TEMPERATURE
}

pub fn sun_core_density() -> f64 {
    crate::constants::SUN_CORE_DENSITY
}

pub fn sun_age() -> f64 {
    crate::constants::SUN_AGE
}

pub fn sun_rotation_period() -> f64 {
    crate::constants::SUN_ROTATION_PERIOD
}

pub fn solar_density() -> f64 {
    crate::constants::SOLAR_DENSITY
}

pub fn solar_surface_gravity() -> f64 {
    crate::constants::SOLAR_GRAVITY
}

pub fn sun_luminosity_to_mass_ratio() -> f64 {
    crate::constants::SOLAR_LUMINOSITY / SOLAR_MASS
}