364 lines
11 KiB
Rust
364 lines
11 KiB
Rust
//! 设置 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);
|
||
}
|
||
}
|
||
}
|