SpectraRust/src/math/stark0.rs
2026-03-19 14:05:33 +08:00

130 lines
3.2 KiB
Rust

//! Stark 轮廓辅助函数。
//!
//! 重构自 TLUSTY `stark0.f`
/// Stark 轮廓辅助参数计算。
///
/// 计算氢线近似 Stark 轮廓所需的频率无关参数。
///
/// # 参数
///
/// * `i` - 下能级主量子数
/// * `j` - 上能级主量子数
/// * `izz` - 离子电荷 (1 为氢)
///
/// # 返回值
///
/// (xkij, wl0, fij) 元组:
/// - xkij: Holtsmark 轮廓的 K(i,j) 系数
/// - wl0: 谱线波长
/// - fij: Stark f 值
///
/// # 备注
///
/// j≤6 时使用精确值,更高时使用渐近公式。
pub fn stark0(i: usize, j: usize, izz: usize) -> (f64, f64, f64) {
const RYD1: f64 = 911.763811;
const RYD2: f64 = 911.495745 / 4.0;
const CXKIJ: f64 = 5.5e-5;
const WI1: f64 = 911.753578;
const WI2: f64 = 227.837832;
// XKIJ 表格 (5 x 4)
const XKIJT: [[f64; 4]; 5] = [
[3.56e-4, 0.0125, 0.124, 0.683],
[5.23e-4, 0.0177, 0.171, 0.866],
[1.09e-3, 0.028, 0.223, 1.02],
[1.49e-3, 0.0348, 0.261, 1.19],
[2.25e-3, 0.0493, 0.342, 1.46],
];
// FSTARK 表格 (10 x 4)
const FSTARK: [[f64; 4]; 10] = [
[0.1387, 0.3921, 0.6103, 0.8163],
[0.0791, 0.1193, 0.1506, 0.1788],
[0.02126, 0.03766, 0.04931, 0.05985],
[0.01394, 0.02209, 0.02768, 0.03189],
[0.00642, 0.01139, 0.01485, 0.01762],
[4.814e-3, 8.036e-3, 0.01023, 0.01196],
[2.779e-3, 5.007e-3, 6.588e-3, 7.825e-3],
[2.216e-3, 3.85e-3, 4.996e-3, 5.882e-3],
[1.443e-3, 2.658e-3, 3.524e-3, 4.233e-3],
[1.201e-3, 2.151e-3, 2.838e-3, 3.375e-3],
];
let ii = (i * i) as f64;
let jj = (j * j) as f64;
let jmin = j - i;
// 计算 XKIJ
let xkij = if jmin <= 5 {
XKIJT[jmin - 1][i - 1]
} else {
CXKIJ * (ii * jj) * (ii * jj) / (jj - ii)
};
// 计算 FIJ
let fij = if jmin <= 10 {
FSTARK[jmin - 1][i - 1]
} else {
let cfij = ((20.0 * i as f64 + 100.0) * j as f64) / ((i as f64 + 10.0) * (jj - ii));
FSTARK[9][i - 1] * cfij * cfij * cfij
};
// 计算波长
let wl0_base = if izz == 2 { WI2 } else { WI1 };
let wl0 = wl0_base / (1.0 / ii - 1.0 / jj);
(xkij, wl0, fij)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stark0_h_alpha() {
// H-alpha: i=2, j=3
let (xkij, wl0, fij) = stark0(2, 3, 1);
assert!(xkij > 0.0);
assert!(wl0 > 0.0);
assert!(fij > 0.0);
}
#[test]
fn test_stark0_h_beta() {
// H-beta: i=2, j=4
let (xkij, wl0, fij) = stark0(2, 4, 1);
assert!(xkij > 0.0);
assert!(wl0 > 0.0);
assert!(fij > 0.0);
}
#[test]
fn test_stark0_he_ii() {
// He II: izz=2
let (xkij, wl0, fij) = stark0(2, 3, 2);
assert!(xkij > 0.0);
assert!(wl0 > 0.0);
assert!(fij > 0.0);
}
#[test]
fn test_stark0_high_j() {
// j > 6 使用渐近公式
let (xkij, wl0, fij) = stark0(2, 10, 1);
assert!(xkij > 0.0);
assert!(wl0 > 0.0);
assert!(fij > 0.0);
}
#[test]
fn test_stark0_jmin_gt_10() {
// j - i > 10
let (xkij, wl0, fij) = stark0(2, 15, 1);
assert!(xkij > 0.0);
assert!(wl0 > 0.0);
assert!(fij > 0.0);
}
}