//! H⁻ 自由-自由吸收截面。 //! //! 重构自 TLUSTY `sffhmi.f` //! //! 来自 Bell and Berrington J.Phys.B, vol. 20, 801-806, 1987。 //! 取自 Kurucz ATLAS9。 use crate::math::ylintp; use std::sync::OnceLock; /// 初始化的自由-自由数据 struct FfData { wfflog: [f64; 22], fflog: [[f64; 11]; 22], } static FF_DATA: OnceLock = OnceLock::new(); fn get_ff_data() -> &'static FfData { FF_DATA.get_or_init(|| { // 波长数据 (μm) const WAVEK: [f64; 22] = [ 0.50, 0.40, 0.35, 0.30, 0.25, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10, 0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01, 0.008, 0.006, ]; const THETAFF: [f64; 11] = [ 0.5, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.8, 3.6, ]; // FFCS 数据 (11 x 22) const FFBEG: [[f64; 11]; 11] = [ [ 1.0178, 0.0222, 0.0308, 0.0402, 0.0498, 0.0596, 0.0695, 0.0795, 0.0896, 0.131, 0.172, ], [ 0.0228, 0.0280, 0.0388, 0.0499, 0.0614, 0.0732, 0.0851, 0.0972, 0.110, 0.160, 0.211, ], [ 0.0277, 0.0342, 0.0476, 0.0615, 0.0760, 0.0908, 0.105, 0.121, 0.136, 0.199, 0.262, ], [ 0.0364, 0.0447, 0.0616, 0.0789, 0.0966, 0.114, 0.132, 0.150, 0.169, 0.243, 0.318, ], [ 0.0520, 0.0633, 0.0859, 0.108, 0.131, 0.154, 0.178, 0.201, 0.225, 0.321, 0.418, ], [ 0.0791, 0.0959, 0.129, 0.161, 0.194, 0.227, 0.260, 0.293, 0.327, 0.463, 0.602, ], [ 0.0965, 0.117, 0.157, 0.195, 0.234, 0.272, 0.311, 0.351, 0.390, 0.549, 0.711, ], [ 0.121, 0.146, 0.195, 0.241, 0.288, 0.334, 0.381, 0.428, 0.475, 0.667, 0.861, ], [ 0.154, 0.188, 0.249, 0.309, 0.367, 0.424, 0.482, 0.539, 0.597, 0.830, 1.07, ], [ 0.208, 0.250, 0.332, 0.409, 0.484, 0.557, 0.630, 0.702, 0.774, 1.06, 1.36, ], [ 0.293, 0.354, 0.468, 0.576, 0.677, 0.777, 0.874, 0.969, 1.06, 1.45, 1.83, ], ]; const FFEND: [[f64; 11]; 11] = [ [ 0.358, 0.432, 0.572, 0.702, 0.825, 0.943, 1.06, 1.17, 1.28, 1.73, 2.17, ], [ 0.448, 0.539, 0.711, 0.871, 1.02, 1.16, 1.29, 1.43, 1.57, 2.09, 2.60, ], [ 0.579, 0.699, 0.924, 1.13, 1.33, 1.51, 1.69, 1.86, 2.02, 2.67, 3.31, ], [ 0.781, 0.940, 1.24, 1.52, 1.78, 2.02, 2.26, 2.48, 2.69, 3.52, 4.31, ], [ 1.11, 1.34, 1.77, 2.17, 2.53, 2.87, 3.20, 3.51, 3.80, 4.92, 5.97, ], [ 1.73, 2.08, 2.74, 3.37, 3.90, 4.50, 5.01, 5.50, 5.95, 7.59, 9.06, ], [ 3.04, 3.65, 4.80, 5.86, 6.86, 7.79, 8.67, 9.50, 10.3, 13.2, 15.6, ], [ 6.79, 8.16, 10.7, 13.1, 15.3, 17.4, 19.4, 21.2, 23.0, 29.5, 35.0, ], [ 27.0, 32.4, 42.6, 51.9, 60.7, 68.9, 76.8, 84.2, 91.4, 117., 140., ], [ 42.3, 50.6, 66.4, 80.8, 94.5, 107., 120., 131., 142., 183., 219., ], [ 75.1, 90.0, 118., 144., 168., 191., 212., 234., 253., 325., 388., ], ]; // 合并 FFBEG 和 FFEND 成 FFCS (11 x 22) // EQUIVALENCE (FFCS(1,1),FFBEG(1,1)),(FFCS(1,12),FFEND(1,1)) let mut ffcs = [[0.0; 22]; 11]; for i in 0..11 { for j in 0..11 { ffcs[i][j] = FFBEG[i][j]; } for j in 0..11 { ffcs[i][j + 11] = FFEND[i][j]; } } // 计算对数 let mut wfflog = [0.0; 22]; let mut fflog = [[0.0; 11]; 22]; for iwave in 0..22 { wfflog[iwave] = (91.134 / WAVEK[iwave]).ln(); for itheta in 0..11 { fflog[iwave][itheta] = (ffcs[itheta][iwave] * 1e-26).ln(); } } FfData { wfflog, fflog } }) } /// H⁻ 自由-自由吸收截面。 /// /// 计算负氢离子的自由-自由吸收截面。 /// /// # 参数 /// /// * `popi` - H⁻ 粒子数密度 /// * `fr` - 频率 (Hz) /// * `t` - 温度 (K) /// /// # 返回值 /// /// H⁻ 自由-自由吸收系数。 /// /// # 备注 /// /// 数据来自 Bell and Berrington J.Phys.B, vol. 20, 801-806, 1987。 pub fn sffhmi(popi: f64, fr: f64, t: f64) -> f64 { const CONFF: f64 = 5040.0 * 1.380658e-16; const CONTH: f64 = 5040.0; const HK: f64 = 4.79928144e-11; const THETAFF: [f64; 11] = [ 0.5, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.8, 3.6, ]; let data = get_ff_data(); let wave = 2.99792458e17 / fr; let wavelog = wave.ln(); // 对每个 theta 值进行插值 let mut fftt = [0.0; 11]; for itheta in 0..11 { let fflog2: Vec = (0..22).map(|iw| data.fflog[iw][itheta]).collect(); let fftlog = ylintp(&data.wfflog, &fflog2, wavelog); fftt[itheta] = fftlog.exp() / THETAFF[itheta] * CONFF; } // 对温度进行插值 let theta = CONTH / t; let ffth = ylintp(&THETAFF, &fftt, theta); ffth * popi / (1.0 - (-HK * fr / t).exp()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_sffhmi_basic() { // 基本测试 let result = sffhmi(1e10, 5e14, 6000.0); assert!(result.is_finite()); assert!(result > 0.0); } #[test] fn test_sffhmi_uv() { // 紫外范围 let result = sffhmi(1e10, 1e15, 8000.0); assert!(result.is_finite()); assert!(result > 0.0); } #[test] fn test_sffhmi_visible() { // 可见光范围 let result = sffhmi(1e10, 5e14, 5000.0); assert!(result.is_finite()); assert!(result > 0.0); } #[test] fn test_sffhmi_scaling() { // 应随 popi 线性增加 let r1 = sffhmi(1e10, 5e14, 6000.0); let r2 = sffhmi(2e10, 5e14, 6000.0); assert!((r2 / r1 - 2.0).abs() < 0.01); } }