新增 TLUSTY 模块: - crossd: 光电离截面评估 (bound-free cross section) - sgmer0: 合并能级光电离截面初始化 - sgmerd: 合并能级光电离截面计算 - dwnfr0: 频率网格下载 (continuum) - convc1: 对流收敛控制 (radiative) - chckse: 统计平衡检查 (rates) 扩展 RESOLV 编排器: - 添加 Feautrier 形式解 - 添加 Lucy 温度修正 - 添加 ROSSTD/PZEVAL/CONOUT 调用 - 添加 IFPOPR=2 占据数更新 - 添加 HESOL6 流体静力平衡修正 修复: - sgmer0.rs: 修复 config 未声明为 mut 的编译错误 - crossd.rs: 修复测试中使用错误字段路径的问题 (frqall.ijbf/phoexp.aijbf/phoexp.bfcs 而非 obfpar) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
164 lines
4.5 KiB
Rust
164 lines
4.5 KiB
Rust
//! 光致电离截面插值(Hidalgo 1968)。
|
||
//!
|
||
//! 重构自 SYNSPEC `hidalg.f`
|
||
//!
|
||
//! 使用 Hidalgo (1968, Ap. J., 153, 981) 的波长和光致电离截面数据表,
|
||
//! 对给定频率进行线性插值。
|
||
|
||
/// 波长网格 1 (Å),用于 INDEX < 13 的物种
|
||
const WL1: [f64; 20] = [
|
||
39.1, 80.9, 97.6, 100.1, 104.3, 107.2, 108.7, 111.9, 113.6, 115.4,
|
||
117.1, 119.0, 124.8, 126.9, 129.1, 131.3, 133.6, 136.0, 138.5, 141.1,
|
||
];
|
||
|
||
/// 波长网格 2 (Å),用于 INDEX >= 13 的物种
|
||
const WL2: [f64; 20] = [
|
||
68.5, 80.9, 100.1, 120.9, 158.8, 165.7, 177.3, 190.6, 200.7, 206.2,
|
||
211.9, 218.0, 224.5, 231.3, 246.3, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
];
|
||
|
||
/// 光致电离截面数据 (Mbarn),20×24 矩阵(列优先存储)
|
||
const SIG0: [[f64; 20]; 24] = [
|
||
[0.0; 20], // col 1
|
||
[
|
||
0.0460, 0.2400, 0.3500, 0.3700, 0.4000, 0.4300, 0.4400, 0.4600, 0.4700, 0.4900,
|
||
0.5000, 0.5200, 0.5700, 0.6200, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
], // col 2
|
||
[0.0; 20], // col 3
|
||
[
|
||
0.0092, 0.1000, 0.1900, 0.2100, 0.2300, 0.2500, 0.2600, 0.2900, 0.3000, 0.3200,
|
||
0.3400, 0.3500, 0.4100, 0.4300, 0.4500, 0.4800, 0.5000, 0.5300, 0.5600, 0.5900,
|
||
], // col 4
|
||
[
|
||
0.3400, 0.4600, 0.6300, 0.7700, 0.9100, 1.080, 0.0, 0.0, 0.0, 0.0,
|
||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
], // col 5
|
||
[0.0; 20], // col 6
|
||
[
|
||
0.0064, 0.1100, 0.2200, 0.4100, 0.9400, 1.000, 1.300, 1.600, 0.0, 0.0,
|
||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
], // col 7
|
||
[0.0; 20], // col 8
|
||
[
|
||
0.0370, 0.0650, 0.1300, 0.2400, 0.5500, 0.6300, 0.7700, 0.9500, 1.100, 1.250,
|
||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
], // col 9
|
||
[0.0; 20], // col 10
|
||
[
|
||
0.0220, 0.0390, 0.0800, 0.1500, 0.3500, 0.4000, 0.4900, 0.6200, 0.7200, 0.7800,
|
||
0.8500, 0.9300, 1.020, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||
], // col 11
|
||
[0.0; 20], // col 12
|
||
[0.0; 20], // col 13
|
||
[0.0; 20], // col 14
|
||
[0.0; 20], // col 15
|
||
[0.0; 20], // col 16
|
||
[0.0; 20], // col 17
|
||
[0.0; 20], // col 18
|
||
[0.0; 20], // col 19
|
||
[0.0; 20], // col 20
|
||
[0.0; 20], // col 21
|
||
[0.0; 20], // col 22
|
||
[0.0; 20], // col 23
|
||
[0.0; 20], // col 24
|
||
];
|
||
|
||
/// 光速 (cm/s)
|
||
const C_LIGHT: f64 = 2.997925e18;
|
||
|
||
/// 截面单位转换因子 (cm^2)
|
||
const SIG_FACTOR: f64 = 1.0e-18;
|
||
|
||
/// Hidalgo (1968) 光致电离截面插值。
|
||
///
|
||
/// 根据 Hidalgo 数据表,对给定频率进行线性插值。
|
||
///
|
||
/// # 参数
|
||
///
|
||
/// * `ib` - 物种标识(负值,`INDEX = -IB - 100`)
|
||
/// * `fr` - 频率 (Hz)
|
||
///
|
||
/// # 返回值
|
||
///
|
||
/// 光致电离截面 (cm^2)
|
||
pub fn hidalg(ib: i32, fr: f64) -> f64 {
|
||
let index = (-ib - 101) as usize; // 转为 0-indexed
|
||
if index >= 24 {
|
||
return 0.0;
|
||
}
|
||
|
||
// 根据 INDEX 选择波长网格和数据
|
||
let num = if index < 12 { 20 } else { 15 };
|
||
let wli = if index < 12 { &WL1 } else { &WL2 };
|
||
let sigs = &SIG0[index];
|
||
|
||
// 将频率转换为波长 (Å)
|
||
let wlam = C_LIGHT / fr;
|
||
|
||
// 查找插值区间
|
||
let mut il = 0;
|
||
let mut ir = num - 1;
|
||
for i in 0..num - 1 {
|
||
if wlam >= wli[i] && wlam <= wli[i + 1] {
|
||
il = i;
|
||
ir = i + 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 线性插值
|
||
let mut sigm = if wli[ir] - wli[il] > 0.0 {
|
||
(sigs[ir] - sigs[il]) * (wlam - wli[il]) / (wli[ir] - wli[il]) + sigs[il]
|
||
} else {
|
||
sigs[il]
|
||
};
|
||
|
||
// 边界处理
|
||
if wlam <= wli[0] {
|
||
sigm = sigs[0];
|
||
}
|
||
if wlam >= wli[num - 1] {
|
||
sigm = sigs[num - 1];
|
||
}
|
||
|
||
sigm * SIG_FACTOR
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_hidalg_in_range() {
|
||
// 测试 H I (IB=-101, INDEX=0) 在有效波长范围内
|
||
// 100 Å 对应频率
|
||
let fr = C_LIGHT / 100.0;
|
||
let result = hidalg(-101, fr);
|
||
// H I 数据全为 0,所以结果应为 0
|
||
assert!(result >= 0.0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_hidalg_species_2() {
|
||
// 测试物种 2 (IB=-102, INDEX=1)
|
||
let fr = C_LIGHT / 50.0; // 50 Å
|
||
let result = hidalg(-102, fr);
|
||
assert!(result >= 0.0);
|
||
assert!(result.is_finite());
|
||
}
|
||
|
||
#[test]
|
||
fn test_hidalg_invalid_index() {
|
||
let result = hidalg(-125, C_LIGHT / 100.0);
|
||
assert_eq!(result, 0.0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_hidalg_above_range() {
|
||
// 高于波长范围时返回末值
|
||
let fr = C_LIGHT / 200.0;
|
||
let result = hidalg(-102, fr);
|
||
assert!(result >= 0.0);
|
||
}
|
||
}
|