SpectraRust/src/synspec/math/starkir.rs
2026-03-25 13:31:23 +08:00

137 lines
3.6 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.

//! Stark 加宽轮廓计算(改进版)。
//!
//! 重构自 SYNSPEC `starkir.f`
use crate::tlusty::math::eint;
/// 物理常量
const PI: f64 = 3.14159265;
const PI2: f64 = 2.0 * PI;
const OS0: f64 = 0.026564;
const RYD: f64 = 3.28805e15;
const CL: f64 = 2.997925e10;
const Y2CON: f64 = PI * PI * 0.5 / OS0 / CL;
const HK: f64 = 4.79928144e-11;
/// 计算 Stark 加宽轮廓(改进版)。
///
/// # 参数
///
/// * `ii` - 下能级主量子数
/// * `jj` - 上能级主量子数
/// * `t` - 温度 (K)
/// * `ane` - 电子密度
/// * `beta` - Doppler 宽度参数
/// * `dbeta` - 波长相关系数 (来自 COMMON/AUXHYD/)
///
/// # 返回值
///
/// Stark 加宽轮廓值
///
/// # 备注
///
/// 这是用于氢线 Stark 加宽的改进算法。
/// 使用了量子力学微扰理论和等离子体效应的组合。
pub fn starkir(ii: i32, jj: i32, t: f64, ane: f64, beta: f64, dbeta: f64) -> f64 {
let del = beta / dbeta;
let hkt = HK / t;
let xii = ii as f64;
let xjj = jj as f64;
let xx = xii / xjj;
let dd = 2.0 * xjj * RYD / del;
let y1 = xjj * del * 0.5 * hkt;
let y2 = Y2CON * del * del / ane;
// 计算统计因子 QSTAT
let y1_sq = y1 * y1;
let qstat = 1.5 + 0.5 * (y1_sq - 1.384) / (y1_sq + 1.384);
let mut qimpa = 0.0;
// 计算 QIMPA
if !(y1 > 8.0 || y1 >= y2) {
let exy2 = if y2 <= 8.0 {
let (e1, _, _) = eint(y2);
e1
} else {
0.0
};
let (e1_y1, _, _) = eint(y1);
qimpa = 1.438 * (y1 * (1.0 - xx)).sqrt()
* (0.4 * (-y1).exp() + e1_y1 - 0.5 * exy2);
}
// 计算轮廓
let (prof, ratio) = if beta <= 20.0 {
let prof = 8.0 / (80.0 + beta * beta * beta);
let ratio = qstat + qimpa;
(prof, ratio)
} else {
let prof = 1.5 / beta / beta / beta.sqrt();
let dioi = PI2 * 1.48e-25 * dd * ane
* (dd.sqrt() * (1.3 * qstat + 0.3 * qimpt()) - 3.9 * RYD * hkt);
let ratio = qstat * (1.0 + dioi).min(1.25) + qimpa;
(prof, ratio)
};
prof * ratio
}
/// 计算 QIMPT简化版
///
/// 这是一个占位函数,在完整实现中应该从其他模块获取。
fn qimpt() -> f64 {
// TODO: 这个值在原始代码中没有直接定义
// 需要进一步研究 SYNSPEC 源码来确定正确的实现
0.0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_starkir_basic() {
// 基本测试H-alpha 线 (n=3 -> n=2)
let result = starkir(2, 3, 10000.0, 1e13, 5.0, 1.0);
assert!(result.is_finite());
assert!(result > 0.0);
}
#[test]
fn test_starkir_beta_small() {
// beta <= 20 的情况
let result = starkir(2, 3, 10000.0, 1e13, 10.0, 1.0);
assert!(result.is_finite());
assert!(result > 0.0);
}
#[test]
fn test_starkir_beta_large() {
// beta > 20 的情况
let result = starkir(2, 3, 10000.0, 1e13, 50.0, 1.0);
assert!(result.is_finite());
assert!(result > 0.0);
}
#[test]
fn test_starkir_y1_large() {
// y1 > 8 的情况(跳过 qimpa 计算)
let result = starkir(2, 3, 1000.0, 1e10, 5.0, 0.001);
assert!(result.is_finite());
assert!(result > 0.0);
}
#[test]
fn test_starkir_different_quantum_numbers() {
// 测试不同量子数
let r1 = starkir(1, 2, 10000.0, 1e13, 5.0, 1.0); // Lyman-alpha
let r2 = starkir(3, 4, 10000.0, 1e13, 5.0, 1.0); // Paschen-alpha
let r3 = starkir(2, 4, 10000.0, 1e13, 5.0, 1.0); // H-beta
assert!(r1.is_finite());
assert!(r2.is_finite());
assert!(r3.is_finite());
}
}