SpectraRust/src/synspec/math/gvdw.rs
fmq 0f97c0b05b feat: 添加 TLUSTY 新模块 + 修复编译错误
新增 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>
2026-06-07 12:35:09 +08:00

160 lines
4.1 KiB
Rust

//! Van der Waals broadening parameter evaluation.
//!
//! Translated from SYNSPEC54.FOR function GVDW(IL,ILIST,ID) at line 19468.
//!
//! Supports two modes:
//! - Standard expression (`ivdwli == 0`)
//! - EXOMOL form with H2 and He broadening (`ivdwli > 0`)
/// Parameters for Van der Waals broadening calculation.
pub struct GvdwParams<'a> {
/// Line index
pub il: usize,
/// Line list index
pub ilist: usize,
/// Depth index
pub id: usize,
/// Van der Waals damping parameter (standard mode)
pub gwm: f64,
/// Van der Waals coefficient at depth
pub vdwc: &'a [f64],
/// Mode of evaluation per line list (0 = standard, >0 = EXOMOL)
pub ivdwli: &'a [i32],
/// Temperature at each depth
pub temp: &'a [f64],
/// He number density at each depth (from rrr array)
pub anhe: f64,
/// H2 number density at each depth
pub anh2: &'a [f64],
/// EXOMOL H2 broadening exponent
pub gexph2: f64,
/// EXOMOL H2 broadening width
pub gvdwh2: f64,
/// EXOMOL He broadening exponent
pub gexphe: f64,
/// EXOMOL He broadening width
pub gvdwhe: f64,
}
/// Van der Waals broadening parameter.
///
/// Computes the Van der Waals broadening parameter for spectral line profiles.
/// Supports both the standard classical expression and the EXOMOL form
/// (broadening by H2 and He).
///
/// # Arguments
/// * `params` - Calculation parameters
///
/// # Returns
/// Van der Waals broadening parameter
pub fn gvdw(params: &GvdwParams) -> f64 {
// Standard classical expression
if params.ivdwli[params.ilist] == 0 {
return params.gwm * params.vdwc[params.id];
}
// EXOMOL form - broadening by H2 and He
// con = 1e-6 * c * k (cgs)
let con = 4.1388e-12;
let t = params.temp[params.id];
con * t
* ((296.0 / t).powf(params.gexph2) * params.gvdwh2 * params.anh2[params.id]
+ (296.0 / t).powf(params.gexphe) * params.gvdwhe * params.anhe)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gvdw_standard_mode() {
let vdwc = vec![1.0, 2.0, 3.0];
let ivdwli = vec![0];
let temp = vec![5000.0, 6000.0, 7000.0];
let anh2 = vec![1e10, 1e10, 1e10];
let params = GvdwParams {
il: 0,
ilist: 0,
id: 1,
gwm: 0.5,
vdwc: &vdwc,
ivdwli: &ivdwli,
temp: &temp,
anhe: 1e10,
anh2: &anh2,
gexph2: 0.0,
gvdwh2: 0.0,
gexphe: 0.0,
gvdwhe: 0.0,
};
// Standard: gwm * vdwc[id] = 0.5 * 2.0 = 1.0
let result = gvdw(&params);
assert!((result - 1.0).abs() < 1e-15);
}
#[test]
fn test_gvdw_exomol_mode() {
let vdwc = vec![1.0; 3];
let ivdwli = vec![1];
let temp = vec![5000.0; 3];
let anh2 = vec![1e12; 3];
let params = GvdwParams {
il: 0,
ilist: 0,
id: 0,
gwm: 1.0,
vdwc: &vdwc,
ivdwli: &ivdwli,
temp: &temp,
anhe: 1e11,
anh2: &anh2,
gexph2: 0.5,
gvdwh2: 1e-9,
gexphe: 0.3,
gvdwhe: 5e-10,
};
let result = gvdw(&params);
assert!(result > 0.0);
assert!(result.is_finite());
}
#[test]
fn test_gvdw_exomol_temperature_dependence() {
let vdwc = vec![1.0; 2];
let ivdwli = vec![1];
let anh2 = vec![1e12; 2];
let params_low = GvdwParams {
il: 0,
ilist: 0,
id: 0,
gwm: 1.0,
vdwc: &vdwc,
ivdwli: &ivdwli,
temp: &[3000.0, 10000.0],
anhe: 1e11,
anh2: &anh2,
gexph2: 0.5,
gvdwh2: 1e-9,
gexphe: 0.3,
gvdwhe: 5e-10,
};
let params_high = GvdwParams {
id: 1,
..params_low
};
let r_low = gvdw(&params_low);
let r_high = gvdw(&params_high);
// Both should be positive
assert!(r_low > 0.0);
assert!(r_high > 0.0);
}
}