模块重构大部分已完成

This commit is contained in:
Asfmq 2026-03-25 12:33:47 +08:00
parent fc64e24fac
commit b71930cf8e
3 changed files with 206 additions and 1 deletions

View File

@ -187,6 +187,7 @@ mod princ;
mod pzeval; mod pzeval;
mod prnt; mod prnt;
mod prsent; mod prsent;
mod pretab;
mod profil; mod profil;
mod profsp; mod profsp;
mod quartc; mod quartc;
@ -397,7 +398,7 @@ pub use gamhe::{gamhe, GamheData, GamheParams};
pub use gami::gami; pub use gami::gami;
pub use getlal::{getlal, GetlalParams, GetlalResult}; pub use getlal::{getlal, GetlalParams, GetlalResult};
pub use gamsp::gamsp; pub use gamsp::gamsp;
pub use gfree::{gfree0, gfreed}; pub use gfree::{gfree0, gfree1, gfreed};
pub use ghydop::{ghydop, GhydopParams, GhydopResult}; pub use ghydop::{ghydop, GhydopParams, GhydopResult};
pub use gaunt::gaunt; pub use gaunt::gaunt;
pub use gntk::gntk; pub use gntk::gntk;
@ -507,6 +508,7 @@ pub use prchan::{prchan, PrchanParams, PrchanOutput, format_change_report};
pub use princ::{princ_pure, PrincParams, PrincOutput, PrincTransResult, PrincDepthResult, pub use princ::{princ_pure, PrincParams, PrincOutput, PrincTransResult, PrincDepthResult,
format_princ_header, format_princ_line}; format_princ_header, format_princ_line};
pub use prsent::{prsent, PrsentParams, PrsentOutput, ThermTables}; pub use prsent::{prsent, PrsentParams, PrsentOutput, ThermTables};
pub use pretab::{pretab, VoigtTables};
pub use profil::{profil, ProfilParams}; pub use profil::{profil, ProfilParams};
pub use profsp::{profsp, ProfspParams}; pub use profsp::{profsp, ProfspParams};
pub use pfni::pfni; pub use pfni::pfni;

199
src/math/pretab.rs Normal file
View File

