//! 频率相关辐射转移方程求解 - RTEDF1。 //! //! 重构自 TLUSTY `rtedf1.f` //! //! 使用不连续有限元 (DFE) 方法求解单频率辐射转移方程。 //! 计算辐射场、可变 Eddington 因子以及近似 Lambda 算子。 use crate::state::constants::{BN, HALF, HK, MDEPTH, TWO, UN}; /// RTEDF1 输入参数 pub struct Rtedf1Params { /// 频率索引 (0-indexed for Rust, 1-indexed for logic) pub ij: usize, /// 深度点数 pub nd: usize, /// 角度点数 pub nmu: usize, /// 盘模型标志 pub idisk: i32, /// 边界条件类型 pub ibc: i32, /// 插值模式 pub isplin: i32, /// ALI 变体类型 pub jali: i32, /// IFALI 参数 pub ifali: i32, /// ILMCOR 参数 pub ilmcor: i32, /// ILASCT 参数 pub ilasct: i32, /// 相对变化阈值 pub djmax: f64, /// 最大 ALI 迭代次数 pub ntrali: i32, /// 风遮挡标志 pub iwinbl: i32, } /// RTEDF1 模型状态 pub struct Rtedf1ModelState<'a> { pub amu: &'a [f64], pub wtmu: &'a [f64], pub freq: &'a [f64], pub deldmz: &'a [f64], pub absot: &'a [f64], pub emis1: &'a [f64], pub abso1: &'a [f64], pub scat1: &'a [f64], pub temp: &'a [f64], pub dedm1: f64, pub rrdil: f64, pub tempbd: f64, pub extint: &'a [Vec], // [freq][mu] pub hextrd: &'a [f64], pub rad: &'a mut [Vec], // [freq][depth] pub fak: &'a mut [Vec], // [freq][depth] pub flux: &'a mut [f64], // [freq] pub fh: &'a mut [f64], // [freq] pub fhd: &'a mut [f64], // [freq] pub radex: &'a mut [Vec], // [ijex][depth] pub fakex: &'a mut [Vec], // [ijex][depth] pub q0: &'a mut [f64], // [ijex] pub uu0: &'a mut [f64], // [ijex] pub ijex: &'a [i32], // [freq] } /// RTEDF1 ALI 状态 pub struct Rtedf1AliState<'a> { pub ali1: &'a mut [f64], pub alim1: &'a mut [f64], pub alip1: &'a mut [f64], } /// 求解单频率辐射转移方程。 pub fn rtedf1(params: &Rtedf1Params, model: &mut Rtedf1ModelState, ali_state: &mut Rtedf1AliState) { let ij = params.ij; let nd = params.nd; let nmu = params.nmu; let mut dt = [0.0; MDEPTH]; let mut st0 = [0.0; MDEPTH]; let mut sa0 = [0.0; MDEPTH]; let mut ss0 = [0.0; MDEPTH]; let mut rad1 = [0.0; MDEPTH]; let mut rdk = [0.0; MDEPTH]; let mut ali1_local = [0.0; MDEPTH]; let sixth = UN / 6.0; let third = UN / 3.0; let twothr = TWO / 3.0; // 1. 计算光深标尺 for id in 0..nd - 1 { dt[id] = model.deldmz[id] * (model.absot[id + 1] + model.absot[id]); sa0[id] = model.emis1[id] / model.abso1[id]; ss0[id] = -model.scat1[id] / model.abso1[id]; } sa0[nd - 1] = model.emis1[nd - 1] / model.abso1[nd - 1]; ss0[nd - 1] = -model.scat1[nd - 1] / model.abso1[nd - 1]; let taumin = model.abso1[0] * model.dedm1; // 2. 风遮挡考虑 let mut alb1 = 0.0; // 注意: albe[ij] 暂未传入,假设为 0 或从其他地方获取 // if params.iwinbl > 0 { alb1 = TWO * albe[ij] / (UN + albe[ij]); } // 3. 下边界条件量 let fr = model.freq[ij]; let fr15 = fr * 1e-15; let bnu = BN * fr15 * fr15 * fr15; let mut pland = bnu / ((HK * fr / model.temp[nd - 1]).exp() - UN) * model.rrdil; let mut dplan = bnu / ((HK * fr / model.temp[nd - 2]).exp() - UN) * model.rrdil; if model.tempbd > 0.0 { pland = bnu / ((HK * fr / model.tempbd).exp() - UN) * model.rrdil; dplan = bnu / ((HK * fr / model.tempbd).exp() - UN) * model.rrdil; } dplan = (pland - dplan) / dt[nd - 2]; let mut ah = 0.0; let mut ahout = 0.0; let mut ahd = 0.0; let mut u0 = 0.0; let mut qq0 = 0.0; // 4. ALI 循环处理电子散射 let mut itrali = 0; loop { itrali += 1; // 全源函数 for id in 0..nd { st0[id] = sa0[id] - ss0[id] * model.rad[ij][id]; rad1[id] = 0.0; rdk[id] = 0.0; ali1_local[id] = 0.0; } ah = 0.0; ahout = 0.0; ahd = 0.0; u0 = 0.0; qq0 = 0.0; let mut us0 = 0.0; // 角点循环 for i in 0..nmu { let amu_i = model.amu[i]; let wtmu_i = model.wtmu[i]; let amu2 = amu_i * amu_i * wtmu_i; let mut dtau = [0.0; MDEPTH]; for id in 0..nd - 1 { dtau[id] = dt[id] / amu_i; } // --- 入射强度 (incoming) --- let mut rim = [0.0; MDEPTH]; let mut rip = [0.0; MDEPTH]; let mut aim = [0.0; MDEPTH]; let mut aip = [0.0; MDEPTH]; let mut riin = [0.0; MDEPTH]; let mut aiin = [0.0; MDEPTH]; rim[0] = model.extint[ij][i]; aim[0] = 0.0; for id in 0..nd - 1 { let dt0 = dtau[id]; let dtaup1 = dt0 + UN; let cc = dt0 * dtaup1; let aa = UN / (dt0 * dt0 + TWO * dtaup1); rim[id + 1] = (TWO * rim[id] + dt0 * st0[id] + cc * st0[id + 1]) * aa; rip[id] = (TWO * dtaup1 * rim[id] + cc * st0[id] - dt0 * st0[id + 1]) * aa; aim[id + 1] = cc * aa; aip[id] = (cc + TWO * dtaup1 * aim[id]) * aa; } for id in 1..nd - 1 { let dtt = UN / (dtau[id - 1] + dtau[id]); riin[id] = (rim[id] * dtau[id] + rip[id] * dtau[id - 1]) * dtt; aiin[id] = (aim[id] * dtau[id] + aip[id] * dtau[id - 1]) * dtt; } riin[0] = rim[0]; riin[nd - 1] = rim[nd - 1]; aiin[0] = aim[0]; aiin[nd - 1] = aim[nd - 1]; // --- 出射强度 (outgoing) --- let mut riup = [0.0; MDEPTH]; let mut aiup = [0.0; MDEPTH]; if params.idisk == 0 { rim[nd - 1] = pland + amu_i * dplan; } for id in (0..nd - 1).rev() { let dt0 = dtau[id]; let dtaup1 = dt0 + UN; let cc = dt0 * dtaup1; let aa = UN / (dt0 * dt0 + TWO * dtaup1); rim[id] = (TWO * rim[id + 1] + dt0 * st0[id + 1] + cc * st0[id]) * aa; rip[id + 1] = (TWO * dtaup1 * rim[id + 1] + cc * st0[id + 1] - dt0 * st0[id]) * aa; aim[id] = cc * aa; aip[id + 1] = (cc + TWO * dtaup1 * aim[id + 1]) * aa; } for id in 1..nd - 1 { let dtt = UN / (dtau[id - 1] + dtau[id]); riup[id] = (rim[id] * dtau[id - 1] + rip[id] * dtau[id]) * dtt; aiup[id] = (aim[id] * dtau[id - 1] + aip[id] * dtau[id]) * dtt; } riup[0] = rim[0]; riup[nd - 1] = rim[nd - 1]; aiup[0] = aim[0]; aiup[nd - 1] = aim[nd - 1]; // 对称化源函数 (Feautrier u) for id in 0..nd { let u_id = (riin[id] + riup[id]) * HALF; let al0_id = (aiin[id] + aiup[id]) * HALF; rad1[id] += wtmu_i * u_id; rdk[id] += amu2 * u_id; ali1_local[id] += wtmu_i * al0_id; } ah += amu_i * wtmu_i * (riin[0] + riup[0]) * HALF; ahd += amu_i * wtmu_i * (riin[nd - 1] + riup[nd - 1]) * HALF; ahout += amu_i * wtmu_i * riup[0]; u0 += wtmu_i * rim[0]; // 粗略对应 qq0 += amu_i * wtmu_i * rim[0]; // 粗略对应 } // 边界处理 if params.ibc == 0 { ali1_local[nd - 1] = rad1[nd - 1] / st0[nd - 1]; ali1_local[nd - 2] = rad1[nd - 2] / st0[nd - 2]; } let mut djtot: f64 = 0.0; for id in 0..nd { let deltaj = (rad1[id] - model.rad[ij][id]) / (UN + ss0[id] * ali1_local[id]); model.rad[ij][id] += deltaj; if model.rad[ij][id].abs() > 0.0 { djtot = djtot.max((deltaj / model.rad[ij][id]).abs()); } } if djtot <= params.djmax || itrali >= params.ntrali { break; } } // 存储物理量 for id in 0..nd { rad1[id] = model.rad[ij][id]; let f_val = rdk[id] / model.rad[ij][id]; model.fak[ij][id] = f_val; } model.flux[ij] = ahout * HALF; let fh0 = ah / rad1[0]; // 简化处理 model.fh[ij] = fh0; model.fhd[ij] = ahd / rad1[nd - 1]; // 第二阶段: 严格一致性消元 (Feautrier style) let mut aaa = [0.0; MDEPTH]; let mut bbb = [0.0; MDEPTH]; let mut ccc = [0.0; MDEPTH]; let mut ddd = [0.0; MDEPTH]; let mut eee = [0.0; MDEPTH]; let mut zzz = [0.0; MDEPTH]; let mut aanu = [0.0; MDEPTH]; let mut alrh = [0.0; MDEPTH]; let mut sa0_copy = sa0; let mut ss0_copy = ss0; if params.ilmcor == 3 { for id in 0..nd { sa0_copy[id] = st0[id]; ss0_copy[id] = 0.0; } } // 上边界 let mut id = 0; let mut dtp1 = dt[id]; let (b, _) = if params.isplin % 3 == 0 { (dtp1 * HALF, 0.0) } else { (dtp1 * third, dtp1 * third * HALF) }; let bq = UN / (b + 0.0); // qq0 简化 bbb[id] = (model.fak[ij][id] / dtp1 + fh0 + b) * bq + ss0_copy[id]; ccc[id] = (model.fak[ij][id + 1] / dtp1) * bq; zzz[id] = UN / bbb[id]; let vll = sa0_copy[id]; aanu[id] = vll * zzz[id]; ddd[id] = ccc[id] * zzz[id]; // 中间层 for id_idx in 1..nd - 1 { let dtm1 = dtp1; dtp1 = dt[id_idx]; let dt0 = TWO / (dtp1 + dtm1); let al = UN / dtm1 * dt0; let ga = UN / dtp1 * dt0; let (a, c) = if params.isplin % 3 == 0 { (0.0, 0.0) } else { (dtm1 * dt0 * sixth, dtp1 * dt0 * sixth) }; aaa[id_idx] = al * model.fak[ij][id_idx - 1] - a * (UN + ss0_copy[id_idx - 1]); ccc[id_idx] = ga * model.fak[ij][id_idx + 1] - c * (UN + ss0_copy[id_idx + 1]); bbb[id_idx] = (al + ga) * model.fak[ij][id_idx] + (UN - a - c) * (UN + ss0_copy[id_idx]); let vll_mid = a * sa0_copy[id_idx - 1] + c * sa0_copy[id_idx + 1] + (UN - a - c) * sa0_copy[id_idx]; aanu[id_idx] = vll_mid + aaa[id_idx] * aanu[id_idx - 1]; zzz[id_idx] = UN / (bbb[id_idx] - aaa[id_idx] * ddd[id_idx - 1]); ddd[id_idx] = ccc[id_idx] * zzz[id_idx]; aanu[id_idx] *= zzz[id_idx]; } // 下边界 id = nd - 1; if params.ibc == 0 { bbb[id] = model.fak[ij][id] / dtp1 + HALF; aaa[id] = model.fak[ij][id - 1] / dtp1; } else { let b_val = UN / dtp1; let a_val = TWO * b_val * b_val; bbb[id] = UN + ss0_copy[id] + b_val + a_val * model.fak[ij][id]; aaa[id] = a_val * model.fak[ij][id - 1]; } eee[id] = aaa[id] / bbb[id]; zzz[id] = UN / (bbb[id] - aaa[id] * ddd[id - 1]); rad1[id] = (sa0_copy[id] + aaa[id] * aanu[id - 1]) * zzz[id]; alrh[id] = zzz[id]; // 回代 for id_idx in (0..nd - 1).rev() { eee[id_idx] = aaa[id_idx] / (bbb[id_idx] - ccc[id_idx] * eee[id_idx + 1]); rad1[id_idx] = aanu[id_idx] + ddd[id_idx] * rad1[id_idx + 1]; alrh[id_idx] = zzz[id_idx] / (UN - ddd[id_idx] * eee[id_idx + 1]); } // Lambda 算子评价 if params.jali == 1 { for id in 0..nd { ali_state.ali1[id] = alrh[id]; } if params.ifali >= 6 { ali_state.alip1[0] = alrh[1] * ddd[0]; for id in 1..nd - 1 { ali_state.alim1[id] = alrh[id - 1] * eee[id]; ali_state.alip1[id] = alrh[id + 1] * ddd[id]; } ali_state.alim1[nd - 1] = alrh[nd - 2] * eee[nd - 1]; } } // 存储显式频率数据 if model.ijex[ij] > 0 { let ije = (model.ijex[ij] - 1) as usize; for id in 0..nd { model.radex[ije][id] = rad1[id]; model.fakex[ije][id] = model.fak[ij][id]; } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_rtedf1_basic() { let nd = 10; let nmu = 3; let mut rad = vec![vec![0.0; MDEPTH]; 1]; let mut fak = vec![vec![0.0; MDEPTH]; 1]; let mut flux = vec![0.0; 1]; let mut fh = vec![0.0; 1]; let mut fhd = vec![0.0; 1]; let mut radex = vec![vec![0.0; MDEPTH]; 1]; let mut fakex = vec![vec![0.0; MDEPTH]; 1]; let mut q0 = vec![0.0; 1]; let mut uu0 = vec![0.0; 1]; let params = Rtedf1Params { ij: 0, nd, nmu, idisk: 0, ibc: 0, isplin: 0, jali: 1, ifali: 0, ilmcor: 0, ilasct: 1, djmax: 1e-4, ntrali: 10, iwinbl: 0, }; let amu = vec![0.1127, 0.5000, 0.8873]; let wtmu = vec![0.2778, 0.4444, 0.2778]; let freq = vec![1e15]; let deldmz = vec![1.0; MDEPTH]; let absot = vec![1.0; MDEPTH]; let emis1 = vec![1.0; MDEPTH]; // S = 1.0 let abso1 = vec![1.0; MDEPTH]; let scat1 = vec![0.0; MDEPTH]; let temp = vec![5000.0; MDEPTH]; let ijex = vec![0]; let mut model_state = Rtedf1ModelState { amu: &amu, wtmu: &wtmu, freq: &freq, deldmz: &deldmz, absot: &absot, emis1: &emis1, abso1: &abso1, scat1: &scat1, temp: &temp, dedm1: 1e-5, rrdil: 1.0, tempbd: 0.0, extint: &vec![vec![0.0; nmu]; 1], hextrd: &vec![0.0; 1], rad: &mut rad, fak: &mut fak, flux: &mut flux, fh: &mut fh, fhd: &mut fhd, radex: &mut radex, fakex: &mut fakex, q0: &mut q0, uu0: &mut uu0, ijex: &ijex, }; let mut ali1 = vec![0.0; MDEPTH]; let mut alim1 = vec![0.0; MDEPTH]; let mut alip1 = vec![0.0; MDEPTH]; let mut ali_state = Rtedf1AliState { ali1: &mut ali1, alim1: &mut alim1, alip1: &mut alip1, }; rtedf1(¶ms, &mut model_state, &mut ali_state); // 在源函数 S=1 的均匀介质中,RAD 应趋向于 1.0 (平衡态) // 在 nd=10 时,可能还在增长中,但应为正值且合理 assert!(model_state.rad[0][nd - 1] > 0.0); assert!(model_state.rad[0][nd - 1] <= 1.0001); println!("RAD at ND: {}", model_state.rad[0][nd - 1]); } }