//! ALI (加速 Lambda 迭代) Kantorovich 迭代简化版本 - ALISK2。 //! //! 重构自 TLUSTY `alisk2.f` //! //! # 功能 //! //! 简化版 ALISET,用于 Kantorovich 迭代。 //! 计算所有必要的 ALI 参数和辐射跃迁率(类似于 RATES)。 //! //! # 与 ALISK1 的区别 //! //! - 增加 FLEXP 数组处理 //! - 支持 Opacity Sampling 选项 (ISPODF) //! - 扩展频率数据存储顺序不同 use crate::state::constants::{MDEPTH, MFREQ, MTRANS, UN, HK, PCK}; // ============================================================================ // 配置结构体 // ============================================================================ /// ALISK2 配置参数。 #[derive(Debug, Clone)] pub struct Alisk2Config { /// 深度修正数(负值表示不计算 Rosseland) pub ndre: i32, /// 当前迭代次数 pub iter: i32, /// 最终迭代标志 pub lfin: bool, /// 混合参数 (>0 强制计算 Rosseland) pub hmix0: f64, /// 不透明度表格标志 (<0 跳过跃迁处理) pub ioptab: i32, /// ODF 采样标志 (0=标准模式, >=1=ODF 采样) pub ispodf: i32, } impl Default for Alisk2Config { fn default() -> Self { Self { ndre: 0, iter: 1, lfin: false, hmix0: 0.0, ioptab: 0, ispodf: 0, } } } // ============================================================================ // 输入/输出结构体 // ============================================================================ /// ALISK2 频率相关参数。 pub struct Alisk2FreqParams<'a> { /// 频率数 pub nfreq: usize, /// 频率数组 [nfreq] pub freq: &'a [f64], /// 频率权重 [nfreq] pub w0e: &'a [f64], /// 频率索引标志 (-1 表示跳过) [nfreq] pub ijx: &'a [i32], /// 扩展频率索引 (>0 表示扩展) [nfreq] pub ijex: &'a [i32], /// 线频率索引 (>0 表示有线) [nfreq] pub ijlin: &'a [i32], /// 重叠线数 [nfreq] pub nlines: &'a [i32], /// 普朗克函数 [nfreq × nd] - BNUE pub bnue: &'a [f64], /// 线线型 [nd × nfreq] - PRFLIN (注意:与 ALISK1 不同,是 [nd][nfreq]) pub prflin: &'a [f64], } /// ALISK2 原子参数。 pub struct Alisk2AtomicParams<'a> { /// 连续谱跃迁数 pub ntranc: usize, /// 总跃迁数 pub ntrans: usize, /// 束缚-自由跃迁索引 [ntranc], 1-indexed pub itrbf: &'a [i32], /// 低能级索引 [ntrans], 1-indexed pub ilow: &'a [i32], /// 高能级索引 [ntrans], 1-indexed pub iup: &'a [i32], /// Macfarlane 下沉修正索引 [ntrans] pub mcdw: &'a [i32], /// 能级合并组索引 [mlevel] pub imrg: &'a [i32], /// 能级频率加权选项 [mlevel] pub ifwop: &'a [i32], /// 束缚-自由截面 [ntranc × nfreq] pub cross: &'a [f64], /// 重叠线跃迁索引 [maxlines × nfreq], 1-indexed pub trlin: &'a [i32], /// 跃迁起始频率索引 [ntrans] pub ifr0: &'a [i32], /// 跃迁结束频率索引 [ntrans] pub ifr1: &'a [i32], /// 跃迁采样起始索引 [ntrans] pub kfr0: &'a [i32], /// 跃迁指数类型 [ntrans] pub indexp: &'a [i32], /// 线排除标志 [ntrans] pub linexp: &'a [bool], /// 合并 Gaunt 因子 [mmer × nd] pub sgmg: &'a [f64], /// 下沉因子 [maxcdw × nd] pub dwf1: &'a [f64], /// ITRA 索引矩阵 [mlevel × mlevel] pub itra: &'a [i32], /// Fe 不透明度采样数据 [nd_fe × nfreq_fe] - 用于 ISPODF > 0 pub sigfe: &'a [f64], } /// ALISK2 模型状态参数。 pub struct Alisk2ModelState<'a> { /// 深度点数 pub nd: usize, /// 温度 [nd] pub temp: &'a [f64], /// 电子密度 [nd] pub elec: &'a [f64], /// 总粒子密度 [nd] pub dens: &'a [f64], /// 密度倒数 [nd] pub dens1: &'a [f64], /// 柱质量密度 [nd] pub dm: &'a [f64], /// HK/T [nd] pub hkt1: &'a [f64], /// 辐射等效积分 [nd] pub reint: &'a [f64], /// 辐射等效扩散 [nd] pub redif: &'a [f64], /// CRSW 修正因子 [nd] pub crsw: &'a [f64], /// 零占据数标志 [mlevel × nd] pub ipzero: &'a [i32], /// JID 索引 [nd] - 用于 ISPODF > 0 pub jidi: &'a [i32], /// XJID 因子 [nd] - 用于 ISPODF > 0 pub xjid: &'a [f64], } /// ALISK2 输出状态。 pub struct Alisk2OutputState<'a> { // 累积量 [nd] /// 冷却率积分 pub fcooli: &'a mut [f64], /// 固定辐射通量 pub flfix: &'a mut [f64], /// 显式辐射通量 (ALISK2 特有) pub flexp: &'a mut [f64], /// 辐射压力导数 pub fprd: &'a mut [f64], /// 辐射通量红翼 pub flrd: &'a mut [f64], /// 辐射压力总量 pub pradt: &'a mut [f64], /// 辐射压力吸收 pub prada: &'a mut [f64], /// 参考辐射压力 [输出] pub prd0: &'a mut f64, // 跃迁率 [ntrans × nd] /// 向上跃迁率 pub rru: &'a mut [f64], /// 向下跃迁率 pub rrd: &'a mut [f64], // Rosseland 平均 /// Rosseland 平均不透明度 [nd] pub abrosd: &'a mut [f64], /// Rosseland 累加量 [nd] pub sumdpl: &'a mut [f64], // 扩展频率数据 /// 扩展吸收系数 [存储索引 × nd] pub absoex: &'a mut [f64], /// 扩展发射系数 [存储索引 × nd] pub emisex: &'a mut [f64], /// 扩展散射系数 [存储索引 × nd] pub scatex: &'a mut [f64], // 单频率工作数组(由 OPACF1/RTEFR1 填充) /// 当前频率吸收系数 [nd] pub abso1: &'a mut [f64], /// 当前频率发射系数 [nd] pub emis1: &'a mut [f64], /// 当前频率散射系数 [nd] pub scat1: &'a mut [f64], /// 当前频率辐射强度 [nd] pub rad1: &'a mut [f64], // 冷却率输出 [nd] pub fcool: &'a mut [f64], } /// ALISK2 输出结果。 #[derive(Debug, Clone)] pub struct Alisk2Output { /// 是否执行了计算 pub computed: bool, /// Rosseland 标志 pub lross: bool, /// 最小辐射压力比 pub prdx: f64, } // ============================================================================ // 核心计算函数 // ============================================================================ /// ALI Kantorovich 迭代简化版本 (ALISK2)。 /// /// 计算所有必要的 ALI 参数和辐射跃迁率。 /// /// # 参数 /// /// * `config` - 配置参数 /// * `freq_params` - 频率相关参数 /// * `atomic_params` - 原子参数 /// * `model_state` - 模型状态 /// * `output_state` - 输出状态(可变) /// /// # 返回值 /// /// 返回 `Alisk2Output`,包含计算结果信息。 pub fn alisk2_pure( config: &Alisk2Config, freq_params: &Alisk2FreqParams, atomic_params: &Alisk2AtomicParams, model_state: &Alisk2ModelState, output_state: &mut Alisk2OutputState, ) -> Alisk2Output { let nd = model_state.nd; let nfreq = freq_params.nfreq; let ntrans = atomic_params.ntrans; // ======================================================================== // 1. 初始化速率和其他量 // ======================================================================== for id in 0..nd { output_state.fcooli[id] = 0.0; output_state.flfix[id] = 0.0; output_state.flexp[id] = 0.0; // ALISK2 特有 output_state.fprd[id] = 0.0; output_state.flrd[id] = 0.0; output_state.pradt[id] = 0.0; output_state.prada[id] = 0.0; for itr in 0..ntrans { output_state.rru[itr * nd + id] = 0.0; output_state.rrd[itr * nd + id] = 0.0; } } *output_state.prd0 = 0.0; // ======================================================================== // 2. 确定 LROSS 标志 // ======================================================================== let mut lross = (config.ndre <= 0 && config.iter == 1) || config.lfin; if config.hmix0 > 0.0 { lross = true; } if lross { for id in 0..nd { output_state.abrosd[id] = 0.0; output_state.sumdpl[id] = 0.0; } } // ======================================================================== // 3. 遍历频率点 // ======================================================================== for ij in 0..nfreq { // 跳过标记为 -1 的频率 if freq_params.ijx[ij] == -1 { continue; } let fr = freq_params.freq[ij]; let w0 = freq_params.w0e[ij]; // ---------------------------------------------------------------- // 3a. 调用 OPACF1(IJ) - 计算不透明度 // ---------------------------------------------------------------- // 注意:实际实现需要调用 opacf1 函数 // ---------------------------------------------------------------- // 3b. 调用 RTEFR1(IJ) - 辐射转移 // ---------------------------------------------------------------- // 注意:实际实现需要调用 rtefr1 函数 // ---------------------------------------------------------------- // 3c. 调用 ALIFRK(IJ) - ALI 系数 // ---------------------------------------------------------------- // 注意:实际实现需要调用 alifrk 函数 // ---------------------------------------------------------------- // 3d. 可选:调用 ROSSTD(IJ) - Rosseland 贡献 // ---------------------------------------------------------------- // if lross { rosstd_contribute(...); } // 跳过跃迁处理(如果 ioptab < 0) if config.ioptab < 0 { continue; } // ---------------------------------------------------------------- // 3e. 存储扩展频率数据 (ALISK2 顺序:在跃迁处理后) // ---------------------------------------------------------------- let ije = freq_params.ijex[ij]; if ije > 0 { let ije_idx = (ije - 1) as usize; for id in 0..nd { output_state.absoex[ije_idx * nd + id] = output_state.abso1[id]; output_state.emisex[ije_idx * nd + id] = output_state.emis1[id]; output_state.scatex[ije_idx * nd + id] = output_state.scat1[id]; } } // ---------------------------------------------------------------- // 3f. 处理连续谱跃迁 // ---------------------------------------------------------------- process_continuum_transitions_alisk2( ij, fr, w0, nd, freq_params, atomic_params, model_state, output_state, ); // ---------------------------------------------------------------- // 3g. 处理线跃迁 // ---------------------------------------------------------------- if config.ispodf == 0 { // 标准模式 process_line_transitions_standard( ij, fr, w0, nd, freq_params, atomic_params, model_state, output_state, ); } else { // ODF 采样模式 process_line_transitions_odf( ij, fr, w0, nd, freq_params, atomic_params, model_state, output_state, ); } } // ======================================================================== // 4. 后处理:乘以频率无关常数 // ======================================================================== for id in 0..nd { // FCOOL(ID) = REINT(ID) * FCOOLI(ID) - REDIF(ID) * FLFIX(ID) output_state.fcool[id] = model_state.reint[id] * output_state.fcooli[id] - model_state.redif[id] * output_state.flfix[id]; // CRSW 修正 if (model_state.crsw[id] - UN).abs() > 1e-30 { for itr in 0..ntrans { output_state.rru[itr * nd + id] *= model_state.crsw[id]; output_state.rrd[itr * nd + id] *= model_state.crsw[id]; } } } // ======================================================================== // 5. 辐射压力计算 // ======================================================================== let mut prdx = 1.0; for id in 0..nd { output_state.pradt[id] *= PCK; output_state.prada[id] *= PCK; if output_state.prada[id] > 0.0 { let prdr = output_state.pradt[id] / output_state.prada[id]; if prdr < prdx { prdx = prdr; } } } // PRD0 = PRD0 / DENS1(1) * DM(1) * PCK *output_state.prd0 = *output_state.prd0 / model_state.dens1[0] * model_state.dm[0] * PCK; // ======================================================================== // 6. Rosseland 平均不透明度 // ======================================================================== if lross { for id in 0..nd { if output_state.abrosd[id] > 0.0 { output_state.abrosd[id] = output_state.sumdpl[id] / (output_state.abrosd[id] * model_state.dens[id]); } } } Alisk2Output { computed: true, lross, prdx, } } /// 处理连续谱跃迁 (ALISK2 版本)。 fn process_continuum_transitions_alisk2( ij: usize, fr: f64, w0: f64, nd: usize, freq_params: &Alisk2FreqParams, atomic_params: &Alisk2AtomicParams, model_state: &Alisk2ModelState, output_state: &mut Alisk2OutputState, ) { let ntranc = atomic_params.ntranc; // 工作数组 RBNU(MDEPTH) let mut rbnu = vec![0.0; MDEPTH]; // 计算 RBNU = (RAD1 + BNUE) * EXP(-HKT1 * FR) for id in 0..nd { let bnue_ij = freq_params.bnue[ij * nd + id]; rbnu[id] = (output_state.rad1[id] + bnue_ij) * (-model_state.hkt1[id] * fr).exp(); } // 遍历连续谱跃迁 for ibft in 0..ntranc { let itr = (atomic_params.itrbf[ibft] - 1) as usize; let sg = atomic_params.cross[ibft * freq_params.nfreq + ij]; if sg <= 0.0 { continue; } let ii = (atomic_params.ilow[itr] - 1) as usize; let jj = (atomic_params.iup[itr] - 1) as usize; // 遍历深度点 for id in 0..nd { // 检查零占据数 if model_state.ipzero[ii * nd + id] != 0 || model_state.ipzero[jj * nd + id] != 0 { continue; } let mut sg_local = sg; // 频率加权修正 if atomic_params.ifwop[ii] >= 0 { let icdw = atomic_params.mcdw[itr]; if icdw >= 1 { let icdw_idx = (icdw - 1) as usize; sg_local *= atomic_params.dwf1[icdw_idx * nd + id]; } } else { let imer = atomic_params.imrg[ii] as usize; sg_local = atomic_params.sgmg[imer * nd + id]; } let sgw0 = sg_local * w0; // 累积跃迁率 output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id]; output_state.rrd[itr * nd + id] += sgw0 * rbnu[id]; } } } /// 处理线跃迁 - 标准模式。 fn process_line_transitions_standard( ij: usize, fr: f64, w0: f64, nd: usize, freq_params: &Alisk2FreqParams, atomic_params: &Alisk2AtomicParams, model_state: &Alisk2ModelState, output_state: &mut Alisk2OutputState, ) { // 工作数组 RBNU let mut rbnu = vec![0.0; MDEPTH]; for id in 0..nd { let bnue_ij = freq_params.bnue[ij * nd + id]; rbnu[id] = (output_state.rad1[id] + bnue_ij) * (-model_state.hkt1[id] * fr).exp(); } // 主线跃迁 let ijlin_ij = freq_params.ijlin[ij]; if ijlin_ij > 0 { let itr = (ijlin_ij - 1) as usize; let ii = (atomic_params.ilow[itr] - 1) as usize; let jj = (atomic_params.iup[itr] - 1) as usize; for id in 0..nd { if model_state.ipzero[ii * nd + id] != 0 || model_state.ipzero[jj * nd + id] != 0 { continue; } // PRFLIN(ID, IJ) - 注意:Fortran 是 [nd, nfreq] let sgw0 = freq_params.prflin[id * freq_params.nfreq + ij] * w0; output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id]; output_state.rrd[itr * nd + id] += sgw0 * rbnu[id]; } } // 重叠线 let nlines_ij = freq_params.nlines[ij]; if nlines_ij <= 0 { return; } for ilint in 0..nlines_ij as usize { let itr = (atomic_params.trlin[ilint * freq_params.nfreq + ij] - 1) as usize; if atomic_params.linexp[itr] { continue; } let ii = (atomic_params.ilow[itr] - 1) as usize; let jj = (atomic_params.iup[itr] - 1) as usize; let ij0 = atomic_params.ifr0[itr] as usize; let ij1 = atomic_params.ifr1[itr] as usize; // 查找插值位置 let mut ij0_idx = ij0; for ijt in ij0..=ij1 { if freq_params.freq[ijt] <= fr { ij0_idx = ijt; break; } } let ij1_idx = if ij0_idx > 0 { ij0_idx - 1 } else { 0 }; // 插值系数 let freq_ij0 = freq_params.freq[ij0_idx]; let freq_ij1 = freq_params.freq[ij1_idx]; let denom = freq_ij1 - freq_ij0; let (a1, a2) = if denom.abs() > 1e-30 { let a1 = (fr - freq_ij0) / denom * w0; (a1, w0 - a1) } else { (w0, 0.0) }; // 遍历深度点 for id in 0..nd { if model_state.ipzero[ii * nd + id] != 0 || model_state.ipzero[jj * nd + id] != 0 { continue; } let sgw0 = a1 * freq_params.prflin[id * freq_params.nfreq + ij1_idx] + a2 * freq_params.prflin[id * freq_params.nfreq + ij0_idx]; output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id]; output_state.rrd[itr * nd + id] += sgw0 * rbnu[id]; } } } /// 处理线跃迁 - ODF 采样模式。 fn process_line_transitions_odf( ij: usize, _fr: f64, w0: f64, nd: usize, freq_params: &Alisk2FreqParams, atomic_params: &Alisk2AtomicParams, model_state: &Alisk2ModelState, output_state: &mut Alisk2OutputState, ) { // 工作数组 RBNU let mut rbnu = vec![0.0; MDEPTH]; // 在 ODF 模式下,使用简化计算 for id in 0..nd { rbnu[id] = output_state.rad1[id]; // 简化 } let nlines_ij = freq_params.nlines[ij]; if nlines_ij <= 0 { return; } for ilint in 0..nlines_ij as usize { let itr = (atomic_params.trlin[ilint * freq_params.nfreq + ij] - 1) as usize; let kj = (ij as i32 - atomic_params.ifr0[itr] + atomic_params.kfr0[itr]) as usize; let indxpa = atomic_params.indexp[itr].abs(); let ii = (atomic_params.ilow[itr] - 1) as usize; let jj = (atomic_params.iup[itr] - 1) as usize; if indxpa != 3 && indxpa != 4 { // 标准处理 for id in 0..nd { if model_state.ipzero[ii * nd + id] != 0 || model_state.ipzero[jj * nd + id] != 0 { continue; } let sgw0 = freq_params.prflin[id * freq_params.nfreq + kj] * w0; output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id]; output_state.rrd[itr * nd + id] += sgw0 * rbnu[id]; } } else { // 特殊处理(使用 SIGFE 插值) for id in 0..nd { if model_state.ipzero[ii * nd + id] != 0 || model_state.ipzero[jj * nd + id] != 0 { continue; } let kjd = model_state.jidi[id] as usize; let xjid = model_state.xjid[id]; // SIGFE 插值 let sg = (xjid * atomic_params.sigfe[kjd * freq_params.nfreq + kj] + (UN - xjid) * atomic_params.sigfe[(kjd + 1) * freq_params.nfreq + kj]) .exp(); let sgw0 = sg * w0; output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id]; output_state.rrd[itr * nd + id] += sgw0 * rbnu[id]; } } } } // ============================================================================ // 测试 // ============================================================================ #[cfg(test)] mod tests { use super::*; fn create_test_config() -> Alisk2Config { Alisk2Config { ndre: 0, iter: 1, lfin: false, hmix0: 0.0, ioptab: -1, // 跳过跃迁处理 ispodf: 0, } } #[test] fn test_alisk2_initialization() { let config = create_test_config(); let nfreq = 10; let nd = 5; let ntrans = 3; let freq = vec![1e14; nfreq]; let w0e = vec![1.0; nfreq]; let ijx = vec![0; nfreq]; let ijex = vec![0; nfreq]; let ijlin = vec![0; nfreq]; let nlines = vec![0; nfreq]; let bnue = vec![0.0; nfreq * nd]; let prflin = vec![0.0; nd * nfreq]; let freq_params = Alisk2FreqParams { nfreq, freq: &freq, w0e: &w0e, ijx: &ijx, ijex: &ijex, ijlin: &ijlin, nlines: &nlines, bnue: &bnue, prflin: &prflin, }; let itrbf = vec![1, 2, 3]; let ilow = vec![1, 1, 2]; let iup = vec![2, 3, 3]; let mcdw = vec![0; ntrans]; let imrg = vec![0; 10]; let ifwop = vec![0; 10]; let cross = vec![0.0; 3 * nfreq]; let trlin = vec![0; 10 * nfreq]; let ifr0 = vec![0; ntrans]; let ifr1 = vec![0; ntrans]; let kfr0 = vec![0; ntrans]; let indexp = vec![0; ntrans]; let linexp = vec![false; ntrans]; let sgmg = vec![1.0; 5 * nd]; let dwf1 = vec![1.0; 5 * nd]; let itra = vec![0; 100]; let sigfe = vec![0.0; 100 * nfreq]; let atomic_params = Alisk2AtomicParams { ntranc: 3, ntrans, itrbf: &itrbf, ilow: &ilow, iup: &iup, mcdw: &mcdw, imrg: &imrg, ifwop: &ifwop, cross: &cross, trlin: &trlin, ifr0: &ifr0, ifr1: &ifr1, kfr0: &kfr0, indexp: &indexp, linexp: &linexp, sgmg: &sgmg, dwf1: &dwf1, itra: &itra, sigfe: &sigfe, }; let temp = vec![10000.0; nd]; let elec = vec![1e12; nd]; let dens = vec![1e14; nd]; let dens1 = vec![1e-14; nd]; let dm = vec![1e-3; nd]; let hkt1 = vec![4.8e-12; nd]; let reint = vec![1.0; nd]; let redif = vec![0.0; nd]; let crsw = vec![1.0; nd]; let ipzero = vec![0; 100 * nd]; let jidi = vec![0; nd]; let xjid = vec![0.0; nd]; let model_state = Alisk2ModelState { nd, temp: &temp, elec: &elec, dens: &dens, dens1: &dens1, dm: &dm, hkt1: &hkt1, reint: &reint, redif: &redif, crsw: &crsw, ipzero: &ipzero, jidi: &jidi, xjid: &xjid, }; let mut fcooli = vec![0.0; nd]; let mut flfix = vec![0.0; nd]; let mut flexp = vec![0.0; nd]; let mut fprd = vec![0.0; nd]; let mut flrd = vec![0.0; nd]; let mut pradt = vec![0.0; nd]; let mut prada = vec![0.0; nd]; let mut prd0 = 0.0; let mut rru = vec![0.0; ntrans * nd]; let mut rrd = vec![0.0; ntrans * nd]; let mut abrosd = vec![0.0; nd]; let mut sumdpl = vec![0.0; nd]; let mut absoex = vec![0.0; 10 * nd]; let mut emisex = vec![0.0; 10 * nd]; let mut scatex = vec![0.0; 10 * nd]; let mut abso1 = vec![1.0; nd]; let mut emis1 = vec![0.5; nd]; let mut scat1 = vec![0.1; nd]; let mut rad1 = vec![0.8; nd]; let mut fcool = vec![0.0; nd]; let mut output_state = Alisk2OutputState { fcooli: &mut fcooli, flfix: &mut flfix, flexp: &mut flexp, fprd: &mut fprd, flrd: &mut flrd, pradt: &mut pradt, prada: &mut prada, prd0: &mut prd0, rru: &mut rru, rrd: &mut rrd, abrosd: &mut abrosd, sumdpl: &mut sumdpl, absoex: &mut absoex, emisex: &mut emisex, scatex: &mut scatex, abso1: &mut abso1, emis1: &mut emis1, scat1: &mut scat1, rad1: &mut rad1, fcool: &mut fcool, }; let output = alisk2_pure(&config, &freq_params, &atomic_params, &model_state, &mut output_state); assert!(output.computed); assert!(output.lross); // 因为 iter=1 且 ndre=0 } #[test] fn test_alisk2_flexp_initialization() { // 测试 FLEXP 初始化(ALISK2 特有) let nd = 3; let mut flexp = vec![1.0; nd]; // 初始化为非零值 // 验证 FLEXP 会被初始化为零 let config = Alisk2Config { ioptab: -1, ..Default::default() }; let nfreq = 1; let freq = vec![1e14; nfreq]; let w0e = vec![1.0; nfreq]; let ijx = vec![-1; nfreq]; // 跳过所有频率 let ijex = vec![0; nfreq]; let ijlin = vec![0; nfreq]; let nlines = vec![0; nfreq]; let bnue = vec![0.0; nfreq * nd]; let prflin = vec![0.0; nd * nfreq]; let freq_params = Alisk2FreqParams { nfreq, freq: &freq, w0e: &w0e, ijx: &ijx, ijex: &ijex, ijlin: &ijlin, nlines: &nlines, bnue: &bnue, prflin: &prflin, }; let atomic_params = Alisk2AtomicParams { ntranc: 0, ntrans: 0, itrbf: &[], ilow: &[], iup: &[], mcdw: &[], imrg: &[], ifwop: &[], cross: &[], trlin: &[], ifr0: &[], ifr1: &[], kfr0: &[], indexp: &[], linexp: &[], sgmg: &[], dwf1: &[], itra: &[], sigfe: &[], }; let temp = vec![10000.0; nd]; let elec = vec![1e12; nd]; let dens = vec![1e14; nd]; let dens1 = vec![1e-14; nd]; let dm = vec![1e-3; nd]; let hkt1 = vec![4.8e-12; nd]; let reint = vec![1.0; nd]; let redif = vec![0.0; nd]; let crsw = vec![1.0; nd]; let ipzero = vec![0; 100 * nd]; let jidi = vec![0; nd]; let xjid = vec![0.0; nd]; let model_state = Alisk2ModelState { nd, temp: &temp, elec: &elec, dens: &dens, dens1: &dens1, dm: &dm, hkt1: &hkt1, reint: &reint, redif: &redif, crsw: &crsw, ipzero: &ipzero, jidi: &jidi, xjid: &xjid, }; let mut fcooli = vec![0.0; nd]; let mut flfix = vec![0.0; nd]; let mut fprd = vec![0.0; nd]; let mut flrd = vec![0.0; nd]; let mut pradt = vec![0.0; nd]; let mut prada = vec![0.0; nd]; let mut prd0 = 0.0; let mut rru = vec![0.0; 1]; let mut rrd = vec![0.0; 1]; let mut abrosd = vec![0.0; nd]; let mut sumdpl = vec![0.0; nd]; let mut absoex = vec![0.0; 10 * nd]; let mut emisex = vec![0.0; 10 * nd]; let mut scatex = vec![0.0; 10 * nd]; let mut abso1 = vec![1.0; nd]; let mut emis1 = vec![0.5; nd]; let mut scat1 = vec![0.1; nd]; let mut rad1 = vec![0.8; nd]; let mut fcool = vec![0.0; nd]; let mut output_state = Alisk2OutputState { fcooli: &mut fcooli, flfix: &mut flfix, flexp: &mut flexp, fprd: &mut fprd, flrd: &mut flrd, pradt: &mut pradt, prada: &mut prada, prd0: &mut prd0, rru: &mut rru, rrd: &mut rrd, abrosd: &mut abrosd, sumdpl: &mut sumdpl, absoex: &mut absoex, emisex: &mut emisex, scatex: &mut scatex, abso1: &mut abso1, emis1: &mut emis1, scat1: &mut scat1, rad1: &mut rad1, fcool: &mut fcool, }; let _ = alisk2_pure(&config, &freq_params, &atomic_params, &model_state, &mut output_state); // FLEXP 应该被初始化为零 for id in 0..nd { assert_eq!(output_state.flexp[id], 0.0); } } }