//! 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); } }