198 lines
6.9 KiB
Rust
198 lines
6.9 KiB
Rust
//! 氦 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-based,Rust 是 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);
|
||
}
|
||
}
|