SpectraRust/src/tlusty/math/utils/irc.rs
2026-04-01 16:35:36 +08:00

120 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 氢原子碰撞电离速率。
//!
//! 重构自 TLUSTY `irc.f`
//!
//! 基于 Johnson (1972)。
use crate::tlusty::math::{expinx, szirc};
// f2r_depends: EXPINX, SZIRC
/// 氢原子碰撞电离激发速率。
///
/// 计算从状态 N 由于电子碰撞导致的氢原子电离激发速率。
///
/// # 参数
///
/// * `n` - 主量子数
/// * `t` - 温度 (K)
/// * `ic` - 电荷 (1 = H)
/// * `rno` - 连续谱起始能级
///
/// # 返回值
///
/// 激发速率 SE (cm³/s)。
///
/// # 备注
///
/// 基于 Johnson (1972)。
/// Tim Kallman 的 XSTAR 程序的修改版本。
pub fn irc(n: i32, t: f64, ic: i32, rno: f64) -> f64 {
// 非 H 原子调用 szirc
if ic != 1 {
return szirc(n as usize, t, ic, rno);
}
let nf = n as f64;
let xo = 1.0 - nf * nf / rno / rno;
let yn = xo * 157803.0 / (t * nf * nf);
let (an, bn, rn) = if n <= 1 {
let an = 1.9603 * nf
* (1.133 / 3.0 / xo.powi(3) - 0.4059 / 4.0 / xo.powi(4) + 0.07014 / 5.0 / xo.powi(5));
let bn = 2.0 / 3.0 * nf * nf / xo * (3.0 + 2.0 / xo - 0.603 / (xo * xo));
let rn = 0.45;
(an, bn, rn)
} else if n == 2 {
let an = 1.9603 * nf
* (1.0785 / 3.0 / xo.powi(3) - 0.2319 / 4.0 / xo.powi(4) + 0.02947 / 5.0 / xo.powi(5));
let bn = (4.0 - 18.63 / nf + 36.24 / (nf * nf) - 28.09 / (nf * nf * nf)) / nf;
let bn = 2.0 / 3.0 * nf * nf / xo * (3.0 + 2.0 / xo + bn / (xo * xo));
let rn = 0.653;
(an, bn, rn)
} else {
let g0 = (0.9935 + 0.2328 / nf - 0.1296 / (nf * nf)) / 3.0 / xo.powi(3);
let g1 = -(0.6282 - 0.5598 / nf + 0.5299 / (nf * nf)) / (nf * 4.0) / xo.powi(4);
let g2 = (0.3887 - 1.181 / nf + 1.470 / (nf * nf)) / (nf * nf * 5.0) / xo.powi(5);
let an = 1.9603 * nf * (g0 + g1 + g2);
let bn = (4.0 - 18.63 / nf + 36.24 / (nf * nf) - 28.09 / (nf * nf * nf)) / nf;
let bn = (3.0 + 2.0 / xo + bn / (xo * xo)) * 2.0 * nf * nf / 3.0 / xo;
let rn = 1.94 * nf.powf(-1.57);
(an, bn, rn)
};
let rn = rn * xo;
let zn = rn + yn;
let ey = expinx(yn);
let ez = expinx(zn);
let mut se = an * (ey / (yn * yn) - (-rn).exp() * ez / (zn * zn));
let ey = 1.0 + 1.0 / yn - ey * (2.0 / yn + 1.0);
let ez = (-rn).exp() * (1.0 + 1.0 / zn - ez * (2.0 / zn + 1.0));
se = se + (bn - an * (2.0 * nf * nf / xo).ln()) * (ey - ez);
se = se * t.sqrt() * yn * yn * nf * nf * 1.095e-10 / xo;
se
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_irc_hydrogen_n1() {
// H I 从 n=1 电离rno > n² = 1
let result = irc(1, 10000.0, 1, 2.0);
assert!(result.is_finite());
}
#[test]
fn test_irc_hydrogen_n2() {
// H I 从 n=2 电离rno > n² = 4
let result = irc(2, 10000.0, 1, 5.0);
assert!(result.is_finite());
}
#[test]
fn test_irc_hydrogen_n3() {
// H I 从 n=3 电离rno > n² = 9
let result = irc(3, 10000.0, 1, 10.0);
assert!(result.is_finite());
}
#[test]
fn test_irc_hydrogen_high_temp() {
// 高温
let result = irc(1, 50000.0, 1, 2.0);
assert!(result.is_finite());
}
#[test]
fn test_irc_non_hydrogen() {
// 非 H 原子 (调用 szirc)
let result = irc(1, 10000.0, 2, 2.0);
assert!(result.is_finite());
}
}