//! ALI 参数和辐射跃迁率计算 - 变体 2(用于速率矩阵对占据数的导数)。 //! //! 重构自 TLUSTY `alist2.f` //! //! 计算所有必要的 ALI 参数和辐射跃迁率。 //! 这是 RATES1 的类似函数,用于速率矩阵对占据数的导数计算。 //! //! ## IRDER 模式 //! - IRDER = 1: 计算 APT, APN (T 和 N 导数) //! - IRDER = 2: 计算 APP (能级导数) //! - IRDER = 3: 计算 APT, APN, APP (所有导数) use crate::tlusty::state::constants::{MDEPTH, MFREQ, MLEVEL, MTRANS, MLVEXP, UN}; /// ALIST2 输入参数(只读) pub struct Alist2Params<'a> { // 维度参数 /// 深度点数 pub nd: usize, /// 频率点数 pub nfreq: usize, /// 能级数 pub nlevel: usize, /// 离子数 pub nion: usize, /// 束缚-自由跃迁数 pub ntranc: usize, /// 束缚-束缚跃迁数 pub ntrans: usize, /// 线性化能级数 pub nlvexp: usize, // 控制参数 /// 辐射导数模式 (1, 2, 3) pub irder: i32, /// 迭代次数 pub iter: i32, /// ODF/OS 选项 pub ispodf: i32, /// 不透明度表选项 pub ioptab: i32, /// 最终迭代标志 pub lfin: bool, /// 混合长度参数 pub hmix0: f64, /// 对流开关 pub crsw: &'a [f64], // 频率相关 /// 频率数组 [nfreq] pub freq: &'a [f64], /// 频率权重 [nfreq] pub w0e: &'a [f64], /// 跳过标志 [nfreq] pub ijx: &'a [i32], /// ALI 索引 [nfreq] pub ijali: &'a [i32], /// 普朗克函数 [nfreq] pub bnue: &'a [f64], // 模型状态 /// 温度 [nd] pub temp: &'a [f64], /// 电子密度 [nd] pub elec: &'a [f64], /// 总粒子密度 [nd] pub dens: &'a [f64], /// 1/密度 [nd] pub dens1: &'a [f64], /// 柱质量 [nd] pub dm: &'a [f64], /// 深度差分 [nd-1] pub deldmz: &'a [f64], /// h/kT [nd] pub hkt1: &'a [f64], /// h/(kT)² [nd] pub hkt21: &'a [f64], // 原子/能级数据 /// 元素索引 [nlevel] pub iel: &'a [i32], /// 原子索引 [nlevel] pub iatm: &'a [i32], /// 能级类型 [nlevel] pub ilk: &'a [i32], /// 模型能级 [nlevel] pub imodl: &'a [i32], /// LTE 能级标志 [nlevel] pub iltlev: &'a [i32], /// 显式能级索引 [nlevel] pub iiexp: &'a [i32], /// 固定原子标志 [nlevel] pub iifix: &'a [i32], /// 零占据数标志 [nlevel × nd] pub ipzero: &'a [i32], /// 参考原子 [nd × natom] pub nrefs: &'a [i32], // 跃迁数据 /// 束缚-自由跃迁索引 [ntranc] pub itrbf: &'a [i32], /// 跃迁下能级 [ntrans] pub ilow: &'a [i32], /// 跃迁上能级 [ntrans] pub iup: &'a [i32], /// 跃迁阈值频率 [ntrans] pub fr0: &'a [i32], /// 跃迁频率范围起点 [ntrans] pub ifr0: &'a [i32], /// 跃迁频率范围终点 [ntrans] pub ifr1: &'a [i32], /// 跃迁频率偏移 [ntrans] pub kfr0: &'a [i32], /// 跃迁索引类型 [ntrans] pub indexp: &'a [i32], /// 截面 [ntranc × nfreq] pub cross: &'a [f64], /// 跃迁吸收 [ntrans × nd] pub abtra: &'a [f64], /// 跃迁发射 [ntrans × nd] pub emtra: &'a [f64], /// Van der Waals 宽化因子索引 [ntrans] pub mcdw: &'a [i32], /// Van der Waals 宽化因子 [nion × nd] pub dwf1: &'a [f64], /// 合并截面 [nion × nd] pub sgmg: &'a [f64], /// 能级合并索引 [nlevel] pub imrg: &'a [i32], /// 线显式标志 [ntrans] pub linexp: &'a [bool], // 线数据 /// 频率对应的主线索引 [nfreq] pub ijlin: &'a [i32], /// 频率对应的重叠线数 [nfreq] pub nlines: &'a [i32], /// 重叠线索引 [nfreq × nlines_max] pub itrlin: &'a [i32], /// 线轮廓 [nd × nfreq] pub prflin: &'a [f64], // 辐射场 /// 辐射强度 [nd] pub rad1: &'a [f64], /// Eddington 因子 [nd] pub fak1: &'a [f64], // ALI 导数 /// 源函数 T 导数 [nd] pub dsfdt: &'a [f64], /// 源函数 N 导数 [nd] pub dsfdn: &'a [f64], /// 源函数能级导数 [nlvexp × nd] pub dsfdp: &'a [f64], // ODF/OS 特定 /// J 迭代索引 [nd] pub jidi: &'a [i32], /// XJ 迭代 [nd] pub xjid: &'a [f64], /// Fe 线截面 [njd × nkj] pub sigfe: &'a [f64], // 对流相关 /// 对流能量 [nd] pub reint: &'a [f64], /// 辐射扩散 [nd] pub redif: &'a [f64], /// 质量权重 [nd] pub wmm: &'a [f64], } /// ALIST2 可变状态 pub struct Alist2State<'a> { // 速率数组 [ntrans × nd] /// 向上跃迁率 pub rru: &'a mut [f64], /// 向下跃迁率 pub rrd: &'a mut [f64], /// 速率温度导数 pub drdt: &'a mut [f64], // ALI 参数 [nd] pub reit: &'a mut [f64], pub rein: &'a mut [f64], pub reix: &'a mut [f64], pub areit: &'a mut [f64], pub arein: &'a mut [f64], pub creit: &'a mut [f64], pub crein: &'a mut [f64], pub creix: &'a mut [f64], pub redt: &'a mut [f64], pub redtm: &'a mut [f64], pub redtp: &'a mut [f64], pub redn: &'a mut [f64], pub rednm: &'a mut [f64], pub rednp: &'a mut [f64], pub redx: &'a mut [f64], pub redxm: &'a mut [f64], pub redxp: &'a mut [f64], pub heit: &'a mut [f64], pub heitm: &'a mut [f64], pub heitp: &'a mut [f64], pub hein: &'a mut [f64], pub heinm: &'a mut [f64], pub heinp: &'a mut [f64], pub ehet: &'a mut [f64], pub ehen: &'a mut [f64], pub eret: &'a mut [f64], pub eren: &'a mut [f64], pub fcooli: &'a mut [f64], pub flfix: &'a mut [f64], pub flexp: &'a mut [f64], pub flrd: &'a mut [f64], pub fprd: &'a mut [f64], pub pradt: &'a mut [f64], pub prada: &'a mut [f64], // 能级导数 [nlvexp × nd] pub heip: &'a mut [f64], pub reip: &'a mut [f64], pub areip: &'a mut [f64], pub creip: &'a mut [f64], pub redp: &'a mut [f64], pub redpm: &'a mut [f64], pub heipm: &'a mut [f64], pub redpp: &'a mut [f64], pub heipp: &'a mut [f64], // AP 矩阵 [nlvexp × nd] pub apt: &'a mut [f64], pub apn: &'a mut [f64], // APP 矩阵 [nlvexp × nlvexp × nd] pub app: &'a mut [f64], // Rosseland 相关 [nd] pub abrosd: &'a mut [f64], pub sumdpl: &'a mut [f64], // 辐射压力表面值 pub prd0: &'a mut f64, } /// ALIST2 输出结果 pub struct Alist2Output { /// 辐射压力最小比值 pub prdx: f64, } /// 常量 const PCK: f64 = 1.5e-4; // h/c 常数因子 /// 执行 ALIST2 计算。 /// /// # 参数 /// - `params`: 输入参数 /// - `state`: 可变状态 /// /// # 返回 /// 计算结果 pub fn alist2(params: &Alist2Params, state: &mut Alist2State) -> Alist2Output { let nd = params.nd; let nfreq = params.nfreq; let ntranc = params.ntranc; let ntrans = params.ntrans; let nlvexp = params.nlvexp; // 零初始化所有速率和其他量 zero_rates(state, nd, ntrans, nlvexp); // 计算 dedm1 let dedm1 = params.dm[0] / params.dens[0]; let mut prdx = 1.0; match params.irder { 1 => { // IRDER = 1: 只计算 APT, APN process_irder1(params, state, nd, nfreq, ntranc, nlvexp); } 2 => { // IRDER = 2: 只计算 APP process_irder2(params, state, nd, nfreq, ntranc, nlvexp); } 3 => { // IRDER = 3: 计算所有导数 process_irder3(params, state, nd, nfreq, ntranc, nlvexp); } _ => { panic!("Invalid IRDER - ALIST2: {}", params.irder); } } // 乘以频率无关常数 for id in 0..nd { state.redx[id] *= params.wmm[id] * params.dens1[id] * params.dens1[id]; if id > 0 { state.redxm[id] *= params.wmm[id] * params.dens1[id - 1] * params.dens1[id - 1]; } // 对流冷却 state.flfix[id] = params.reint[id] * state.fcooli[id] - params.redif[id] * state.flfix[id]; // CRSW 缩放 if (params.crsw[id] - UN).abs() > 1e-10 { for itr in 0..ntrans { state.rru[itr * nd + id] *= params.crsw[id]; state.rrd[itr * nd + id] *= params.crsw[id]; state.drdt[itr * nd + id] *= params.crsw[id]; } if params.irder > 0 { for ii in 0..nlvexp { state.apt[ii * nd + id] *= params.crsw[id]; state.apn[ii * nd + id] *= params.crsw[id]; for jj in 0..nlvexp { state.app[(jj * nlvexp + ii) * nd + id] *= params.crsw[id]; } } } } } // 辐射压力 for id in 0..nd { state.pradt[id] *= PCK; state.prada[id] *= PCK; if state.prada[id] > 0.0 { let prdr = state.pradt[id] / state.prada[id]; if prdr < prdx { prdx = prdr; } } } *state.prd0 = *state.prd0 / params.dens1[0] * params.dm[0] * PCK; // Rosseland 平均不透明度 let lross = (params.ioptab < 0 && dedm1 > 0.0) && (params.iter == 1 || params.lfin) || params.hmix0 > 0.0; if lross { for id in 0..nd { state.abrosd[id] = state.sumdpl[id] / (state.abrosd[id] * params.dens[id]); } if params.ioptab < 0 { // rosstd 函数调用 (待实现) // rosstd(0); } } Alist2Output { prdx } } /// 零初始化所有速率数组 fn zero_rates(state: &mut Alist2State, nd: usize, ntrans: usize, nlvexp: usize) { for id in 0..nd { state.reit[id] = 0.0; state.rein[id] = 0.0; state.reix[id] = 0.0; state.areit[id] = 0.0; state.arein[id] = 0.0; state.creit[id] = 0.0; state.crein[id] = 0.0; state.creix[id] = 0.0; state.redt[id] = 0.0; state.redtm[id] = 0.0; state.redtp[id] = 0.0; state.redn[id] = 0.0; state.rednm[id] = 0.0; state.rednp[id] = 0.0; state.redx[id] = 0.0; state.redxm[id] = 0.0; state.redxp[id] = 0.0; state.heit[id] = 0.0; state.heitm[id] = 0.0; state.heitp[id] = 0.0; state.hein[id] = 0.0; state.heinm[id] = 0.0; state.heinp[id] = 0.0; state.ehet[id] = 0.0; state.ehen[id] = 0.0; state.eret[id] = 0.0; state.eren[id] = 0.0; state.fcooli[id] = 0.0; state.flfix[id] = 0.0; state.flexp[id] = 0.0; state.flrd[id] = 0.0; state.fprd[id] = 0.0; state.pradt[id] = 0.0; state.prada[id] = 0.0; for ii in 0..nlvexp { state.heip[ii * nd + id] = 0.0; state.reip[ii * nd + id] = 0.0; state.areip[ii * nd + id] = 0.0; state.creip[ii * nd + id] = 0.0; state.redp[ii * nd + id] = 0.0; state.redpm[ii * nd + id] = 0.0; state.heipm[ii * nd + id] = 0.0; state.redpp[ii * nd + id] = 0.0; state.heipp[ii * nd + id] = 0.0; state.apt[ii * nd + id] = 0.0; state.apn[ii * nd + id] = 0.0; for jj in 0..nlvexp { state.app[(jj * nlvexp + ii) * nd + id] = 0.0; } } for itr in 0..ntrans { state.rru[itr * nd + id] = 0.0; state.rrd[itr * nd + id] = 0.0; state.drdt[itr * nd + id] = 0.0; } } *state.prd0 = 0.0; } /// IRDER = 3 的处理(计算所有导数) fn process_irder3( params: &Alist2Params, state: &mut Alist2State, nd: usize, nfreq: usize, ntranc: usize, nlvexp: usize, ) { let lross = (params.ioptab < 0 && params.dm[0] / params.dens[0] > 0.0) && (params.iter == 1 || params.lfin) || params.hmix0 > 0.0; if lross { for id in 0..nd { state.abrosd[id] = 0.0; state.sumdpl[id] = 0.0; } } // 工作数组 let mut exx = vec![0.0; MDEPTH]; let mut rbnu = vec![0.0; MDEPTH]; let mut rbnuf = vec![0.0; MDEPTH]; for ij in 0..nfreq { if params.ijx[ij] == -1 { continue; } let fr = params.freq[ij]; let w0 = params.w0e[ij]; let lrder = params.ijali[ij] > 0; // 注意:这里需要调用 OPACFD, RTEFR1, ALIFR1 // 由于这些函数有复杂的参数,这里用占位符表示 // call opacfd(ij); // call rtefr1(ij); // call alifr1(ij); // if lross: call rosstd(ij); if params.ioptab < 0 { continue; } // 连续谱跃迁 process_continuum_transitions( params, state, ij, fr, w0, lrder, nd, ntranc, nlvexp, &mut exx, &mut rbnu, &mut rbnuf, true, // compute_apt_apn_app ); // 线跃迁 if params.ispodf == 0 { process_line_transitions_standard( params, state, ij, fr, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, true, // compute_apt_apn_app ); } else { process_line_transitions_odf( params, state, ij, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, true, // compute_apt_apn_app ); } } } /// IRDER = 1 的处理(只计算 APT, APN) fn process_irder1( params: &Alist2Params, state: &mut Alist2State, nd: usize, nfreq: usize, ntranc: usize, nlvexp: usize, ) { let mut exx = vec![0.0; MDEPTH]; let mut rbnu = vec![0.0; MDEPTH]; let mut rbnuf = vec![0.0; MDEPTH]; for ij in 0..nfreq { if params.ijx[ij] == -1 { continue; } let fr = params.freq[ij]; let w0 = params.w0e[ij]; let lrder = params.ijali[ij] > 0; // call opacfd(ij); // call rtefr1(ij); // call alifr1(ij); // 连续谱跃迁 process_continuum_transitions( params, state, ij, fr, w0, lrder, nd, ntranc, nlvexp, &mut exx, &mut rbnu, &mut rbnuf, true, // compute_apt_apn ); // 线跃迁 if params.ispodf == 0 { process_line_transitions_standard( params, state, ij, fr, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, true, // compute_apt_apn ); } else { process_line_transitions_odf( params, state, ij, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, true, // compute_apt_apn ); } } } /// IRDER = 2 的处理(只计算 APP) fn process_irder2( params: &Alist2Params, state: &mut Alist2State, nd: usize, nfreq: usize, ntranc: usize, nlvexp: usize, ) { let mut exx = vec![0.0; MDEPTH]; let mut rbnu = vec![0.0; MDEPTH]; let mut rbnuf = vec![0.0; MDEPTH]; for ij in 0..nfreq { if params.ijx[ij] == -1 { continue; } let fr = params.freq[ij]; let w0 = params.w0e[ij]; let lrder = params.ijali[ij] > 0; // call opacfd(ij); // call rtefr1(ij); // call alifr1(ij); // 连续谱跃迁 process_continuum_transitions( params, state, ij, fr, w0, lrder, nd, ntranc, nlvexp, &mut exx, &mut rbnu, &mut rbnuf, false, // 不计算 apt/apn,只计算 app ); // 线跃迁 if params.ispodf == 0 { process_line_transitions_standard( params, state, ij, fr, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, false, // 不计算 apt/apn,只计算 app ); } else { process_line_transitions_odf( params, state, ij, w0, lrder, nd, nlvexp, &exx, &rbnu, &rbnuf, false, // 不计算 apt/apn,只计算 app ); } } } /// 处理连续谱跃迁 #[allow(clippy::too_many_arguments)] fn process_continuum_transitions( params: &Alist2Params, state: &mut Alist2State, _ij: usize, fr: f64, w0: f64, lrder: bool, nd: usize, ntranc: usize, nlvexp: usize, exx: &mut [f64], rbnu: &mut [f64], rbnuf: &mut [f64], compute_apt_apn: bool, ) { // 计算辅助量 for id in 0..nd { exx[id] = (-params.hkt1[id] * fr).exp(); rbnu[id] = (params.rad1[id] + params.bnue[_ij]) * exx[id]; rbnuf[id] = rbnu[id] * fr * params.hkt21[id]; } // 遍历束缚-自由跃迁 for ibft in 0..ntranc { let itr = (params.itrbf[ibft] - 1) as usize; let ii = (params.ilow[itr] - 1) as usize; let jj = (params.iup[itr] - 1) as usize; for id in 0..nd { // 检查零占据数 if params.ipzero[ii * nd + id] != 0 || params.ipzero[jj * nd + id] != 0 { continue; } // 获取截面 let mut sg = get_cross_section(params, ibft, _ij, nd, id); if sg <= 0.0 { continue; } // 应用 Van der Waals 宽化或合并截面 let icdw = params.mcdw[itr]; let imer = params.imrg[ii]; if params.iifix[ii] >= 0 { if icdw >= 1 { sg *= params.dwf1[icdw as usize * nd + id]; } } else { sg = params.sgmg[imer as usize * nd + id]; } let sgw0 = sg * w0; // 更新跃迁率 state.rru[itr * nd + id] += sgw0 * params.rad1[id]; state.rrd[itr * nd + id] += sgw0 * rbnu[id]; state.drdt[itr * nd + id] += sgw0 * rbnuf[id]; if lrder { let apfr = (params.abtra[itr * nd + id] - params.emtra[itr * nd + id] * exx[id]) * sgw0; let ie = (params.iiexp[ii].abs()) as usize; let je = (params.iiexp[jj].abs()) as usize; let nrefi = params.nrefs[params.iatm[ii] as usize * nd + id] as usize; // 更新 AP 矩阵 update_ap_matrices( state, id, ie, je, ii, jj, nrefi, apfr, nd, nlvexp, params.dsfdt, params.dsfdn, params.dsfdp, compute_apt_apn, ); } } } } /// 获取截面(占位符) fn get_cross_section(_params: &Alist2Params, _ibft: usize, _ij: usize, _nd: usize, _id: usize) -> f64 { // 实际实现需要从 params.cross 数组读取 0.0 } /// 更新 AP 矩阵 #[allow(clippy::too_many_arguments)] fn update_ap_matrices( state: &mut Alist2State, id: usize, ie: usize, je: usize, ii: usize, jj: usize, nrefi: usize, apfr: f64, nd: usize, nlvexp: usize, dsfdt: &[f64], dsfdn: &[f64], dsfdp: &[f64], compute_apt_apn: bool, ) { // 下能级贡献 if ie > 0 && ii != nrefi { // 注意:需要检查 iltlev[ii] <= 0 if compute_apt_apn { state.apt[ie * nd + id] += apfr * dsfdt[id]; state.apn[ie * nd + id] += apfr * dsfdn[id]; } for kk in 0..nlvexp { state.app[(kk * nlvexp + ie) * nd + id] += apfr * dsfdp[kk * nd + id]; } } // 上能级贡献 if je > 0 && jj != nrefi { // 注意:需要检查 iltlev[jj] <= 0 && imodl[ii] != ±4 if compute_apt_apn { state.apt[je * nd + id] -= apfr * dsfdt[id]; state.apn[je * nd + id] -= apfr * dsfdn[id]; } for kk in 0..nlvexp { state.app[(kk * nlvexp + je) * nd + id] -= apfr * dsfdp[kk * nd + id]; } } } /// 处理标准线跃迁(非 ODF) #[allow(clippy::too_many_arguments)] fn process_line_transitions_standard( params: &Alist2Params, state: &mut Alist2State, ij: usize, fr: f64, w0: f64, lrder: bool, nd: usize, nlvexp: usize, exx: &[f64], rbnu: &[f64], rbnuf: &[f64], compute_apt_apn: bool, ) { // 主线 if params.ijlin[ij] > 0 { let itr = (params.ijlin[ij] - 1) as usize; let ii = (params.ilow[itr] - 1) as usize; let jj = (params.iup[itr] - 1) as usize; let ie = (params.iiexp[ii].abs()) as usize; let je = (params.iiexp[jj].abs()) as usize; for id in 0..nd { if params.ipzero[ii * nd + id] != 0 || params.ipzero[jj * nd + id] != 0 { continue; } // 获取线轮廓 let sgw0 = params.prflin[id * params.nfreq + ij] * w0; // 更新跃迁率 state.rru[itr * nd + id] += sgw0 * params.rad1[id]; state.rrd[itr * nd + id] += sgw0 * rbnu[id]; state.drdt[itr * nd + id] += sgw0 * rbnuf[id]; if lrder { let apfr = (params.abtra[itr * nd + id] - params.emtra[itr * nd + id] * exx[id]) * sgw0; let nrefi = params.nrefs[params.iatm[ii] as usize * nd + id] as usize; update_ap_matrices( state, id, ie, je, ii, jj, nrefi, apfr, nd, nlvexp, params.dsfdt, params.dsfdn, params.dsfdp, compute_apt_apn, ); } } } // 重叠线 if params.nlines[ij] <= 0 { return; } for ilint in 0..params.nlines[ij] as usize { let itr = (params.itrlin[ij * 100 + ilint] - 1) as usize; // 假设最大 100 条重叠线 if params.linexp[itr] { continue; } let ii = (params.ilow[itr] - 1) as usize; let jj = (params.iup[itr] - 1) as usize; let ie = (params.iiexp[ii].abs()) as usize; let je = (params.iiexp[jj].abs()) as usize; // 频率插值 let ij0 = (params.ifr0[itr] - 1) as usize; let ij1 = if ij0 > 0 { ij0 - 1 } else { 0 }; let a1 = if ij1 != ij0 { (fr - params.freq[ij0]) / (params.freq[ij1] - params.freq[ij0]) * w0 } else { 0.0 }; let a2 = w0 - a1; for id in 0..nd { if params.ipzero[ii * nd + id] != 0 || params.ipzero[jj * nd + id] != 0 { continue; } let sgw0 = a1 * params.prflin[id * params.nfreq + ij1] + a2 * params.prflin[id * params.nfreq + ij0]; state.rru[itr * nd + id] += sgw0 * params.rad1[id]; state.rrd[itr * nd + id] += sgw0 * rbnu[id]; state.drdt[itr * nd + id] += sgw0 * rbnuf[id]; if lrder { let apfr = (params.abtra[itr * nd + id] - params.emtra[itr * nd + id] * exx[id]) * sgw0; let nrefi = params.nrefs[params.iatm[ii] as usize * nd + id] as usize; update_ap_matrices( state, id, ie, je, ii, jj, nrefi, apfr, nd, nlvexp, params.dsfdt, params.dsfdn, params.dsfdp, compute_apt_apn, ); } } } } /// 处理 ODF 线跃迁 #[allow(clippy::too_many_arguments)] fn process_line_transitions_odf( params: &Alist2Params, state: &mut Alist2State, ij: usize, w0: f64, lrder: bool, nd: usize, nlvexp: usize, exx: &[f64], rbnu: &[f64], rbnuf: &[f64], compute_apt_apn: bool, ) { if params.nlines[ij] <= 0 { return; } for ilint in 0..params.nlines[ij] as usize { let itr = (params.itrlin[ij * 100 + ilint] - 1) as usize; let ii = (params.ilow[itr] - 1) as usize; let jj = (params.iup[itr] - 1) as usize; let ie = (params.iiexp[ii].abs()) as usize; let je = (params.iiexp[jj].abs()) as usize; let kj = ij - (params.ifr0[itr] - 1) as usize + (params.kfr0[itr] - 1) as usize; let indxpa = (params.indexp[itr].abs()) as i32; for id in 0..nd { if params.ipzero[ii * nd + id] != 0 || params.ipzero[jj * nd + id] != 0 { continue; } let sgw0 = if indxpa != 3 && indxpa != 4 { // 标准 ODF params.prflin[id * params.nfreq + kj] * w0 } else { // Fe 线特殊处理 let kjd = (params.jidi[id] - 1) as usize; let sg = (params.xjid[id] * params.sigfe[kjd * 1000 + kj] + (UN - params.xjid[id]) * params.sigfe[(kjd + 1) * 1000 + kj]).exp(); sg * w0 }; state.rru[itr * nd + id] += sgw0 * params.rad1[id]; state.rrd[itr * nd + id] += sgw0 * rbnu[id]; state.drdt[itr * nd + id] += sgw0 * rbnuf[id]; if lrder { let apfr = (params.abtra[itr * nd + id] - params.emtra[itr * nd + id] * exx[id]) * sgw0; let nrefi = params.nrefs[params.iatm[ii] as usize * nd + id] as usize; update_ap_matrices( state, id, ie, je, ii, jj, nrefi, apfr, nd, nlvexp, params.dsfdt, params.dsfdn, params.dsfdp, compute_apt_apn, ); } } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_alist2_zero_rates() { let nd = 5; let ntrans = 10; let nlvexp = 3; let mut reit = vec![0.0; MDEPTH]; let mut rru = vec![0.0; MTRANS * MDEPTH]; let mut apt = vec![0.0; MLVEXP * MDEPTH]; let mut state = Alist2State { reit: &mut reit, rein: &mut vec![0.0; MDEPTH], reix: &mut vec![0.0; MDEPTH], areit: &mut vec![0.0; MDEPTH], arein: &mut vec![0.0; MDEPTH], creit: &mut vec![0.0; MDEPTH], crein: &mut vec![0.0; MDEPTH], creix: &mut vec![0.0; MDEPTH], redt: &mut vec![0.0; MDEPTH], redtm: &mut vec![0.0; MDEPTH], redtp: &mut vec![0.0; MDEPTH], redn: &mut vec![0.0; MDEPTH], rednm: &mut vec![0.0; MDEPTH], rednp: &mut vec![0.0; MDEPTH], redx: &mut vec![0.0; MDEPTH], redxm: &mut vec![0.0; MDEPTH], redxp: &mut vec![0.0; MDEPTH], heit: &mut vec![0.0; MDEPTH], heitm: &mut vec![0.0; MDEPTH], heitp: &mut vec![0.0; MDEPTH], hein: &mut vec![0.0; MDEPTH], heinm: &mut vec![0.0; MDEPTH], heinp: &mut vec![0.0; MDEPTH], ehet: &mut vec![0.0; MDEPTH], ehen: &mut vec![0.0; MDEPTH], eret: &mut vec![0.0; MDEPTH], eren: &mut vec![0.0; MDEPTH], fcooli: &mut vec![0.0; MDEPTH], flfix: &mut vec![0.0; MDEPTH], flexp: &mut vec![0.0; MDEPTH], flrd: &mut vec![0.0; MDEPTH], fprd: &mut vec![0.0; MDEPTH], pradt: &mut vec![0.0; MDEPTH], prada: &mut vec![0.0; MDEPTH], heip: &mut vec![0.0; MLVEXP * MDEPTH], reip: &mut vec![0.0; MLVEXP * MDEPTH], areip: &mut vec![0.0; MLVEXP * MDEPTH], creip: &mut vec![0.0; MLVEXP * MDEPTH], redp: &mut vec![0.0; MLVEXP * MDEPTH], redpm: &mut vec![0.0; MLVEXP * MDEPTH], heipm: &mut vec![0.0; MLVEXP * MDEPTH], redpp: &mut vec![0.0; MLVEXP * MDEPTH], heipp: &mut vec![0.0; MLVEXP * MDEPTH], apt: &mut apt, apn: &mut vec![0.0; MLVEXP * MDEPTH], app: &mut vec![0.0; MLVEXP * MLVEXP * MDEPTH], abrosd: &mut vec![0.0; MDEPTH], sumdpl: &mut vec![0.0; MDEPTH], rru: &mut rru, rrd: &mut vec![0.0; MTRANS * MDEPTH], drdt: &mut vec![0.0; MTRANS * MDEPTH], prd0: &mut 0.0, }; // 初始化一些非零值 state.reit[0] = 1.0; state.rru[0] = 1.0; zero_rates(&mut state, nd, ntrans, nlvexp); // 验证所有值都被清零 for id in 0..nd { assert_eq!(state.reit[id], 0.0); } for itr in 0..ntrans { for id in 0..nd { assert_eq!(state.rru[itr * nd + id], 0.0); } } } }