use crate::constants;
#[must_use]
#[inline]
pub fn stellar_mass_solar_to_mu(mass_solar: f64) -> f64 {
mass_solar * constants::GM_SUN
}
#[must_use]
pub fn luminosity_class_to_abs_magnitude(
luminosity_class: crate::classification::LuminosityClass,
) -> f64 {
use crate::classification::LuminosityClass;
match luminosity_class {
LuminosityClass::Ia => -7.0, LuminosityClass::Ib => -5.0, LuminosityClass::II => -3.0, LuminosityClass::III => 0.0, LuminosityClass::IV => 2.0, LuminosityClass::V => 5.0, LuminosityClass::VI => 10.0, LuminosityClass::VII => 15.0, }
}
#[must_use]
#[inline]
pub fn temperature_to_peak_wavelength_nm(temperature_k: f64) -> f64 {
if temperature_k <= 0.0 {
return 0.0;
}
constants::WIEN_B_NM / temperature_k
}
#[must_use]
#[inline]
pub fn surface_gravity_to_limb_darkening(log_g: f64) -> f64 {
(0.6 - 0.1 * (log_g - 4.0)).clamp(0.2, 0.9)
}
#[must_use]
#[inline]
pub fn composition_to_lifetime_scale(hydrogen_fraction: f64) -> f64 {
if hydrogen_fraction <= 0.0 {
return 0.0;
}
(hydrogen_fraction / 0.74).clamp(0.0, 2.0)
}
#[must_use]
#[inline]
pub fn core_temp_to_cno_fraction(core_temperature_k: f64) -> f64 {
let t_mk = core_temperature_k / 1e6;
let x = (t_mk - 17.0) / 3.0;
1.0 / (1.0 + (-x).exp())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sun_mu() {
let mu = stellar_mass_solar_to_mu(1.0);
assert!(
(mu - constants::GM_SUN).abs() < f64::EPSILON,
"1 M_sun → μ = {mu}, expected {}",
constants::GM_SUN
);
}
#[test]
fn luminosity_main_sequence() {
use crate::classification::LuminosityClass;
let m = luminosity_class_to_abs_magnitude(LuminosityClass::V);
assert!((m - 5.0).abs() < 0.1);
}
#[test]
fn luminosity_supergiant_ia_brighter_than_ib() {
use crate::classification::LuminosityClass;
let ia = luminosity_class_to_abs_magnitude(LuminosityClass::Ia);
let ib = luminosity_class_to_abs_magnitude(LuminosityClass::Ib);
assert!(ia < ib, "Ia should be brighter (lower mag) than Ib");
}
#[test]
fn wien_sun() {
let nm = temperature_to_peak_wavelength_nm(constants::T_SUN);
assert!(
(nm - 502.0).abs() < 5.0,
"Solar peak: {nm} nm, expected ~502"
);
}
#[test]
fn wien_zero() {
assert!(temperature_to_peak_wavelength_nm(0.0).abs() < f64::EPSILON);
}
#[test]
fn limb_darkening_solar() {
let u = surface_gravity_to_limb_darkening(4.44);
assert!(u > 0.5 && u < 0.7);
}
#[test]
fn composition_solar() {
let s = composition_to_lifetime_scale(0.74);
assert!((s - 1.0).abs() < 0.01);
}
#[test]
fn cno_cool_star() {
let f = core_temp_to_cno_fraction(10e6);
assert!(f < 0.1, "cool star should be pp-dominated: {f}");
}
#[test]
fn cno_hot_star() {
let f = core_temp_to_cno_fraction(25e6);
assert!(f > 0.9, "hot star should be CNO-dominated: {f}");
}
}