SpectraRust/src/tlusty/math/atomic/vern18.rs
2026-03-25 18:34:41 +08:00

169 lines
4.7 KiB
Rust

//! 氩离子光电离截面 (Verner 1996)。
//!
//! 重构自 TLUSTY `vern18.f`
//!
//! 参考:
//! - Verner D.A. et al. 1996, ApJ 465
//! - Verner & Yakovlev 1995, A&AS 109, 125
use crate::tlusty::state::constants::{HALF, UN};
// ============================================================================
// VERN18 - 氩离子光电离截面
// ============================================================================
const T18: f64 = 1e-18;
const MVER: usize = 18;
// 1996 参数
static S0: [f64; MVER] = [
2.106e1, 2.503e1, 3.58e1, 2.035e1, 9.946, 1.080, 3.693,
3.295e1, 8.279e-1, 8.204, 1.76e3, 7.018e-1, 2.459e-2,
4.997e-2, 2.571e4, 2.135e1, 3.108e1, 1.69e2
];
static E0: [f64; MVER] = [
17.09, 24.94, 14.17, 6.953, 10.31, 0.544, 0.02966, 3.844,
0.1926, 10.4, 0.1257, 5.31, 0.3209, 1.557, 18.88, 41.54,
446.8, 139.9
];
static EMX: [f64; MVER] = [
249.2, 266.2, 280.1, 298.7, 320., 342.6, 366.7, 392.5, 3361.,
3446., 3523., 3613., 3702., 3798., 3898., 3988., 5e4, 5e4
];
static Y0: [f64; MVER] = [
1.688, 0.9299, 2.384, 7.501, 6.406, 1.7e2, 4.383e-4, 0., 38.14,
38.04, 3.286e-3, 1.099e2, 2.068e3, 4.552e2, 2.445e-2, 0., 0., 0.
];
static Y1: [f64; MVER] = [
0.8943, 0.7195, 1.794, 0.1806, 3.659e-3, 15.87, 2.513, 0., 4.649,
0.639, 0.3226, 0.2202, 21.13, 6.459, 1.054e-2, 0., 0., 0.
];
static YW: [f64; MVER] = [
0.4185, 0.5108, 0.6316, 0.8842, 0.4885, 11.07, 1.363e-2, 0.,
1.434, 9.203e-4, 1.975, 0.4987, 0.6692, 0.2938, 29.09, 0., 0., 0.
];
static YA: [f64; MVER] = [
2.645e2, 1.272e2, 3.776e1, 1.4e1, 7.444e1, 9.419e2, 9.951e3,
7.082e2, 2.392e2, 1.495e1, 1.579e3, 1.001e2, 2.285e3, 5.031e2,
1.475, 4.118e1, 3.039e1, 3.288e1
];
static PV: [f64; MVER] = [
4.796, 4.288, 5.742, 9.595, 6.261, 7.582, 7.313, 4.645, 11.21,
11.15, 6.714, 8.939, 8.81, 8.966, 26.34, 4.945, 2.092, 2.963
];
// 1995 参数 (高能)
static S95: [f64; MVER] = [
8.372e1, 1.937e2, 2.281e2, 2.007e2, 2.474e2, 2.786e2, 3.204e2,
4.198e2, 2.931e1, 1.585e1, 2.796e1, 1.666e1, 2.888e1, 2.874e1,
2.883e1, 3.003e1, 3.108e1, 1.69e2
];
static E95: [f64; MVER] = [
164.7, 108.5, 102.5, 107.3, 98.35, 92.33, 85.63, 73.68, 467.9,
612.6, 478.9, 602.8, 473.1, 474.9, 475.6, 468., 466.8, 139.9
];
static Y95: [f64; MVER] = [
54.52, 70., 43.8, 70., 42.84, 42.2, 42.3, 44.19, 17.44, 50.,
19.17, 50., 20.42, 22.35, 26.15, 28.54, 30.39, 32.88
];
static YW95: [f64; MVER] = [
0.627, 0.1, 7.167e-3, 0.1, 7.283e-3, 7.408e-3, 7.258e-3,
7.712e-3, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.
];
static P95: [f64; MVER] = [
3.328, 3.7, 4.046, 3.7, 4.125, 4.227, 4.329, 4.492, 2.362,
1.65, 2.271, 1.65, 2.234, 2.171, 2.074, 2.037, 2.092, 2.963
];
/// 计算氩离子基态光电离截面。
///
/// # 参数
///
/// - `e` - 光子能量 (Rydberg)
/// - `izz` - 离子电荷 (1-18, 对应 Ar I - Ar XVIII)
///
/// # 返回
///
/// 光电离截面 (cm²)
pub fn vern18(e: f64, izz: usize) -> f64 {
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 <= 8 { 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_vern18_ar_ii() {
let izz = 2;
let e = E0[izz - 1];
let sigma = vern18(e, izz);
assert!(sigma > 0.0);
}
#[test]
fn test_vern18_ar_i_low_energy() {
let izz = 1;
let e = 50.0;
let sigma = vern18(e, izz);
assert!(sigma > 0.0);
}
#[test]
fn test_vern18_ar_i_high_energy() {
let izz = 1;
let e = 300.0; // 高于 EMX[0] = 249.2
let sigma = vern18(e, izz);
assert!(sigma > 0.0);
}
#[test]
fn test_vern18_invalid_izz() {
assert_eq!(vern18(10.0, 0), 0.0);
assert_eq!(vern18(10.0, 19), 0.0);
}
#[test]
fn test_vern18_decreasing_with_energy() {
let izz = 1;
let sigma_low = vern18(30.0, izz);
let sigma_high = vern18(100.0, izz);
assert!(sigma_low > sigma_high);
}
}