//! 硫离子光电离截面 (Verner 1996)。 //! //! 重构自 TLUSTY `vern16.f` //! //! 参考: //! - Verner D.A. et al. 1996, ApJ 465 //! - Verner & Yakovlev 1995, A&AS 109, 125 use crate::tlusty::state::constants::{HALF, UN}; // ============================================================================ // VERN16 - 硫离子光电离截面 // ============================================================================ const T18: f64 = 1e-18; const MVER: usize = 16; // 1996 参数 static S0: [f64; MVER] = [ 4.564e4, 3.136e2, 6.666, 2.606, 5.072e-4, 9.139, 5.703e-1, 3.161e1, 9.646e3, 5.364e1, 1.275e1, 3.49e-1, 2.294e4, 2.555e1, 2.453e1, 2.139e2 ]; static E0: [f64; MVER] = [ 18.08, 8.787, 2.027, 2.173, 0.1713, 14.13, 0.3757, 14.62, 0.1526, 10.4, 6.485, 2.443, 14.74, 33.1, 439., 110.4 ]; static EMX: [f64; MVER] = [ 170., 184.6, 199.5, 216.4, 235., 255.7, 2569., 2641., 2705., 2782., 2859., 2941., 3029., 3107., 5e4, 5e4 ]; static Y0: [f64; MVER] = [ 0.9935, 2.782, 15.68, 19.75, 94.24, 0., 222.2, 18.69, 1.615e-3, 17.75, 34.26, 227.9, 2.203e-2, 0., 0., 0. ]; static Y1: [f64; MVER] = [ 0.2486, 0.1788, 9.421, 3.361, 0.6265, 0., 4.606, 0.3037, 0.4049, 1.663, 0.137, 1.172, 1.073e-2, 0., 0., 0. ]; static YW: [f64; MVER] = [ 0.6385, 0.7354, 4.109, 1.863, 0.788, 0., 1.503, 1.153e-3, 1.492, 2.31, 1.678, 0.7033, 27.38, 0., 0., 0. ]; static YA: [f64; MVER] = [ 1., 3.442, 54.54, 66.41, 198.6, 1656., 146., 16.11, 1438., 36.41, 65.83, 541.1, 1.529, 38.21, 44.05, 32.88 ]; static PV: [f64; MVER] = [ 13.61, 12.81, 8.611, 8.655, 13.07, 3.626, 11.35, 8.642, 5.977, 7.09, 7.692, 7.769, 25.68, 5.037, 1.765, 2.963 ]; // 1995 参数 (高能) static S95: [f64; MVER] = [ 1.883e2, 1.896e2, 1.780e2, 2.037e2, 2.919e2, 4.712e2, 1.916e1, 1.931e1, 1.946e1, 2.041e1, 2.101e1, 2.087e1, 2.233e1, 2.293e1, 2.453e1, 2.139e2 ]; static E95: [f64; MVER] = [ 91.52, 90.58, 92.46, 87.44, 74.11, 57.47, 495.2, 489.1, 493.7, 480.2, 475.8, 482.8, 466.9, 466.7, 439., 110.4 ]; static Y95: [f64; MVER] = [ 71.93, 75.38, 149.8, 93.1, 48.64, 36.1, 35.55, 50., 35.68, 50., 50., 37.42, 50., 44.59, 44.05, 32.88 ]; static YW95: [f64; MVER] = [ 0.2485, 0.2934, 0.02142, 9.497e-3, 0.02785, 0.0248, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ]; static P95: [f64; MVER] = [ 3.633, 3.635, 3.319, 3.565, 4.142, 4.742, 1.742, 1.65, 1.737, 1.65, 1.65, 1.72, 1.65, 1.668, 1.765, 2.963 ]; /// 计算硫离子基态光电离截面。 /// /// # 参数 /// /// - `e` - 光子能量 (Rydberg) /// - `izz` - 离子电荷 (1-16, 对应 S I - S XVI) /// /// # 返回 /// /// 光电离截面 (cm²) /// /// # Fortran 原始代码 /// /// ```fortran /// FUNCTION VERN16(E,IZZ) /// ... /// IVER=IZZ /// IF(E.LT.EMX(IVER)) THEN /// ! 1996 Expression /// XX=E/E0(IVER)-Y0(IVER) /// YY=SQRT(XX*XX+Y1(IVER)*Y1(IVER)) /// AA=(XX-UN)*(XX-UN)+YW(IVER)*YW(IVER) /// BB=YY**(HALF*PV(IVER)-5.5) /// CC=(UN+SQRT(YY/YA(IVER)))**PV(IVER) /// FY=AA*BB/CC /// VERN16=S0(IVER)*T18*FY /// ELSE /// ! 1995 Expression for high energies /// YY=E/E95(IVER) /// XL=0. /// IF(IZZ.LE.6) XL=UN /// Q=HALF*P95(IVER)-5.5-XL /// AA=(YY-UN)*(YY-UN)+YW95(IVER)*YW95(IVER) /// BB=YY**Q /// CC=(UN+SQRT(YY/Y95(IVER)))**P95(IVER) /// FY=AA*BB/CC /// VERN16=S95(IVER)*T18*FY /// END IF /// END /// ``` pub fn vern16(e: f64, izz: usize) -> f64 { // Fortran: IZZ = 1..16 → Rust: izz = 0..15 if izz == 0 || izz > MVER { return 0.0; } let iver = izz - 1; // 转换为 0-indexed if e < EMX[iver] { // 1996 表达式 let xx = e / E0[iver] - Y0[iver]; let yy = (xx * xx + Y1[iver] * Y1[iver]).sqrt(); let aa = (xx - UN) * (xx - UN) + YW[iver] * YW[iver]; let bb = yy.powf(HALF * PV[iver] - 5.5); let cc = (UN + (yy / YA[iver]).sqrt()).powf(PV[iver]); let fy = aa * bb / cc; S0[iver] * T18 * fy } else { // 1995 高能表达式 (内壳层电离) let yy = e / E95[iver]; let xl = if izz <= 6 { UN } else { 0.0 }; let q = HALF * P95[iver] - 5.5 - xl; let aa = (yy - UN) * (yy - UN) + YW95[iver] * YW95[iver]; let bb = yy.powf(q); let cc = (UN + (yy / Y95[iver]).sqrt()).powf(P95[iver]); let fy = aa * bb / cc; S95[iver] * T18 * fy } } #[cfg(test)] mod tests { use super::*; #[test] fn test_vern16_s_ii() { // S II (izz=2) 在阈值附近 let izz = 2; let e = E0[izz - 1]; // 阈值能量 let sigma = vern16(e, izz); assert!(sigma > 0.0, "sigma should be positive at threshold"); } #[test] fn test_vern16_s_i_low_energy() { // S I (izz=1) 低能区 let izz = 1; let e = 10.0; // 低于 EMX[0] = 170 let sigma = vern16(e, izz); assert!(sigma > 0.0, "sigma should be positive"); } #[test] fn test_vern16_s_i_high_energy() { // S I (izz=1) 高能区 let izz = 1; let e = 200.0; // 高于 EMX[0] = 170 let sigma = vern16(e, izz); assert!(sigma > 0.0, "sigma should be positive"); } #[test] fn test_vern16_zero_energy() { // 零能量 let sigma = vern16(0.0, 1); assert!(sigma >= 0.0); } #[test] fn test_vern16_invalid_izz() { // 无效的 izz let sigma = vern16(10.0, 0); // 0 无效 assert_eq!(sigma, 0.0); let sigma = vern16(10.0, 17); // 17 超出范围 assert_eq!(sigma, 0.0); } #[test] fn test_vern16_decreasing_with_energy() { // 截面应该随能量增加而减小 let izz = 1; let sigma_low = vern16(20.0, izz); let sigma_high = vern16(100.0, izz); assert!(sigma_low > sigma_high, "sigma should decrease with energy"); } }