//! 深度导数计算。 //! //! 重构自 TLUSTY `dmder.f` use crate::tlusty::state::constants::{MDEPTH, UN}; /// 深度导数参数。 /// /// 对应 Fortran COMMON/DEPTDR/ #[derive(Debug, Clone)] pub struct DepthDeriv { /// DM(ID) - DM(ID-1) pub ddm: Vec, /// DM(ID+1) - DM(ID) pub ddp: Vec, /// DM(ID+1) - DM(ID-1) pub dd0: Vec, /// DDP / DD0 pub ddmin: Vec, /// DDM / DD0 pub ddplu: Vec, /// DDMIN / DDM pub dda: Vec, /// DDA - DDC pub ddb: Vec, /// DDPLU / DDP pub ddc: Vec, } impl Default for DepthDeriv { fn default() -> Self { Self { ddm: vec![0.0; MDEPTH], ddp: vec![0.0; MDEPTH], dd0: vec![0.0; MDEPTH], ddmin: vec![0.0; MDEPTH], ddplu: vec![0.0; MDEPTH], dda: vec![0.0; MDEPTH], ddb: vec![0.0; MDEPTH], ddc: vec![0.0; MDEPTH], } } } /// 计算深度相关的导数。 /// /// # 参数 /// /// * `dm` - 深度质量数组 (1-indexed in Fortran, 0-indexed here) /// * `nd` - 深度点数 /// /// # 返回值 /// /// 深度导数结构体 pub fn dmder(dm: &[f64], nd: usize) -> DepthDeriv { let mut deriv = DepthDeriv::default(); // 内部点 (ID = 2 to ND-1, Fortran 1-indexed) // Rust 0-indexed: id = 1 to nd-2 for id in 1..nd - 1 { deriv.ddm[id] = dm[id] - dm[id - 1]; deriv.ddp[id] = dm[id + 1] - dm[id]; deriv.dd0[id] = dm[id + 1] - dm[id - 1]; deriv.ddmin[id] = deriv.ddp[id] / deriv.dd0[id]; deriv.ddplu[id] = deriv.ddm[id] / deriv.dd0[id]; deriv.dda[id] = deriv.ddmin[id] / deriv.ddm[id]; deriv.ddc[id] = deriv.ddplu[id] / deriv.ddp[id]; } // 边界条件 // ID = 1 (Fortran) -> id = 0 (Rust) deriv.ddm[0] = 0.0; deriv.ddp[0] = dm[1] - dm[0]; deriv.ddmin[0] = 0.0; deriv.ddplu[0] = 1.0; deriv.dda[0] = 0.0; deriv.ddc[0] = UN / deriv.ddp[0]; // ID = ND (Fortran) -> id = nd-1 (Rust) let id_last = nd - 1; deriv.ddm[id_last] = dm[id_last] - dm[id_last - 1]; deriv.ddp[id_last] = 0.0; deriv.ddmin[id_last] = 1.0; deriv.ddplu[id_last] = 0.0; deriv.dda[id_last] = UN / deriv.ddm[id_last]; deriv.ddc[id_last] = 0.0; // DDB = DDA - DDC for id in 0..nd { deriv.ddb[id] = deriv.dda[id] - deriv.ddc[id]; } deriv } #[cfg(test)] mod tests { use super::*; #[test] fn test_dmder_uniform() { // 均匀网格 let dm: Vec = (0..10).map(|i| i as f64).collect(); let deriv = dmder(&dm, 10); // 检查内部点 assert!((deriv.ddm[5] - 1.0).abs() < 1e-10); assert!((deriv.ddp[5] - 1.0).abs() < 1e-10); assert!((deriv.dd0[5] - 2.0).abs() < 1e-10); } #[test] fn test_dmder_boundary() { let dm: Vec = (0..5).map(|i| i as f64 * 2.0).collect(); let deriv = dmder(&dm, 5); // 边界条件 assert!((deriv.ddm[0] - 0.0).abs() < 1e-10); assert!((deriv.ddp[0] - 2.0).abs() < 1e-10); assert!((deriv.ddmin[0] - 0.0).abs() < 1e-10); assert!((deriv.ddplu[0] - 1.0).abs() < 1e-10); } #[test] fn test_dmder_consistency() { let dm: Vec = vec![0.0, 1.0, 3.0, 6.0, 10.0]; let deriv = dmder(&dm, 5); // 检查 DDB = DDA - DDC for id in 0..5 { assert!((deriv.ddb[id] - (deriv.dda[id] - deriv.ddc[id])).abs() < 1e-10); } } }