//! 温度依赖量初始化。 //! //! 重构自 TLUSTY `tdpini.f` use crate::state::config::BasNum; use crate::state::constants::{HALF, H, HK, MDEPTH, UN}; use crate::state::model::{CurOpa, GffPar, ModPar}; use super::gfree0; // ============================================================================ // TDPINI - 温度依赖量初始化 // ============================================================================ /// 初始化仅依赖温度的量。 /// /// # 参数 /// /// - `basnum` - 基本数值 /// - `modpar` - 模型参数 (会被修改) /// - `gffpar` - Gaunt 因子参数 (会被修改) /// - `curopa` - 当前不透明度 (会被修改) /// /// # Fortran 原始代码 /// /// ```fortran /// SUBROUTINE TDPINI /// DO ID=1,ND /// T=TEMP(ID) /// T1=UN/T /// HKT1(ID)=HK*T1 /// HKT21(ID)=HKT1(ID)*T1 /// TK1(ID)=HKT1(ID)/H /// SQT1(ID)=SQRT(T) /// TEMP1(ID)=T1 /// CALL GFREE0(ID) /// EMEL1(ID)=UN /// END DO /// DO ID=1,ND-1 /// DELDM(ID)=HALF*(DM(ID+1)-DM(ID)) /// deldmz(id)=deldm(id) /// if(izscal.eq.1) deldmz(id)=half*(zd(id)-zd(id+1)) /// END DO /// DEDM1=DM(1)/DENS(1) /// END /// ``` pub fn tdpini( basnum: &BasNum, modpar: &mut ModPar, gffpar: &mut GffPar, curopa: &mut CurOpa, ) { let nd = basnum.nd as usize; let izscal = basnum.izscal; // 温度依赖量 for id in 0..nd { let t = modpar.temp[id]; let t1 = UN / t; modpar.hkt1[id] = HK * t1; modpar.hkt21[id] = modpar.hkt1[id] * t1; modpar.tk1[id] = modpar.hkt1[id] / H; modpar.sqt1[id] = t.sqrt(); modpar.temp1[id] = t1; // Gaunt 因子初始化 gfree0(id, &modpar.temp, gffpar); // 电子发射系数初始化 curopa.emel1[id] = UN; } // 深度差分 (用于光学深度评估) for id in 0..(nd - 1) { modpar.deldm[id] = HALF * (modpar.dm[id + 1] - modpar.dm[id]); modpar.deldmz[id] = modpar.deldm[id]; // 如果使用几何深度缩放 if izscal == 1 { modpar.deldmz[id] = HALF * (modpar.zd[id] - modpar.zd[id + 1]); } } // 第一个深度的密度/质量比 modpar.dedm1 = modpar.dm[0] / modpar.dens[0]; } #[cfg(test)] mod tests { use super::*; fn create_test_data() -> (BasNum, ModPar, GffPar, CurOpa) { let mut basnum = BasNum::default(); basnum.nd = 5; basnum.izscal = 0; let mut modpar = ModPar::default(); // 设置温度和密度 for id in 0..5 { modpar.temp[id] = 10000.0 + id as f64 * 1000.0; modpar.dm[id] = (id + 1) as f64 * 0.1; modpar.dens[id] = 1e-7; } let gffpar = GffPar::new(); let curopa = CurOpa::default(); (basnum, modpar, gffpar, curopa) } #[test] fn test_tdpini_basic() { let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data(); tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa); // 检查温度相关量 let t0 = 10000.0; let t1 = UN / t0; assert!((modpar.hkt1[0] - HK * t1).abs() < 1e-10); assert!((modpar.sqt1[0] - t0.sqrt()).abs() < 1e-10); assert!((modpar.temp1[0] - t1).abs() < 1e-10); } #[test] fn test_tdpini_delta_m() { let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data(); tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa); // 检查深度差分 // DELDM[0] = 0.5 * (DM[1] - DM[0]) = 0.5 * (0.2 - 0.1) = 0.05 assert!((modpar.deldm[0] - 0.05).abs() < 1e-10); assert!((modpar.deldmz[0] - 0.05).abs() < 1e-10); // izscal = 0 } #[test] fn test_tdpini_emel1() { let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data(); tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa); // 检查 EMEL1 被初始化为 1 for id in 0..basnum.nd as usize { assert!((curopa.emel1[id] - UN).abs() < 1e-10); } } #[test] fn test_tdpini_dedm1() { let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data(); tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa); // DEDM1 = DM[0] / DENS[0] = 0.1 / 1e-7 = 1e6 let expected = 0.1 / 1e-7; assert!((modpar.dedm1 - expected).abs() < 1e-5); } #[test] fn test_tdpini_with_zscal() { let (mut basnum, mut modpar, mut gffpar, mut curopa) = create_test_data(); basnum.izscal = 1; // 设置几何深度 for id in 0..5 { modpar.zd[id] = (5 - id) as f64 * 1e5; // 从表面向内递减 } tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa); // 检查使用几何深度计算的 DELDMZ // DELDMZ[0] = 0.5 * (ZD[0] - ZD[1]) = 0.5 * (5e5 - 4e5) = 5e4 let expected_z = 0.5 * (5e5 - 4e5); assert!((modpar.deldmz[0] - expected_z).abs() < 1e-5); } }