//! 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, /// 对数不透明度 alpha(freq, temp) alpha: Vec>, /// 是否已初始化 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() }