@ -0,0 +1,199 @@
//! Voigt 函数展开系数预计算表。
//!
//! 重构自 SYNSPEC `pretab.f`。
//!
//! 预计算 Voigt 函数的展开系数表:
//! - 200 步/Doppler 宽度
//! - 最多 10 个 Doppler 宽度
//! - 共 MVOI=2001 个点
use crate::math::interp::interp;
/// Voigt 表步长 (每 Doppler 宽度的步数)
const VSTEPS: f64 = 200.0;
/// TABVI 数据: 速度值 (0 到 12, 81 点)
static TABVI: [f64; 81] = [
0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9,
2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9,
3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9,
4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8,
6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8,
8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8,
10.0, 10.2, 10.4, 10.6, 10.8, 11.0, 11.2, 11.4, 11.6, 11.8,
12.0,
];
/// TABH1 数据: H1 展开系数 (81 点)
static TABH1: [f64; 81] = [
-1.12838, -1.10596, -1.04048, -0.93703, -0.80346, -0.64945,
-0.48552, -0.32192, -0.16772, -0.03012, 0.08594, 0.17789,
0.24537, 0.28981, 0.31394, 0.32130, 0.31573, 0.30094, 0.28027,
0.25648, 0.231726, 0.207528, 0.184882, 0.164341, 0.146128,
0.130236, 0.116515, 0.104739, 0.094653, 0.086005, 0.078565,
0.072129, 0.066526, 0.061615, 0.057281, 0.053430, 0.049988,
0.046894, 0.044098, 0.041561, 0.039250, 0.035195, 0.031762,
0.028824, 0.026288, 0.024081, 0.022146, 0.020441, 0.018929,
0.017582, 0.016375, 0.015291, 0.014312, 0.013426, 0.012620,
0.0118860, 0.0112145, 0.0105990, 0.0100332, 0.0095119,
0.0090306, 0.0085852, 0.0081722, 0.0077885, 0.0074314,
0.0070985, 0.0067875, 0.0064967, 0.0062243, 0.0059688,
0.0057287, 0.0055030, 0.0052903, 0.0050898, 0.0049006,
0.0047217, 0.0045526, 0.0043924, 0.0042405, 0.0040964,
0.0039595,
];
/// Voigt 函数预计算表。
///
/// 包含 H0, H1, H2 三个展开系数数组。
#[derive(Debug, Clone)]
pub struct VoigtTables {
/// H0 展开系数 (Gauss 轮廓)
pub h0tab: Vec<f64>,
/// H1 展开系数 (Voigt 轮廓一阶修正)
pub h1tab: Vec<f64>,
/// H2 展开系数 (Voigt 轮廓二阶修正)
pub h2tab: Vec<f64>,
}
impl Default for VoigtTables {
fn default() -> Self {
Self::new()
}
}
impl VoigtTables {
/// 创建新的 Voigt 表 (未初始化)。
pub fn new() -> Self {
Self {
h0tab: vec![0.0; crate::state::MVOI],
h1tab: vec![0.0; crate::state::MVOI],
h2tab: vec![0.0; crate::state::MVOI],
}
}
/// 预计算 Voigt 展开系数表。
///
/// 重构自 SYNSPEC `PRETAB` 子程序。
///
/// # 算法
/// 1. 设置 H0TAB(i) = (i-1)/VSTEPS 作为速度值
/// 2. 使用二次插值从 TABH1 计算 H1TAB
/// 3. 计算 H0TAB(i) = exp(-v²) (Gauss 轮廓)
/// 4. 计算 H2TAB(i) = H0TAB(i) * (1 - 2v²) (二阶导数)
pub fn compute(&mut self) {
let n = crate::state::MVOI;
// 准备插值输入
let mut x = TABVI.to_vec();
let mut y = TABH1.to_vec();
let mut xx = vec![0.0; n];
let mut yy = vec![0.0; n];
// 步骤 1: 设置速度值
for i in 0..n {
xx[i] = (i as f64) / VSTEPS;
}
// 步骤 2: 插值计算 H1TAB
// INTERP(X, Y, XX, YY, NX, NXX, NPOL, ILOGX, ILOGY)
// NPOL=2 表示线性插值 (NPOL-1 = 1 阶)
interp(&mut x, &mut y, &mut xx, &mut yy, 81, n, 2, 0, 0);
// 复制插值结果到 H1TAB
self.h1tab.copy_from_slice(&yy);
// 步骤 3 & 4: 计算 H0TAB 和 H2TAB
for i in 0..n {
let vv = ((i as f64) / VSTEPS) * ((i as f64) / VSTEPS);
self.h0tab[i] = (-vv).exp();
self.h2tab[i] = self.h0tab[i] - (vv + vv) * self.h0tab[i];
}
}
}
/// 预计算 Voigt 展开系数表 (便捷函数)。
///
/// # 返回值
/// 包含 H0TAB, H1TAB, H2TAB 三个数组的结构体
pub fn pretab() -> VoigtTables {
let mut tables = VoigtTables::new();
tables.compute();
tables
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_relative_eq;
#[test]
fn test_pretab_basic() {
let tables = pretab();
// 检查数组大小
assert_eq!(tables.h0tab.len(), crate::state::MVOI);
assert_eq!(tables.h1tab.len(), crate::state::MVOI);
assert_eq!(tables.h2tab.len(), crate::state::MVOI);
// H0TAB 在 v=0 时应为 1 (exp(0) = 1)
assert_relative_eq!(tables.h0tab[0], 1.0, epsilon = 1e-15);
// H2TAB 在 v=0 时应为 1 (1 - 0*2 = 1)
assert_relative_eq!(tables.h2tab[0], 1.0, epsilon = 1e-15);
// H0TAB 应随 v 增大而减小
assert!(tables.h0tab[100] < tables.h0tab[50]);
assert!(tables.h0tab[200] < tables.h0tab[100]);
}
#[test]
fn test_h0tab_values() {
let tables = pretab();
// 检查一些已知值
// v = 0.5 (i=100), H0 = exp(-0.25) ≈ 0.7788
let v_100 = 100.0_f64 / VSTEPS;
let expected_h0_100 = (-(v_100 * v_100)).exp();
assert_relative_eq!(tables.h0tab[100], expected_h0_100, epsilon = 1e-10);
// v = 1.0 (i=200), H0 = exp(-1) ≈ 0.3679
let v_200 = 200.0_f64 / VSTEPS;
let expected_h0_200 = (-(v_200 * v_200)).exp();
assert_relative_eq!(tables.h0tab[200], expected_h0_200, epsilon = 1e-10);
}
#[test]
fn test_h2tab_values() {
let tables = pretab();
// H2 = H0 * (1 - 2*v²)
// 在 v = 0.5 时, H2 = H0 * (1 - 0.5) = 0.5 * H0
let v_100 = 100.0_f64 / VSTEPS;
let vv = v_100 * v_100;
let expected_h2 = tables.h0tab[100] * (1.0 - 2.0 * vv);
assert_relative_eq!(tables.h2tab[100], expected_h2, epsilon = 1e-10);
}
#[test]
fn test_h1tab_interpolation() {
let tables = pretab();
// H1TAB 应该是从 TABH1 插值得到的
// 在 v = 0 时, 应该接近 TABH1[0] = -1.12838
assert_relative_eq!(tables.h1tab[0], TABH1[0], epsilon = 1e-5);
// 在 v = 1.0 时 (i=200), 应该在 TABH1[10] 和 TABH1[11] 之间
// TABH1[10] = 0.08594 (v=1.0)
assert_relative_eq!(tables.h1tab[200], TABH1[10], epsilon = 1e-5);
}
#[test]
fn test_voigt_tables_default() {
let tables = VoigtTables::default();
assert_eq!(tables.h0tab.len(), crate::state::MVOI);
assert_eq!(tables.h1tab.len(), crate::state::MVOI);
assert_eq!(tables.h2tab.len(), crate::state::MVOI);
}
}

View File

@ -103,6 +103,10 @@ pub const MCFE: usize = 7824000;
/// ODF 频率范围 /// ODF 频率范围
pub const MFRO: usize = MFREQL; pub const MFRO: usize = MFREQL;
// SYNSPEC 相关
/// Voigt 表大小 (200 steps per doppler width, up to 10 Doppler widths)
pub const MVOI: usize = 2001;
// ============================================================================ // ============================================================================
// 物理常数 (CGS 单位) // 物理常数 (CGS 单位)
// ============================================================================ // ============================================================================