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

198 lines
6.9 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.

//! 氦 I 碰撞激发速率(从非平均态到平均态)。
//!
//! 重构自 TLUSTY `CHEAVJ` 函数。
//!
//! # 功能
//!
//! - 计算从氦 I 的非平均 (l,s) 态到平均态的碰撞激发速率
//! - 使用 Storey-Hummer 速率的适当求和
//! - 支持向上跃迁到 n=2, 3, 4 的平均态
// ============================================================================
// 核心计算函数
// ============================================================================
/// 计算碰撞激发速率 CHEAVJ。
///
/// # 参数
/// - `i`: 下能级索引(使用 COLLHE 中定义的顺序)
/// - I=1: 1 sing S
/// - I=2: 2 trip S
/// - I=3: 2 sing S
/// - ...
/// - `nj`: 上能级的主量子数 (2, 3, 4)
/// - `igj`: 上能级的统计权重
/// - `colhe1`: 碰撞速率矩阵 [19][19](由 collhe 函数计算)
///
/// # 返回
/// 碰撞激发速率
pub fn cheavj(i: usize, nj: i32, igj: i32, colhe1: &[[f64; 19]; 19]) -> f64 {
// Fortran 索引是 1-basedRust 是 0-based
// colhe1 在 collhe.rs 中使用 0-based 索引
let i_idx = i; // 已经是 0-based
match nj {
2 => cheavj_n2(igj, i_idx, colhe1),
3 => cheavj_n3(igj, i_idx, colhe1),
4 => cheavj_n4(igj, i_idx, colhe1),
_ => panic!("CHEAVJ: 不支持的主量子数 NJ={},统计权重 IGJ={}", nj, igj),
}
}
/// 计算 n=2 平均态的碰撞激发速率。
fn cheavj_n2(igj: i32, i: usize, colhe1: &[[f64; 19]; 19]) -> f64 {
match igj {
// 上能级是平均单重态
4 => colhe1[i][2] + colhe1[i][4], // COLHE1(I,3) + COLHE1(I,5)
// 上能级是平均三重态
12 => colhe1[i][1] + colhe1[i][3], // COLHE1(I,2) + COLHE1(I,4)
// 上能级是单重态和三重态的平均
16 => colhe1[i][2] + colhe1[i][4] + colhe1[i][1] + colhe1[i][3],
_ => panic!("CHEAVJ: NJ=2 时不支持的统计权重 IGJ={}", igj),
}
}
/// 计算 n=3 平均态的碰撞激发速率。
fn cheavj_n3(igj: i32, i: usize, colhe1: &[[f64; 19]; 19]) -> f64 {
match igj {
// 上能级是平均单重态
9 => colhe1[i][6] + colhe1[i][10] + colhe1[i][9], // COLHE1(I,7) + COLHE1(I,11) + COLHE1(I,10)
// 上能级是平均三重态
27 => colhe1[i][5] + colhe1[i][7] + colhe1[i][8], // COLHE1(I,6) + COLHE1(I,8) + COLHE1(I,9)
// 上能级是单重态和三重态的平均
36 => colhe1[i][6] + colhe1[i][10] + colhe1[i][9]
+ colhe1[i][5] + colhe1[i][7] + colhe1[i][8],
_ => panic!("CHEAVJ: NJ=3 时不支持的统计权重 IGJ={}", igj),
}
}
/// 计算 n=4 平均态的碰撞激发速率。
fn cheavj_n4(igj: i32, i: usize, colhe1: &[[f64; 19]; 19]) -> f64 {
match igj {
// 上能级是平均单重态
16 => colhe1[i][12] + colhe1[i][18] + colhe1[i][15] + colhe1[i][17],
// COLHE1(I,13) + COLHE1(I,19) + COLHE1(I,16) + COLHE1(I,18)
// 上能级是平均三重态
48 => colhe1[i][11] + colhe1[i][13] + colhe1[i][14] + colhe1[i][16],
// COLHE1(I,12) + COLHE1(I,14) + COLHE1(I,15) + COLHE1(I,17)
// 上能级是单重态和三重态的平均
64 => colhe1[i][12] + colhe1[i][18] + colhe1[i][15] + colhe1[i][17]
+ colhe1[i][11] + colhe1[i][13] + colhe1[i][14] + colhe1[i][16],
_ => panic!("CHEAVJ: NJ=4 时不支持的统计权重 IGJ={}", igj),
}
}
// ============================================================================
// 测试
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
fn create_test_colhe1() -> [[f64; 19]; 19] {
let mut colhe1 = [[0.0; 19]; 19];
// 填充测试数据
for i in 0..19 {
for j in 0..19 {
colhe1[i][j] = (i + 1) as f64 * 0.1 + (j + 1) as f64 * 0.01;
}
}
colhe1
}
#[test]
fn test_cheavj_n2_singlet() {
let colhe1 = create_test_colhe1();
// I=1 (0-based), NJ=2, IGJ=4 (singlet)
let result = cheavj(0, 2, 4, &colhe1);
// colhe1[0][2] + colhe1[0][4] = 0.13 + 0.15 = 0.28
let expected = colhe1[0][2] + colhe1[0][4];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n2_triplet() {
let colhe1 = create_test_colhe1();
// I=1 (0-based), NJ=2, IGJ=12 (triplet)
let result = cheavj(0, 2, 12, &colhe1);
let expected = colhe1[0][1] + colhe1[0][3];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n2_combined() {
let colhe1 = create_test_colhe1();
// I=1 (0-based), NJ=2, IGJ=16 (combined)
let result = cheavj(0, 2, 16, &colhe1);
let expected = colhe1[0][2] + colhe1[0][4] + colhe1[0][1] + colhe1[0][3];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n3_singlet() {
let colhe1 = create_test_colhe1();
let result = cheavj(0, 3, 9, &colhe1);
let expected = colhe1[0][6] + colhe1[0][10] + colhe1[0][9];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n3_triplet() {
let colhe1 = create_test_colhe1();
let result = cheavj(0, 3, 27, &colhe1);
let expected = colhe1[0][5] + colhe1[0][7] + colhe1[0][8];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n4_singlet() {
let colhe1 = create_test_colhe1();
let result = cheavj(0, 4, 16, &colhe1);
let expected = colhe1[0][12] + colhe1[0][18] + colhe1[0][15] + colhe1[0][17];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n4_triplet() {
let colhe1 = create_test_colhe1();
let result = cheavj(0, 4, 48, &colhe1);
let expected = colhe1[0][11] + colhe1[0][13] + colhe1[0][14] + colhe1[0][16];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_n4_combined() {
let colhe1 = create_test_colhe1();
let result = cheavj(0, 4, 64, &colhe1);
let expected = colhe1[0][12] + colhe1[0][18] + colhe1[0][15] + colhe1[0][17]
+ colhe1[0][11] + colhe1[0][13] + colhe1[0][14] + colhe1[0][16];
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_cheavj_different_lower_levels() {
let colhe1 = create_test_colhe1();
// 测试不同的下能级
for i in 0..5 {
let result = cheavj(i, 2, 4, &colhe1);
let expected = colhe1[i][2] + colhe1[i][4];
assert!((result - expected).abs() < 1e-10);
}
}
#[test]
#[should_panic(expected = "不支持的主量子数")]
fn test_cheavj_invalid_nj() {
let colhe1 = create_test_colhe1();
cheavj(0, 5, 4, &colhe1);
}
#[test]
#[should_panic(expected = "不支持的统计权重")]
fn test_cheavj_invalid_igj() {
let colhe1 = create_test_colhe1();
cheavj(0, 2, 999, &colhe1);
}
}