135 lines
3.4 KiB
Rust
135 lines
3.4 KiB
Rust
//! 深度导数计算。
|
|
//!
|
|
//! 重构自 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<f64>,
|
|
/// DM(ID+1) - DM(ID)
|
|
pub ddp: Vec<f64>,
|
|
/// DM(ID+1) - DM(ID-1)
|
|
pub dd0: Vec<f64>,
|
|
/// DDP / DD0
|
|
pub ddmin: Vec<f64>,
|
|
/// DDM / DD0
|
|
pub ddplu: Vec<f64>,
|
|
/// DDMIN / DDM
|
|
pub dda: Vec<f64>,
|
|
/// DDA - DDC
|
|
pub ddb: Vec<f64>,
|
|
/// DDPLU / DDP
|
|
pub ddc: Vec<f64>,
|
|
}
|
|
|
|
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<f64> = (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<f64> = (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<f64> = 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);
|
|
}
|
|
}
|
|
}
|