//! 短特征辐射转移求解器 //! //! 原始 Fortran: rte_sc.f //! Short Characteristics 方法求解辐射转移方程 /// 短特征辐射转移求解器 /// /// 对已知源函数的辐射转移方程进行形式求解 /// /// # 参数 /// - `dtau`: 光学深度增量 (nd-1 个元素) /// - `st0`: 总源函数 (nd 个元素) /// - `rup`: 上边界强度 (id=1) /// - `rdown`: 下边界强度 (id=nd) /// - `amu0`: 传播角度余弦 (相对于法线) /// - amu0 < 0: 入射辐射 (向下) /// - amu0 >= 0: 出射辐射 (向上) /// - `ri`: 辐射强度 (输出) /// - `ali`: Lambda 算子对角元素 (输出) /// - `nd`: 深度点数 /// /// # 算法 /// 使用短特征 (Short Characteristics) 方法 pub fn rte_sc( dtau: &[f64], st0: &[f64], rup: f64, rdown: f64, amu0: f64, ri: &mut [f64], ali: &mut [f64], nd: usize, ) { // 工作数组 let mut dtx1 = vec![0.0; nd]; let mut dtx2 = vec![0.0; nd]; let mut dtx0 = vec![0.0; nd]; // 常量 let un = 1.0_f64; // 预计算指数因子 for id in 0..nd - 1 { dtx1[id] = (-dtau[id]).exp(); dtx2[id] = (un - dtx1[id]) / dtau[id]; dtx0[id] = un - dtx2[id]; } // 入射强度 (向下传播) if amu0 < 0.0 { let id = 0; ri[id] = rup; for id in 0..nd - 1 { ri[id + 1] = ri[id] * dtx1[id] + st0[id] * (dtx2[id] - dtx1[id]) + st0[id + 1] * dtx0[id]; ali[id + 1] = dtx0[id]; } ali[0] = 0.0; } else { // 出射强度 (向上传播) ri[nd - 1] = rdown; for id in (0..nd - 1).rev() { ri[id] = ri[id + 1] * dtx1[id] + st0[id] * dtx0[id] + st0[id + 1] * (dtx2[id] - dtx1[id]); ali[id] = dtx0[id]; } ali[nd - 1] = 0.0; } } #[cfg(test)] mod tests { use super::*; #[test] fn test_rte_sc_incoming() { // 测试入射辐射 let nd = 5; let dtau = vec![0.5; nd - 1]; let st0 = vec![1.0; nd]; let rup = 0.0; let rdown = 0.0; let amu0 = -1.0; // 入射 let mut ri = vec![0.0; nd]; let mut ali = vec![0.0; nd]; rte_sc(&dtau, &st0, rup, rdown, amu0, &mut ri, &mut ali, nd); // 入射边界条件 assert!((ri[0] - 0.0).abs() < 1e-10); assert!((ali[0] - 0.0).abs() < 1e-10); // 强度应该随深度增加 assert!(ri[nd - 1] > ri[0]); } #[test] fn test_rte_sc_outgoing() { // 测试出射辐射 let nd = 5; let dtau = vec![0.5; nd - 1]; let st0 = vec![1.0; nd]; let rup = 0.0; let rdown = 0.0; let amu0 = 1.0; // 出射 let mut ri = vec![0.0; nd]; let mut ali = vec![0.0; nd]; rte_sc(&dtau, &st0, rup, rdown, amu0, &mut ri, &mut ali, nd); // 出射边界条件 assert!((ri[nd - 1] - 0.0).abs() < 1e-10); assert!((ali[nd - 1] - 0.0).abs() < 1e-10); // 强度应该随深度增加 assert!(ri[0] > ri[nd - 1]); } #[test] fn test_rte_sc_consistency() { // 测试源函数为常数时的渐进行为 let nd = 100; let dtau = vec![0.1; nd - 1]; let st0 = vec![2.0; nd]; let rup = 0.0; let rdown = 0.0; let mut ri_in = vec![0.0; nd]; let mut ali_in = vec![0.0; nd]; let mut ri_out = vec![0.0; nd]; let mut ali_out = vec![0.0; nd]; rte_sc(&dtau, &st0, rup, rdown, -1.0, &mut ri_in, &mut ali_in, nd); rte_sc(&dtau, &st0, rup, rdown, 1.0, &mut ri_out, &mut ali_out, nd); // 在深部,入射和出射强度应趋近于源函数 // (对于光学厚介质) assert!((ri_in[nd - 1] - st0[nd - 1]).abs() < 0.1); assert!((ri_out[0] - st0[0]).abs() < 0.1); } }