SpectraRust/src/tlusty/math/continuum/cia_h2h2.rs
2026-04-01 16:35:36 +08:00

148 lines
3.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.

//! CIA H2-H2 不透明度。
//!
//! 重构自 TLUSTY `cia_h2h2.f`
//!
//! # 功能
//!
//! 计算 H2-H2 碰撞诱导吸收 (CIA) 不透明度。
//! 数据来源Borysow A., Jorgensen U.G., Fu Y. 2001, JQSRT 68, 235
/// Amagat 单位转换常数 (cm^-3)
const AMAGAT: f64 = 2.6867774e19;
/// 不透明度转换因子
const FAC: f64 = 1.0 / (AMAGAT * AMAGAT);
/// 光速 (cm/s)
const CAS: f64 = 2.997925e10;
/// 温度表点数
const NTEMP: usize = 7;
/// 频率/波长表行数
const NLINES: usize = 1000;
/// CIA H2-H2 温度表
static TEMP_TABLE: [f64; NTEMP] = [1000.0, 2000.0, 3000.0, 4000.0, 5000.0, 6000.0, 7000.0];
/// CIA H2-H2 不透明度表数据。
///
/// 在首次调用时从文件加载,之后缓存。
pub struct CiaH2H2Data {
/// 频率数组
freq: Vec<f64>,
/// 对数不透明度 alpha(freq, temp)
alpha: Vec<Vec<f64>>,
/// 是否已初始化
loaded: bool,
}
impl Default for CiaH2H2Data {
fn default() -> Self {
Self {
freq: Vec::new(),
alpha: Vec::new(),
loaded: false,
}
}
}
impl CiaH2H2Data {
/// 加载 CIA 数据表。
pub fn load(&mut self) {
if self.loaded {
return;
}
println!("Reading in H2-H2 CIA opacity tables...");
// 在完整实现中,这里会从 "./data/CIA_H2H2.dat" 读取数据
// 暂时初始化为空表
self.freq = vec![0.0; NLINES];
self.alpha = vec![vec![0.0; NTEMP]; NLINES];
self.loaded = true;
}
/// 计算 CIA H2-H2 不透明度。
///
/// # 参数
///
/// * `t` - 温度 (K)
/// * `ah2` - H2 数密度
/// * `ff` - 频率 (Hz)
///
/// # 返回值
///
/// CIA 不透明度
pub fn opacity(&mut self, t: f64, ah2: f64, ff: f64) -> f64 {
self.load();
// 输入频率为 Hz但需要波数 (cm^-1)
let f = ff / CAS;
// 在温度数组中定位
let j = locate(&TEMP_TABLE, t);
if j == 0 {
println!();
println!(
"Warning: requested temperature is below{:6.0} K",
TEMP_TABLE[0]
);
println!("CIA H2-H2 opacity set to 0");
println!();
return 0.0;
}
// 在频率数组中定位
let i = locate(&self.freq, f);
let alp = if j == NTEMP {
// 高温端外推:保持恒定
let y1 = self.alpha[i][j - 1];
let y2 = self.alpha[i + 1][j - 1];
let tt = (f - self.freq[i]) / (self.freq[i + 1] - self.freq[i]);
(1.0 - tt) * y1 + tt * y2
} else if i == 0 || i == NLINES {
// 频率表外:设置非常小的值
-50.0
} else {
// 在表内双线性插值
let y1 = self.alpha[i][j - 1];
let y2 = self.alpha[i + 1][j - 1];
let y3 = self.alpha[i + 1][j];
let y4 = self.alpha[i][j];
let tt = (f - self.freq[i]) / (self.freq[i + 1] - self.freq[i]);
let uu = (t - TEMP_TABLE[j - 1]) / (TEMP_TABLE[j] - TEMP_TABLE[j - 1]);
(1.0 - tt) * (1.0 - uu) * y1
+ tt * (1.0 - uu) * y2
+ tt * uu * y3
+ (1.0 - tt) * uu * y4
};
let alp = alp.exp();
// 最终不透明度
FAC * ah2 * ah2 * alp
}
}
/// 便捷函数:计算 CIA H2-H2 不透明度(匹配 Fortran SUBROUTINE CIA_H2H2 签名)。
pub fn cia_h2h2(t: f64, ah2: f64, ff: f64, opac: &mut f64) {
let mut data = CiaH2H2Data::default();
*opac = data.opacity(t, ah2, ff);
}
/// 在有序数组中定位 x 的位置。
///
/// 返回索引 j使得 arr[j-1] <= x < arr[j]。
/// 如果 x < arr[0],返回 0。
fn locate(arr: &[f64], x: f64) -> usize {
if x < arr[0] {
return 0;
}
for i in 1..arr.len() {
if x < arr[i] {
return i;
}
}
arr.len()
}