212 lines
5.8 KiB
Rust
212 lines
5.8 KiB
Rust
//! 硫离子光电离截面 (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");
|
|
}
|
|
}
|