SpectraRust/src/synspec/math/ispec.rs
2026-03-25 13:31:23 +08:00

203 lines
6.4 KiB
Rust

//! 特殊吸收轮廓类型判断。
//!
//! 重构自 SYNSPEC `ispec.f`
//!
//! 用于判断给定谱线是否使用特殊的预计算吸收轮廓(仅氢和氦)。
/// 特殊轮廓类型常量
pub const PROFILE_VOIGT: i32 = 0; // 普通 Voigt 轮廓
pub const PROFILE_HYDROGEN: i32 = 1; // 氢线
// He I 特殊轮廓 (2-5)
pub const PROFILE_HEI_4471: i32 = 2; // He I 447.1 nm
pub const PROFILE_HEI_4388: i32 = 3; // He I 438.8 nm
pub const PROFILE_HEI_4026: i32 = 4; // He I 402.6 nm
pub const PROFILE_HEI_4922: i32 = 5; // He I 492.2 nm
// He II 特殊轮廓 (6-24)
pub const PROFILE_HEII_1640: i32 = 6;
pub const PROFILE_HEII_3203: i32 = 7;
pub const PROFILE_HEII_2733: i32 = 8;
pub const PROFILE_HEII_2511: i32 = 9;
pub const PROFILE_HEII_2385: i32 = 10;
pub const PROFILE_HEII_2306: i32 = 11;
pub const PROFILE_HEII_2253: i32 = 12;
pub const PROFILE_HEII_4686: i32 = 13;
pub const PROFILE_HEII_4859: i32 = 14;
pub const PROFILE_HEII_4542: i32 = 15;
pub const PROFILE_HEII_4339: i32 = 16;
pub const PROFILE_HEII_4200: i32 = 17;
pub const PROFILE_HEII_4100: i32 = 18;
pub const PROFILE_HEII_4026: i32 = 19;
pub const PROFILE_HEII_3968: i32 = 20;
pub const PROFILE_HEII_3923: i32 = 21;
pub const PROFILE_HEII_10124: i32 = 22;
pub const PROFILE_HEII_6560: i32 = 23;
pub const PROFILE_HEII_5412: i32 = 24;
/// 判断谱线是否使用特殊吸收轮廓。
///
/// # 参数
///
/// * `iat` - 原子序数 (1=H, 2=He, ...)
/// * `ion` - 电离态 (1=中性, 2=一次电离, ...)
/// * `alam` - 波长 (nm)
/// * `ihe1pr` - He I 特殊轮廓标志 (>0 表示启用)
/// * `ihe2pr` - He II 特殊轮廓标志 (>0 表示启用)
///
/// # 返回值
///
/// * `0` - 普通 Voigt 轮廓
/// * `>0` - 特殊轮廓类型(见常量定义)
pub fn ispec(iat: i32, ion: i32, alam: f64, ihe1pr: i32, ihe2pr: i32) -> i32 {
// 非氢氦元素返回 0
if iat > 2 {
return PROFILE_VOIGT;
}
if iat == 1 {
// 氢线
return PROFILE_HYDROGEN;
}
// 氦线
if ion == 1 {
// He I
if (alam - 447.1).abs() < 0.5 && ihe1pr > 0 {
return PROFILE_HEI_4471;
}
if (alam - 438.8).abs() < 0.2 && ihe1pr > 0 {
return PROFILE_HEI_4388;
}
if (alam - 402.6).abs() < 0.2 && ihe1pr > 0 {
return PROFILE_HEI_4026;
}
if (alam - 492.2).abs() < 0.2 && ihe1pr > 0 {
return PROFILE_HEI_4922;
}
} else {
// He II
// 波长范围检查
if alam < 163.0 || alam > 1012.7 {
return PROFILE_VOIGT;
}
if alam < 321.0 {
if (alam - 164.0).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_1640;
}
if (alam - 320.3).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_3203;
}
if (alam - 273.3).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_2733;
}
if (alam - 251.1).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_2511;
}
if (alam - 238.5).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_2385;
}
if (alam - 230.6).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_2306;
}
if (alam - 225.3).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_2253;
}
} else if alam < 541.0 {
if alam < 392.3 {
return PROFILE_VOIGT;
}
if (alam - 468.6).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4686;
}
if (alam - 485.9).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4859;
}
if (alam - 454.2).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4542;
}
if (alam - 433.9).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4339;
}
if (alam - 420.0).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4200;
}
if (alam - 410.0).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4100;
}
if (alam - 402.6).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_4026;
}
if (alam - 396.8).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_3968;
}
if (alam - 392.3).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_3923;
}
} else {
if (alam - 1012.4).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_10124;
}
if (alam - 656.0).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_6560;
}
if (alam - 541.2).abs() < 0.2 && ihe2pr > 0 {
return PROFILE_HEII_5412;
}
}
}
PROFILE_VOIGT
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hydrogen() {
// 氢线总是返回 1
assert_eq!(ispec(1, 1, 656.3, 0, 0), PROFILE_HYDROGEN);
assert_eq!(ispec(1, 1, 486.1, 0, 0), PROFILE_HYDROGEN);
}
#[test]
fn test_other_elements() {
// 非氢氦元素返回 0
assert_eq!(ispec(3, 1, 670.8, 1, 1), PROFILE_VOIGT); // Li
assert_eq!(ispec(26, 1, 500.0, 1, 1), PROFILE_VOIGT); // Fe
}
#[test]
fn test_he_i_lines() {
// He I 线,启用特殊轮廓
assert_eq!(ispec(2, 1, 447.1, 1, 0), PROFILE_HEI_4471);
assert_eq!(ispec(2, 1, 438.8, 1, 0), PROFILE_HEI_4388);
assert_eq!(ispec(2, 1, 402.6, 1, 0), PROFILE_HEI_4026);
assert_eq!(ispec(2, 1, 492.2, 1, 0), PROFILE_HEI_4922);
// 禁用特殊轮廓
assert_eq!(ispec(2, 1, 447.1, 0, 0), PROFILE_VOIGT);
}
#[test]
fn test_he_ii_lines() {
// He II 线,启用特殊轮廓
assert_eq!(ispec(2, 2, 164.0, 0, 1), PROFILE_HEII_1640);
assert_eq!(ispec(2, 2, 468.6, 0, 1), PROFILE_HEII_4686);
assert_eq!(ispec(2, 2, 541.2, 0, 1), PROFILE_HEII_5412);
// 禁用特殊轮廓
assert_eq!(ispec(2, 2, 468.6, 0, 0), PROFILE_VOIGT);
}
#[test]
fn test_he_ii_wavelength_ranges() {
// 超出波长范围
assert_eq!(ispec(2, 2, 150.0, 0, 1), PROFILE_VOIGT); // < 163
assert_eq!(ispec(2, 2, 1100.0, 0, 1), PROFILE_VOIGT); // > 1012.7
// 321-392.3 范围内没有特殊轮廓
assert_eq!(ispec(2, 2, 350.0, 0, 1), PROFILE_VOIGT);
}
}