137 lines
3.6 KiB
Rust
137 lines
3.6 KiB
Rust
//! 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());
|
||
}
|
||
}
|