SpectraRust/src/math/odfhst.rs
2026-03-21 09:12:18 +08:00

160 lines
3.8 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.

//! ODF Stark 展宽辅助函数。
//!
//! 重构自 TLUSTY `odfhst.f`
//!
//! 用于 ODF1 的辅助例程,替代多次调用 STARKA。
use crate::state::constants::{TWO, UN};
use crate::state::model::StrAux;
use crate::state::odfpar::MFRO;
/// ODF Stark 展宽辅助函数。
///
/// 用于 ODF1 的辅助例程,计算 Stark 展宽的线轮廓。
///
/// # 参数
///
/// * `n` - 频率点数
/// * `fxk` - 线宽参数
/// * `fid` - 振子强度
/// * `wp` - 权重
/// * `wl` - 波长
/// * `alam` - 频率数组
/// * `straux` - Stark 展宽参数
/// * `sg` - 输出Stark 展宽数组
///
/// # 示例
///
/// ```
/// use tlusty_rust::math::odfhst::odfhst;
/// use tlusty_rust::state::model::StrAux;
///
/// let straux = StrAux::default();
/// let alam = vec![1.0, 2.0, 3.0];
/// let mut sg = vec![0.0; 3];
///
/// odfhst(3, 1.0, 0.5, 1.0, 1215.0, &alam, &straux, &mut sg);
/// ```
pub fn odfhst(
n: usize,
fxk: f64,
fid: f64,
wp: f64,
wl: f64,
alam: &[f64],
straux: &StrAux,
sg: &mut [f64],
) {
// 常数参数
const F0: f64 = -0.5758228;
const F1: f64 = 0.4796232;
const F2: f64 = 0.07209481;
const AL: f64 = 1.26;
const SD: f64 = 0.5641895;
const SLO: f64 = -2.5;
const THRA: f64 = 1.5;
const BL1: f64 = 1.14;
const BL2: f64 = 11.4;
const SAC: f64 = 0.08;
const THR: f64 = THRA * TWO;
let betad = straux.betad;
let adh = straux.adh;
let divh = straux.divh;
// 防止除零
let betad1 = if betad.abs() > 1e-30 { UN / betad } else { 0.0 };
let fxk1 = if fxk.abs() > 1e-30 { UN / fxk } else { 0.0 };
let fidwp = fid * wp;
// for a > 1 Doppler core + asymptotic Holtzmark wing with division point DIV
if adh > AL {
for ij in 0..n {
let beta = (alam[ij] - wl).abs() * fxk1;
let xd = beta * betad1;
let st = if xd <= divh {
SD * (-xd * xd).exp() * betad1
} else {
THR * beta.powf(SLO)
};
sg[ij] = st * fidwp;
}
} else {
// empirical formula for a < 1
for ij in 0..n {
let beta = (alam[ij] - wl).abs() * fxk1;
let xd = beta * betad1;
let st = if beta <= BL1 {
SAC
} else if beta < BL2 {
let xl = beta.ln();
let fl = (F0 * xl + F1) * xl;
F2 * fl.exp()
} else {
THR * beta.powf(SLO)
};
sg[ij] = st * fidwp;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_odfhst_adh_gt_al() {
let mut straux = StrAux::default();
straux.adh = 2.0; // > AL = 1.26
straux.betad = 1.0;
straux.divh = 1.0;
let alam = vec![1200.0, 1215.0, 1230.0];
let mut sg = vec![0.0; 3];
odfhst(3, 1.0, 0.5, 1.0, 1215.0, &alam, &straux, &mut sg);
// 中间点wl=1215.0)应该有最大值
assert!(sg[1] > sg[0]);
assert!(sg[1] > sg[2]);
}
#[test]
fn test_odfhst_adh_lt_al() {
let mut straux = StrAux::default();
straux.adh = 0.5; // < AL = 1.26
straux.betad = 1.0;
straux.divh = 1.0;
let alam = vec![1200.0, 1215.0, 1230.0];
let mut sg = vec![0.0; 3];
odfhst(3, 1.0, 0.5, 1.0, 1215.0, &alam, &straux, &mut sg);
// 所有值应该是正的
for &s in &sg {
assert!(s >= 0.0);
}
}
#[test]
fn test_odfhst_zero_betad() {
let mut straux = StrAux::default();
straux.adh = 2.0;
straux.betad = 0.0; // 零值
straux.divh = 1.0;
let alam = vec![1200.0, 1215.0, 1230.0];
let mut sg = vec![0.0; 3];
// 不应该 panic
odfhst(3, 1.0, 0.5, 1.0, 1215.0, &alam, &straux, &mut sg);
}
}