//! 设置 ALI 处理标志(不透明度采样模式版本)。 //! //! 重构自 TLUSTY `ijali2.f` //! 在完全混合 CL/ALI 方案中,设置个别跃迁的 ALI 处理标志。 use crate::state::atomic::{TraCor, TraPar}; use crate::state::config::BasNum; use crate::state::constants::{MITJ, MFREQ}; use crate::state::model::{CompIf, FreAux, LinFrq, LinOvr}; use crate::state::odfpar::SplCom; /// IJALI2 参数结构体 pub struct Ijali2Params<'a> { /// 基本数值 pub basnum: &'a BasNum, /// 跃迁参数 pub trapar: &'a TraPar, /// 跃迁修正标志 pub tracor: &'a mut TraCor, /// 频率辅助数据 pub freaux: &'a mut FreAux, /// 频率网格 pub frqall: &'a mut crate::state::model::FrqAll, /// 线重叠数据 pub linovr: &'a mut LinOvr, /// 线频率数据 pub linfrq: &'a mut LinFrq, /// 计算标志 pub compif: &'a CompIf, /// 样条数据(包含 FRS1) pub splcom: &'a SplCom, /// ALI 标志(NFFIX) pub nffix: i32, } /// IJALI2 输出结构体 #[derive(Debug, Clone)] pub struct Ijali2Output { /// 最大重叠线数 pub nlimax: i32, /// 总重叠线数 pub nlitot: i32, } /// 设置 ALI 处理标志(不透明度采样模式)。 /// /// # 参数 /// * `params` - 参数结构体 /// /// # 返回值 /// 返回统计信息(最大重叠线数、总重叠线数) pub fn ijali2(params: &mut Ijali2Params) -> Ijali2Output { let nfreq = params.basnum.nfreq as usize; let ntrans = params.basnum.ntrans as usize; let trapar = params.trapar; let tracor = &mut params.tracor; let freaux = &mut params.freaux; let frqall = &mut params.frqall; let linovr = &mut params.linovr; let linfrq = &mut params.linfrq; let compif = params.compif; let splcom = params.splcom; let nffix = params.nffix; let mut nlimax: i32 = 0; let mut nlitot: i32 = 0; // 初始化所有频率点 for ij in 0..nfreq { freaux.ijali[ij] = 1; // 默认 ALI frqall.ijx[ij] = 1; // 显式标志 linfrq.nlines[ij] = 0; // 重叠线数 } // 计算重叠线 for itr in 0..ntrans { if compif.linexp[itr] { continue; // 跳过经验线 } let i0 = (trapar.ifr0[itr] - 1) as usize; // 转换为 0-indexed let i1 = (trapar.ifr1[itr] - 1) as usize; for ij in i0..=i1.min(nfreq - 1) { linfrq.nlines[ij] += 1; let nlines_ij = linfrq.nlines[ij] as usize; if nlines_ij <= MITJ { linovr.itrlin[nlines_ij - 1][ij] = (itr + 1) as i32; // 存储跃迁索引(1-indexed) } } } // 计算统计数据 for ij in 0..nfreq { nlitot += linfrq.nlines[ij]; if linfrq.nlines[ij] > MITJ as i32 { panic!( "Too many overlapping lines at frequency {}: nlines={}, MITJ={}", ij + 1, linfrq.nlines[ij], MITJ ); } if linfrq.nlines[ij] > nlimax { nlimax = linfrq.nlines[ij]; } } // NFFIX == 2 时,所有跃迁都设为 ALI if nffix == 2 { for itr in 0..ntrans { tracor.lexp[itr] = 0; // false tracor.lali[itr] = 1; // true } return Ijali2Output { nlimax, nlitot }; } let xfrma = splcom.frs1.abs().log10(); // 处理每个跃迁 for itr in 0..ntrans { let indxp = trapar.indexp[itr]; let i0 = (trapar.ifr0[itr] - 1) as usize; let i1 = (trapar.ifr1[itr] - 1) as usize; let nf = i1 - i0 + 1; // 跳过频率高于 FRS1 的跃迁 if trapar.fr0[itr] > splcom.frs1 { continue; } let ijl = (trapar.ijtf[itr] - 1) as usize; // 跃迁到连续谱索引 // 处理线跃迁 if trapar.line[itr] != 0 { // 主要显式线跃迁(INDXP > 0) if indxp > 0 { tracor.lexp[itr] = 1; tracor.lali[itr] = 0; if trapar.ifc0[itr] == 0 { // 所有频率点设为显式 for ij in i0..=i1.min(nfreq - 1) { freaux.ijali[ij] = 0; } } else { tracor.lali[itr] = 1; let nfc = (trapar.ifc1[itr] - trapar.ifc0[itr]).abs() + 1; if nfc as usize == nf { // 所有频率点都是 ALI tracor.lexp[itr] = 0; } else { // 只有翼部是显式 let nfc_half = (nfc / 2) as usize; // 蓝翼 for ij in i0..=(ijl.saturating_sub(nfc_half)).min(nfreq - 1) { freaux.ijali[ij] = 0; } // 红翼 for ij in (ijl + nfc_half).min(nfreq - 1)..=i1.min(nfreq - 1) { freaux.ijali[ij] = 0; } } } } else if indxp < 0 { // 主要 ALI 线跃迁(INDXP < 0) tracor.lexp[itr] = 0; tracor.lali[itr] = 1; if trapar.ifc0[itr] != 0 { tracor.lexp[itr] = 1; let nfc = (trapar.ifc1[itr] - trapar.ifc0[itr]).abs() + 1; if nfc as usize == nf { // 所有频率点都是显式 tracor.lali[itr] = 0; for ij in i0..=i1.min(nfreq - 1) { freaux.ijali[ij] = 0; } } else { // 只有核心是显式 let nfc_half = (nfc / 2) as usize; let start = ijl.saturating_sub(nfc_half); let end = (ijl + nfc_half).min(nfreq - 1); for ij in start..=end { freaux.ijali[ij] = 0; } } } } } else { // 连续谱跃迁 if trapar.ifc0[itr] > 0 { let nfc = (trapar.ifc1[itr] - trapar.ifc0[itr] + 1) as usize; for ij in 1..=nfc { let idx = ijl.saturating_sub(ij - 1); if idx < nfreq { freaux.ijali[idx] = 0; } } } } } Ijali2Output { nlimax, nlitot } } #[cfg(test)] mod tests { use super::*; use crate::state::atomic::{TraCor, TraPar}; use crate::state::config::BasNum; use crate::state::constants::{MFREQ, MTRANS}; use crate::state::model::{CompIf, FreAux, FrqAll, LinFrq, LinOvr}; use crate::state::odfpar::SplCom; fn create_test_params() -> ( BasNum, TraPar, TraCor, FreAux, FrqAll, LinOvr, LinFrq, CompIf, SplCom, ) { let mut basnum = BasNum::default(); basnum.nfreq = 100; basnum.ntrans = 5; let mut trapar = TraPar::default(); // 设置跃迁 0 为主要显式线跃迁 trapar.indexp[0] = 1; trapar.ifr0[0] = 10; trapar.ifr1[0] = 20; trapar.ifc0[0] = 0; // 所有频率点显式 trapar.fr0[0] = 1e14; // 低于 FRS1 trapar.line[0] = 1; // 线跃迁 trapar.ijtf[0] = 15; // 设置跃迁 1 为主要 ALI 线跃迁 trapar.indexp[1] = -1; trapar.ifr0[1] = 30; trapar.ifr1[1] = 40; trapar.ifc0[1] = 0; trapar.fr0[1] = 1e14; trapar.line[1] = 1; trapar.ijtf[1] = 35; // 设置跃迁 2 为连续谱跃迁 trapar.indexp[2] = 1; trapar.ifr0[2] = 50; trapar.ifr1[2] = 60; trapar.ifc0[2] = 2; trapar.ifc1[2] = 5; trapar.fr0[2] = 1e14; trapar.line[2] = 0; // 连续谱 trapar.ijtf[2] = 55; let tracor = TraCor::default(); let freaux = FreAux::default(); let frqall = FrqAll::default(); let linovr = LinOvr::default(); let linfrq = LinFrq::default(); let compif = CompIf::default(); let mut splcom = SplCom::default(); splcom.frs1 = 1e15; // 高于所有测试跃迁频率 (basnum, trapar, tracor, freaux, frqall, linovr, linfrq, compif, splcom) } #[test] fn test_ijali2_nffix2() { let (basnum, trapar, mut tracor, mut freaux, mut frqall, mut linovr, mut linfrq, compif, splcom) = create_test_params(); let mut params = Ijali2Params { basnum: &basnum, trapar: &trapar, tracor: &mut tracor, freaux: &mut freaux, frqall: &mut frqall, linovr: &mut linovr, linfrq: &mut linfrq, compif: &compif, splcom: &splcom, nffix: 2, // 强制所有 ALI }; let result = ijali2(&mut params); // 验证所有跃迁都设为 ALI for itr in 0..basnum.ntrans as usize { assert_eq!(params.tracor.lexp[itr], 0); assert_eq!(params.tracor.lali[itr], 1); } } #[test] fn test_ijali2_explicit_line() { let (basnum, trapar, mut tracor, mut freaux, mut frqall, mut linovr, mut linfrq, compif, splcom) = create_test_params(); let mut params = Ijali2Params { basnum: &basnum, trapar: &trapar, tracor: &mut tracor, freaux: &mut freaux, frqall: &mut frqall, linovr: &mut linovr, linfrq: &mut linfrq, compif: &compif, splcom: &splcom, nffix: 0, }; let _result = ijali2(&mut params); // 验证跃迁 0(主要显式线跃迁) assert_eq!(params.tracor.lexp[0], 1); assert_eq!(params.tracor.lali[0], 0); // 验证频率点 9-19(IFR0=10 到 IFR1=20,0-indexed 为 9-19)设为显式 for ij in 9..20 { assert_eq!(params.freaux.ijali[ij], 0, "ijali[{}] should be 0", ij); } } #[test] fn test_ijali2_ali_line() { let (basnum, trapar, mut tracor, mut freaux, mut frqall, mut linovr, mut linfrq, compif, splcom) = create_test_params(); let mut params = Ijali2Params { basnum: &basnum, trapar: &trapar, tracor: &mut tracor, freaux: &mut freaux, frqall: &mut frqall, linovr: &mut linovr, linfrq: &mut linfrq, compif: &compif, splcom: &splcom, nffix: 0, }; let _result = ijali2(&mut params); // 验证跃迁 1(主要 ALI 线跃迁) assert_eq!(params.tracor.lexp[1], 0); assert_eq!(params.tracor.lali[1], 1); // 验证频率点 29-39 仍为 ALI(默认值) for ij in 29..40 { assert_eq!(params.freaux.ijali[ij], 1, "ijali[{}] should be 1", ij); } } }