代码整理

This commit is contained in:
fengmengqi
2026-03-25 18:34:41 +08:00
parent 3416c491ad
commit ddfe08cb93
313 changed files with 2817 additions and 777 deletions
+220
View File
@@ -0,0 +1,220 @@
//! 氢线 Stark 展宽表格插值。
//!
//! 重构自 TLUSTY `inthyd.f`。
//!
//! 从 Lemke 表格中插值计算氢线的 Stark 展宽轮廓。
use crate::tlusty::math::{divstr, starka, yint};
use crate::tlusty::state::HydPrf;
// ============================================================================
// INTHYD - 氢线表格插值
// ============================================================================
/// 从 Lemke 表格插值计算氢线 Stark 展宽轮廓。
///
/// 在温度和电子密度方向上进行二维插值。
///
/// # 参数
///
/// - `x0` - log10(温度)
/// - `z0` - log10(电子密度)
/// - `iwl` - 波长索引 (0-indexed)
/// - `iline` - 谱线索引 (0-indexed)
/// - `hydprf` - 氢线表格数据
/// - `dbeta` - Doppler 宽度 (β 单位)
/// - `xk` - 参考波数
///
/// # 返回
///
/// log10(轮廓值)
///
/// # Fortran 原始代码
///
/// ```fortran
/// SUBROUTINE INTHYD(W0,X0,Z0,IWL,ILINE)
/// ...
/// END
/// ```
pub fn inthyd(
x0: f64,
z0: f64,
iwl: usize,
iline: usize,
hydprf: &HydPrf,
dbeta: f64,
xk: f64,
) -> f64 {
let nt = hydprf.nth[iline] as usize;
let ne = hydprf.neh[iline] as usize;
let beta = hydprf.get_wlh(iwl, iline) / xk;
let izh = 1; // H I
// 检查是否低于最低电子密度网格值
// 对于低于最低网格值的情况,使用近似表达式 (starka)
let xnelem_min = hydprf.get_xnelem(0, iline);
if z0 < xnelem_min * 0.99 {
let (adh, divh) = divstr(dbeta, izh);
let stark_val = starka(beta, 2.0, adh, dbeta, divh);
return (stark_val * dbeta).log10();
}
// 查找电子密度插值区间
let mut ipz = 0;
for izz in 0..(ne - 1) {
ipz = izz;
if z0 <= hydprf.get_xnelem(izz + 1, iline) {
break;
}
}
// 确定插值窗口
let nz = 2;
let mut n0z = ipz as i32 - (nz as i32 / 2) + 1;
if n0z < 1 {
n0z = 1;
}
if n0z > (ne - nz + 1) as i32 {
n0z = (ne - nz + 1) as i32;
}
let n1z = n0z + nz as i32 - 1;
// 准备插值数组
let mut zz = [0.0; 3];
let mut wz = [0.0; 3];
for izz in n0z..=n1z {
let i0z = (izz - n0z) as usize;
zz[i0z] = hydprf.get_xnelem((izz - 1) as usize, iline);
// 检查是否超过最高温度网格值
let xtlem_max = hydprf.get_xtlem(nt - 1, iline);
if x0 > 1.01 * xtlem_max {
let (adh, divh) = divstr(dbeta, izh);
let stark_val = starka(beta, 2.0, adh, dbeta, divh);
return (stark_val * dbeta).log10();
}
// 温度方向插值
let nx = 2;
let mut ipx = 0;
for ix in 0..(nt - 1) {
ipx = ix;
if x0 <= hydprf.get_xtlem(ix + 1, iline) {
break;
}
}
let mut n0x = ipx as i32 - (nx as i32 / 2) + 1;
if n0x < 1 {
n0x = 1;
}
if n0x > (nt - nx + 1) as i32 {
n0x = (nt - nx + 1) as i32;
}
let n1x = n0x + nx as i32 - 1;
let mut xx = [0.0; 3];
let mut wx = [0.0; 3];
for ix in n0x..=n1x {
let i0 = (ix - n0x) as usize;
xx[i0] = hydprf.get_xtlem((ix - 1) as usize, iline);
wx[i0] = hydprf.get_prfhyd(iline, iwl, (ix - 1) as usize, (izz - 1) as usize);
}
// 检查是否有无效值
if wx[0] < -99.0 || wx[1] < -99.0 || wx[2] < -99.0 {
let (adh, divh) = divstr(dbeta, izh);
let stark_val = starka(beta, 2.0, adh, dbeta, divh);
return (stark_val * dbeta).log10();
} else {
wz[i0z] = yint(&xx, &wx, x0);
}
}
// 电子密度方向插值
yint(&zz, &wz, z0)
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_hydprf() -> HydPrf {
let mut hydprf = HydPrf::default();
// 设置谱线 0 的参数
hydprf.nth[0] = 7;
hydprf.neh[0] = 20;
// 设置温度网格 (log10)
for it in 0..7 {
hydprf.xtlem[it] = 4.0 + it as f64 * 0.1; // 10^4.0 到 10^4.6
}
// 设置电子密度网格 (log10)
for ie in 0..20 {
hydprf.xnelem[ie] = 12.0 + ie as f64 * 0.2; // 10^12 到 10^15.8
}
// 设置波长网格
for iwl in 0..90 {
hydprf.wlh[iwl] = 4000.0 + iwl as f64 * 10.0; // 4000 Å 到 4900 Å
}
// 设置轮廓数据 (简单的测试值)
for it in 0..7 {
for ie in 0..20 {
hydprf.set_prfhyd(0, 0, it, ie, -2.0 + it as f64 * 0.1 + ie as f64 * 0.01);
}
}
hydprf
}
#[test]
fn test_inthyd_basic() {
let hydprf = create_test_hydprf();
let dbeta = 10.0;
let xk = 1.0;
// 在表格范围内的插值
let x0 = 4.3; // log10(T)
let z0 = 13.5; // log10(Ne)
let result = inthyd(x0, z0, 0, 0, &hydprf, dbeta, xk);
// 结果应该是有限值
assert!(result.is_finite());
}
#[test]
fn test_inthyd_low_ne() {
let hydprf = create_test_hydprf();
let dbeta = 10.0;
let xk = 1.0;
// 低于最低电子密度,应该使用近似表达式
let x0 = 4.3;
let z0 = 10.0; // 低于 10^12
let result = inthyd(x0, z0, 0, 0, &hydprf, dbeta, xk);
// 结果应该是有限值
assert!(result.is_finite());
}
#[test]
fn test_inthyd_high_temp() {
let hydprf = create_test_hydprf();
let dbeta = 10.0;
let xk = 1.0;
// 高于最高温度,应该使用近似表达式
let x0 = 5.0; // 高于 10^4.6
let z0 = 13.5;
let result = inthyd(x0, z0, 0, 0, &hydprf, dbeta, xk);
// 结果应该是有限值
assert!(result.is_finite());
}
}