SpectraRust/src/math/ijali2.rs
2026-03-23 15:45:52 +08:00

364 lines
11 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 设置 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-19IFR0=10 到 IFR1=200-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);
}
}
}