//! 吸收和发射系数及其导数的计算。 //! //! 重构自 TLUSTY `opacfd.f` //! //! 这个过程与 OPACF1 非常相似,唯一的区别是导数的计算。 //! //! ## 输入 //! - `ij` - 深度索引 //! //! ## 输出 //! - `abso1` - 吸收系数数组 //! - `emis1` - 发射系数数组 //! - `scat1` - 散射系数数组 //! - `dabt1`, `demt1` - 温度导数 //! - `dabn1`, `demn1` - 电子密度导数 //! - `dabp1`, `demp1` - 能级导数 //! - `absff` - 自由-自由吸收 //! - `dabft`, `dabfn` - 自由-自由导数 //! - `absot` - 存储的不透明度 use crate::tlusty::state::constants::{MDEPTH, MFREQ, MLEVEL}; // 导入依赖模块函数(通过 pub use 导出) // 注意:这些函数需要特定的参数结构体,这里只添加导入以供将来完整实现 #[allow(unused_imports)] use crate::tlusty::math::continuum::{opactd, opctab, opadd}; #[allow(unused_imports)] use crate::tlusty::math::hydrogen::lymlin; #[allow(unused_imports)] use crate::tlusty::math::opacity::{prd, quasim}; #[allow(unused_imports)] use crate::tlusty::math::atomic::{gfreed, gfree1}; // 常量 const C14: f64 = 2.99793e14; #[allow(dead_code)] const CFF1: f64 = 1.3727e-25; const DELT: f64 = 1e-3; const DELR: f64 = 1e-3; /// OPACFD 输入参数 pub struct OpacfdParams<'a> { /// 频率索引 (1-indexed) pub ij: usize, // 模型参数 /// 深度点数 pub nd: usize, /// 能级数 pub nlevel: usize, /// 离子数 pub nion: usize, /// 跃迁数 (束缚-自由) pub ntranc: usize, // 频率相关 /// 频率数组 (MFREQ) pub freq: &'a [f64], /// 普朗克函数 B_nu (MFREQ) pub bnue: &'a [f64], // 模型状态 /// 温度 (MDEPTH) pub temp: &'a [f64], /// 电子密度 (MDEPTH) pub elec: &'a [f64], /// 1/电子密度 (MDEPTH) pub elec1: &'a [f64], /// 总粒子密度 (MDEPTH) pub dens: &'a [f64], /// h/kT (MDEPTH) pub hkt1: &'a [f64], /// h/(kT)^2 (MDEPTH) pub hkt21: &'a [f64], /// 1/T (MDEPTH) pub temp1: &'a [f64], // 电子散射截面 /// 电子散射截面 (MFREQ) pub sigec: &'a [f64], // 原子数据 /// 元素索引 (MLEVEL) pub iel: &'a [i32], /// 元素电荷 (MELEM) pub iz: &'a [i32], /// 电荷 (MION) pub charg2: &'a [f64], /// 下一能级索引 (MION) pub nnext: &'a [i32], /// 跃迁类型 (MLEVEL) pub itra: &'a [i32], // 跃迁数据 /// 束缚-自由跃迁索引 (MTRANC) pub itrbf: &'a [i32], /// 跃迁下能级 (MTRANS) pub ilow: &'a [i32], /// 跃迁上能级 (MTRANS) pub iup: &'a [i32], /// 跃迁阈值频率 (MTRANS) pub fr0: &'a [f64], /// 截面 (MTRANC × MFREQ) pub cross: &'a [f64], /// 截面 (带介电复合, MTRANC × MFREQ × MDEPTH) pub crossd: &'a [f64], // 跃迁吸收和发射 /// 跃迁吸收 (MTRANS × MDEPTH) pub abtra: &'a [f64], /// 跃迁发射 (MTRANS × MDEPTH) pub emtra: &'a [f64], /// 跃迁发射温度导数 (MTRANS × MDEPTH) pub demlt: &'a [f64], // 能级占据数 /// 能级占据数 (MLEVEL × MDEPTH) pub popul: &'a [f64], /// 逆占据数 (MLEVEL × MDEPTH) pub popinv: &'a [f64], // 控制标志 /// 介电复合标志 pub ifdiel: i32, /// 附加不透明度标志 pub iopadd: i32, /// Lyman 线不透明度标志 pub ioplym: i32, /// PRD 标志 pub ifprd: i32, /// 迭代次数 pub iter: i32, /// Lyman 线迭代 pub itlas: i32, /// ODF/OS 选项 pub ispodf: i32, /// 不透明度表选项 pub ioptab: i32, /// 频率表上限 pub frtabm: f64, /// 原子选项 pub iatm: &'a [i32], /// 固定原子标志 pub iifix: &'a [i32], /// 零占据数标志 (MLEVEL × MDEPTH) pub ipzero: &'a [i32], // 自由-自由相关 /// SFF3 (MION × MDEPTH) pub sff3: &'a [f64], /// SFF2 (MION × MDEPTH) pub sff2: &'a [f64], /// DSFF (MION × MDEPTH) pub dsff: &'a [f64], /// FF 频率阈值 (MION) pub ff: &'a [f64], // 能级相关 /// 第一个能级索引 (MELEM) pub nfirst: &'a [i32], /// 氢元素索引 pub ielh: usize, // 线相关 /// 主线索引 (MFREQ) pub ijlin: &'a [i32], /// 重叠线数 (MFREQ) pub nlines: &'a [i32], /// 线跃迁索引 (MLINES × MFREQ) pub itrlin: &'a [i32], /// 线轮廓 (MDEPTH × MFREQ) pub prflin: &'a [f64], /// 线频率范围 (MTRANS) pub ifr0: &'a [i32], pub ifr1: &'a [i32], pub kfr0: &'a [i32], /// 线展开标志 (MTRANS) pub linexp: &'a [bool], /// 线指数 (MTRANS) pub indexp: &'a [i32], // ALI 相关 /// 合并能级 (MLEVEL) pub imrg: &'a [i32], /// 截面修改标志 (MLEVEL) pub ifwop: &'a [i32], /// 下降频率修改 (MTRANS) pub mcdw: &'a [i32], // 显式能级 /// 显式能级数 pub nlvexp: usize, /// 显式能级映射 (MLEVEL) pub iiexp: &'a [i32], /// 参考能级 (MLEVEL × MDEPTH) pub iltref: &'a [i32], /// 能级模式 (MLEVEL) pub imodl: &'a [i32], /// 能级导数 PT, PN (MLEVEL × MDEPTH) pub pt: &'a [f64], pub pn: &'a [f64], /// 能级导数 PP (MLEVEL × MDEPTH) pub pp: &'a [f64], // 密度相关 /// 氦模式 pub inhe: i32, /// 密度导数 d rho / d T (MDEPTH) pub drhodt: &'a [f64], // 其他选项 /// 标度不透明度标志 pub izscal: i32, /// Rybicki 标志 pub ifryb: i32, // 显式频率 /// 显式频率索引 (MFREQ) pub ijex: &'a [i32], // 原子选项表 pub iadop: &'a [i32], // Fe 线采样相关 /// JIDI, JID (MDEPTH) pub jidi: &'a [i32], pub xjid: &'a [f64], /// SIGFE (MFREQ × MFREQ) pub sigfe: &'a [f64], // dwnfr1/sgmer1 所需参数 /// 输入参数配置 pub inppar: &'a crate::tlusty::state::config::InpPar, /// 下降频率修改参数 pub dwnpar: &'a crate::tlusty::state::model::DwnPar, /// 合并能级参数 pub mrgpar: &'a crate::tlusty::state::model::MrgPar, } /// OPACFD 可变状态 pub struct OpacfdState<'a> { // 输出数组 (MDEPTH) pub abso1: &'a mut [f64], pub emis1: &'a mut [f64], pub scat1: &'a mut [f64], pub dabt1: &'a mut [f64], pub demt1: &'a mut [f64], pub dabn1: &'a mut [f64], pub demn1: &'a mut [f64], pub dabm1: &'a mut [f64], pub demm1: &'a mut [f64], // 自由-自由输出 (MDEPTH) pub absff: &'a mut [f64], pub dabft: &'a mut [f64], pub dabfn: &'a mut [f64], // 能级导数 (MLEVEL × MDEPTH) pub dabp1: &'a mut [f64], pub demp1: &'a mut [f64], // 电子散射 (MDEPTH) pub elscat: &'a mut [f64], // 中间量 (MDEPTH) pub xkf: &'a mut [f64], pub xkf1: &'a mut [f64], pub xkfb: &'a mut [f64], // 下降频率修改 (MTRANS × MDEPTH) pub dwf1: &'a mut [f64], // 合并截面 (MLEVEL × MDEPTH) pub sgmg: &'a mut [f64], // 存储的不透明度 (MDEPTH) pub absot: &'a mut [f64], // 显式频率存储 pub absoex: &'a mut [f64], pub emisex: &'a mut [f64], pub scatex: &'a mut [f64], pub dabtex: &'a mut [f64], pub demtex: &'a mut [f64], pub dabnex: &'a mut [f64], pub demnex: &'a mut [f64], pub dabmex: &'a mut [f64], pub demmex: &'a mut [f64], pub drchex: &'a mut [f64], pub dretex: &'a mut [f64], // 散射导数 pub dsct1: &'a mut [f64], pub dscn1: &'a mut [f64], // H2 分子 pub anh2: &'a mut [f64], pub anhm: &'a mut [f64], } /// OPACFD 输出(用于无状态版本) #[derive(Debug, Clone)] pub struct OpacfdOutput { /// 吸收系数 (MDEPTH) pub abso1: Vec, /// 发射系数 (MDEPTH) pub emis1: Vec, /// 散射系数 (MDEPTH) pub scat1: Vec, /// 吸收温度导数 (MDEPTH) pub dabt1: Vec, /// 发射温度导数 (MDEPTH) pub demt1: Vec, /// 吸收电子密度导数 (MDEPTH) pub dabn1: Vec, /// 发射电子密度导数 (MDEPTH) pub demn1: Vec, /// 存储的不透明度 (MDEPTH) pub absot: Vec, } impl Default for OpacfdOutput { fn default() -> Self { Self { abso1: vec![0.0; MDEPTH], emis1: vec![0.0; MDEPTH], scat1: vec![0.0; MDEPTH], dabt1: vec![0.0; MDEPTH], demt1: vec![0.0; MDEPTH], dabn1: vec![0.0; MDEPTH], demn1: vec![0.0; MDEPTH], absot: vec![0.0; MDEPTH], } } } /// 计算吸收和发射系数及其导数。 /// /// 这是一个非常复杂的函数,计算: /// 1. 束缚-自由贡献(带或不带介电复合) /// 2. 自由-自由贡献 /// 3. 附加不透明度 (OPADD) /// 4. 线不透明度 /// 5. Lyman α/β 准分子不透明度 /// 6. 背景不透明度表 /// /// # 参数 /// /// * `params` - 输入参数 /// * `state` - 可变状态 /// /// # 注意 /// /// 这个函数修改大量的状态变量,是 TLUSTY 的核心计算之一。 pub fn opacfd(params: &OpacfdParams, state: &mut OpacfdState) { let ij = params.ij; let nd = params.nd; let nlevel = params.nlevel; // 检查是否使用不透明度表 if params.ioptab < 0 { // 调用 opactd - 需要完整参数结构体 // opactd(&opactd_params, &mut opactd_model, &mut opactd_output, None, &opctab_table, &mut opctab_model); let _ = opactd; // 标记函数已导入 return; } // 初始化 for id in 0..nd { state.elscat[id] = params.elec[id] * params.sigec[ij - 1]; } for id in 0..nd { state.abso1[id] = 0.0; state.emis1[id] = 0.0; state.scat1[id] = state.elscat[id]; state.dabt1[id] = 0.0; state.demt1[id] = 0.0; state.dabn1[id] = params.sigec[ij - 1]; state.demn1[id] = 0.0; state.absff[id] = 0.0; state.dabft[id] = 0.0; state.dabfn[id] = 0.0; for ii in 0..nlevel { let idx = ii * MDEPTH + id; state.dabp1[idx] = 0.0; state.demp1[idx] = 0.0; } } // 基本频率和深度相关量 let fr = params.freq[ij - 1]; let lfre = fr > params.frtabm; let frinv = 1.0 / fr; let fr3inv = frinv * frinv * frinv; for id in 0..nd { state.xkf[id] = (-params.hkt1[id] * fr).exp(); state.xkf1[id] = 1.0 - state.xkf[id]; state.xkfb[id] = state.xkf[id] * params.bnue[ij - 1]; } // 1a. 束缚-自由贡献 - 不带介电复合 if params.ifdiel == 0 { compute_bf_no_diel(params, state, fr, frinv, fr3inv, lfre); } else { // 1b. 束缚-自由贡献 - 带介电复合 compute_bf_with_diel(params, state, fr, frinv, fr3inv, lfre); } // 2. 自由-自由贡献 compute_ff(params, state, fr, frinv, fr3inv, lfre); // 3. 附加不透明度 (OPADD) if params.iopadd != 0 { // 调用 opadd - 需要完整参数结构体 // for id in 0..nd { // let opadd_input = OpaddInput { mode: 0, icall: 1, ij: ij - 1, id }; // let opadd_output = opadd(&opadd_input, &opadd_switches, &opadd_model, &mut opadd_cache); // state.abso1[id] += opadd_output.abad; // state.emis1[id] += opadd_output.emad; // state.scat1[id] += opadd_output.scad; // } let _ = opadd; // 标记函数已导入 } // 总连续不透明度 for id in 0..nd { state.abso1[id] += state.absff[id]; state.dabt1[id] += state.dabft[id]; state.dabn1[id] += state.dabfn[id]; state.emis1[id] += state.absff[id]; state.demt1[id] += state.dabft[id]; state.demn1[id] += state.dabfn[id]; } // 4. 线不透明度 let laser = params.iter > params.itlas; if params.ispodf == 0 { compute_lines_standard(params, state, fr, laser, lfre); } else { compute_lines_sampling(params, state, fr, laser, lfre); } // Lyman α/β 准分子不透明度 // 调用 quasim - 需要完整参数结构体 // let quasim_result = quasim(ij, &model, &atomic, &basnum, &freq); // for id in 0..nd { // state.abso1[id] += quasim_result.sgd[id]; // } let _ = quasim; // 标记函数已导入 // 总不透明度、发射率和导数 for id in 0..nd { state.demt1[id] += state.emis1[id] * fr * params.hkt21[id]; state.abso1[id] = state.abso1[id] - state.emis1[id] * state.xkf[id] + state.scat1[id]; state.dabn1[id] -= state.demn1[id] * state.xkf[id]; state.dabt1[id] -= state.demt1[id] * state.xkf[id]; state.emis1[id] *= state.xkfb[id]; state.demn1[id] *= state.xkfb[id]; state.demt1[id] *= state.xkfb[id]; for ii in 0..nlevel { let idx = ii * MDEPTH + id; state.dabp1[idx] -= state.demp1[idx] * state.xkf[id]; state.demp1[idx] *= state.xkfb[id]; } state.absot[id] = state.abso1[id]; } // Lyman 线 if params.ioplym > 0 { // 调用 lymlin - 需要完整参数结构体 // lymlin(&mut lymlin_params, &mut lymlin_cache); let _ = lymlin; // 标记函数已导入 } // PRD if params.ifprd > 0 { // 调用 prd - 需要完整参数结构体 // prd(&prd_params, &prd_config, &prd_atomic, &mut prd_model, &prd_freq_data); let _ = prd; // 标记函数已导入 } // 显式能级导数 if params.nlvexp < nlevel { compute_explicit_level_derivatives(params, state); } // 背景不透明度表 if params.ioptab > 0 { compute_background_opacity(params, state, fr); } // 每克不透明度 if params.izscal == 0 { for id in 0..nd { state.absot[id] = state.abso1[id] / params.dens[id]; } } // 存储显式频率量 if params.ijex[ij - 1] > 0 { store_explicit_frequency(params, state); } } /// 计算束缚-自由贡献(不带介电复合) fn compute_bf_no_diel( params: &OpacfdParams, state: &mut OpacfdState, fr: f64, frinv: f64, fr3inv: f64, lfre: bool, ) { let nd = params.nd; for ibft in 0..params.ntranc { let itr = params.itrbf[ibft] as usize; let ii = params.ilow[itr - 1] as usize; let iad = params.iadop[params.iatm[ii - 1] as usize]; let lcomop = iad == 0 || (lfre && iad > 0); // 获取截面 let sg = params.cross[ibft * MFREQ + (params.ij - 1)]; if sg > 0.0 && lcomop { let jj = params.iup[itr - 1] as usize; let izz = params.iz[params.iel[ii - 1] as usize]; let imer = params.imrg[ii - 1] as usize; for id in 0..nd { let mut sgd = sg; // 下降频率修改 if params.mcdw[itr - 1] > 0 { let dw1 = crate::tlusty::math::dwnfr1( fr, params.fr0[itr - 1], id, (izz - 1) as usize, params.inppar, params.dwnpar, ); sgd = sg * dw1; } // 合并截面 if params.ifwop[ii - 1] < 0 { let sgme1 = crate::tlusty::math::sgmer1( frinv, fr3inv, imer as i32, id + 1, params.mrgpar, ); sgd = sgme1; } let emisbf = sgd * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgd * params.abtra[(itr - 1) * MDEPTH + id]; state.emis1[id] += emisbf; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += emisbf * params.demlt[(itr - 1) * MDEPTH + id]; state.demn1[id] += emisbf * params.elec1[id]; let jj_idx = (jj - 1) * MDEPTH + id; state.demp1[jj_idx] += emisbf * params.popinv[jj_idx]; if params.ipzero[(ii - 1) * MDEPTH + id] == 0 { let ii_idx = (ii - 1) * MDEPTH + id; state.dabp1[ii_idx] += sgd; } } } } } } /// 计算束缚-自由贡献(带介电复合) fn compute_bf_with_diel( params: &OpacfdParams, state: &mut OpacfdState, fr: f64, frinv: f64, fr3inv: f64, lfre: bool, ) { let nd = params.nd; for ibft in 0..params.ntranc { let itr = params.itrbf[ibft] as usize; let ii = params.ilow[itr - 1] as usize; let sg = params.cross[ibft * MFREQ + (params.ij - 1)]; let iad = params.iadop[params.iatm[ii - 1] as usize]; let lcomop = iad == 0 || (lfre && iad > 0); if sg > 0.0 && lcomop { let jj = params.iup[itr - 1] as usize; let izz = params.iz[params.iel[ii - 1] as usize]; let imer = params.imrg[ii - 1] as usize; for id in 0..nd { // 使用 crossd 而不是 cross let sg = params.crossd[ibft * MFREQ * MDEPTH + (params.ij - 1) * MDEPTH + id]; if sg > 0.0 { let mut sgd = sg; if params.mcdw[itr - 1] > 0 { let dw1 = crate::tlusty::math::dwnfr1( fr, params.fr0[itr - 1], id, (izz - 1) as usize, params.inppar, params.dwnpar, ); sgd = sg * dw1; } if params.ifwop[ii - 1] < 0 { let sgme1 = crate::tlusty::math::sgmer1( frinv, fr3inv, imer as i32, id + 1, params.mrgpar, ); sgd = sgme1; } let emisbf = sgd * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgd * params.abtra[(itr - 1) * MDEPTH + id]; state.emis1[id] += emisbf; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += emisbf * params.demlt[(itr - 1) * MDEPTH + id]; state.demn1[id] += emisbf * params.elec1[id]; let jj_idx = (jj - 1) * MDEPTH + id; state.demp1[jj_idx] += emisbf * params.popinv[jj_idx]; if params.ipzero[(ii - 1) * MDEPTH + id] == 0 { let ii_idx = (ii - 1) * MDEPTH + id; state.dabp1[ii_idx] += sgd; } } } } } } } /// 计算自由-自由贡献 fn compute_ff( params: &OpacfdParams, state: &mut OpacfdState, fr: f64, _frinv: f64, fr3inv: f64, lfre: bool, ) { let nd = params.nd; for ion in 0..params.nion { let ii = params.nnext[ion] as usize; let it = params.itra[(ii - 1) * MLEVEL + (ii - 1)]; let iad = params.iadop[params.iatm[ii - 1] as usize]; if iad > 0 && !lfre { continue; } // 氢类离子 (Gaunt 因子 = 1 当 IT=1; 精确当 IT=2) if it <= 2 { for id in 0..nd { let sf1 = params.sff3[ion * MDEPTH + id] * fr3inv; let mut sf2 = params.sff2[ion * MDEPTH + id]; let mut dsf2 = params.dsff[ion * MDEPTH + id]; if fr < params.ff[ion] { sf2 = 1.0 / state.xkf[id]; dsf2 = (params.hkt1[id] * fr + 0.5) * params.temp1[id]; } if it == 2 { let x = C14 * params.charg2[ion] / fr; // 调用 gfree1 - 需要 GffPar 结构体 // let gfr_val = gfree1(id, x, &gffpar); // sf2 = sf2 - 1.0 + gfr_val; let _ = (x, gfree1); // 标记函数已导入 } else if it == 3 { // 调用 gfreed - 需要 GffPar 结构体 // let (gfr, dgfr) = gfreed(id, fr, charg2[ion], &gffpar); // sf2 = sf2 - 1.0 + gfr; // dsf2 = dsf2 - (dgfr - (gfr - 1.0) * temp1[id] * 0.5) / sf2; let _ = gfreed; // 标记函数已导入 } let absoff = sf1 * sf2; state.absff[id] += absoff; if params.iifix[params.iatm[ii - 1] as usize] == 0 { state.dabft[id] -= absoff * dsf2; state.dabfn[id] += absoff * params.elec1[id]; let dabpp = absoff * params.popinv[(ii - 1) * MDEPTH + id]; state.dabp1[(ii - 1) * MDEPTH + id] += dabpp; state.demp1[(ii - 1) * MDEPTH + id] += dabpp; } } } // H- 自由-自由不透明度 else if it == 3 { for id in 0..nd { // H- 自由-自由不透明度 let nfirst_ielh = params.nfirst[params.ielh] as usize; let popi = if nfirst_ielh > 0 && nfirst_ielh <= params.nlevel { params.popul[(nfirst_ielh - 1) * MDEPTH + id] } else { 0.0 }; let absoff = crate::tlusty::math::sffhmi(popi, fr, params.temp[id]) * params.elec[id]; state.absff[id] += absoff; } } // 特殊截面计算 else if it < 0 { for id in 0..nd { // 自由-自由特殊截面 (如 C, N, O 等) let ion_idx = ion - 1; let nnext_ion = params.nnext[ion_idx] as usize; let pop_ion = if nnext_ion > 0 && nnext_ion <= params.nlevel { params.popul[(nnext_ion - 1) * MDEPTH + id] } else { 0.0 }; let absoff = crate::tlusty::math::ffcros(ion as i32, it, params.temp[id], fr) * pop_ion * params.elec[id]; state.absff[id] += absoff; } } } } /// 计算线不透明度(标准模式) fn compute_lines_standard( params: &OpacfdParams, state: &mut OpacfdState, fr: f64, laser: bool, lfre: bool, ) { let nd = params.nd; // 主线 if params.ijlin[params.ij - 1] > 0 { let itr = params.ijlin[params.ij - 1] as usize; let ii = params.ilow[itr - 1] as usize; let iad = params.iadop[params.iatm[ii - 1] as usize]; if iad == 0 || (lfre && iad > 0) { let jj = params.iup[itr - 1] as usize; for id in 0..nd { let sg = params.prflin[id * MFREQ + (params.ij - 1)]; let sgpi = sg * params.abtra[(itr - 1) * MDEPTH + id]; if sgpi > 0.0 || !laser { let sgpj = sg * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgpi; state.emis1[id] += sgpj; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += sgpj * params.demlt[(itr - 1) * MDEPTH + id]; state.dabp1[(ii - 1) * MDEPTH + id] += sgpi * params.popinv[(ii - 1) * MDEPTH + id]; state.demp1[(jj - 1) * MDEPTH + id] += sgpj * params.popinv[(jj - 1) * MDEPTH + id]; } } } } } if params.nlines[params.ij - 1] <= 0 { return; } // 重叠线 for ilint in 0..params.nlines[params.ij - 1] as usize { let itr = params.itrlin[ilint * MFREQ + (params.ij - 1)] as usize; if params.linexp[itr - 1] { continue; } let ii = params.ilow[itr - 1] as usize; let jj = params.iup[itr - 1] as usize; let mut ij0 = params.ifr0[itr - 1] as usize; let iad = params.iadop[params.iatm[ii - 1] as usize]; if iad > 0 && !lfre { continue; } // 找到频率位置 for ijt in (0..ij0).rev() { if params.freq[ijt] <= fr { ij0 = ijt; break; } } let ij1 = ij0 - 1; let a1 = (fr - params.freq[ij0]) / (params.freq[ij1] - params.freq[ij0]); let a2 = 1.0 - a1; for id in 0..nd { let sg = a1 * params.prflin[id * MFREQ + ij1] + a2 * params.prflin[id * MFREQ + ij0]; let sgpi = sg * params.abtra[(itr - 1) * MDEPTH + id]; if sgpi > 0.0 || !laser { let sgpj = sg * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgpi; state.emis1[id] += sgpj; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += sgpj * params.demlt[(itr - 1) * MDEPTH + id]; state.dabp1[(ii - 1) * MDEPTH + id] += sgpi * params.popinv[(ii - 1) * MDEPTH + id]; state.demp1[(jj - 1) * MDEPTH + id] += sgpj * params.popinv[(jj - 1) * MDEPTH + id]; } } } } } /// 计算线不透明度(采样模式) fn compute_lines_sampling( params: &OpacfdParams, state: &mut OpacfdState, _fr: f64, laser: bool, lfre: bool, ) { let nd = params.nd; if params.nlines[params.ij - 1] <= 0 { return; } for ilint in 0..params.nlines[params.ij - 1] as usize { let itr = params.itrlin[ilint * MFREQ + (params.ij - 1)] as usize; let ii = params.ilow[itr - 1] as usize; let jj = params.iup[itr - 1] as usize; let iad = params.iadop[params.iatm[ii - 1] as usize]; if iad > 0 && !lfre { continue; } let kj = params.ij - params.ifr0[itr - 1] as usize + params.kfr0[itr - 1] as usize; let indxpa = (params.indexp[itr - 1]).abs(); if indxpa != 3 && indxpa != 4 { for id in 0..nd { let sgpi = params.prflin[id * MFREQ + kj] * params.abtra[(itr - 1) * MDEPTH + id]; if sgpi > 0.0 || !laser { let sgpj = params.prflin[id * MFREQ + kj] * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgpi; state.emis1[id] += sgpj; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += sgpj * params.demlt[(itr - 1) * MDEPTH + id]; state.dabp1[(ii - 1) * MDEPTH + id] += sgpi * params.popinv[(ii - 1) * MDEPTH + id]; state.demp1[(jj - 1) * MDEPTH + id] += sgpj * params.popinv[(jj - 1) * MDEPTH + id]; } } } } else { for id in 0..nd { let kjd = params.jidi[id] as usize; let sg = (params.xjid[id] * params.sigfe[kjd * MFREQ + kj] + (1.0 - params.xjid[id]) * params.sigfe[(kjd + 1) * MFREQ + kj]) .exp(); let sgpi = sg * params.abtra[(itr - 1) * MDEPTH + id]; if sgpi > 0.0 || !laser { let sgpj = sg * params.emtra[(itr - 1) * MDEPTH + id]; state.abso1[id] += sgpi; state.emis1[id] += sgpj; if params.iifix[params.iatm[ii - 1] as usize] <= 0 { state.demt1[id] += sgpj * params.demlt[(itr - 1) * MDEPTH + id]; state.dabp1[(ii - 1) * MDEPTH + id] += sgpi * params.popinv[(ii - 1) * MDEPTH + id]; state.demp1[(jj - 1) * MDEPTH + id] += sgpj * params.popinv[(jj - 1) * MDEPTH + id]; } } } } } } /// 计算显式能级导数 fn compute_explicit_level_derivatives(params: &OpacfdParams, state: &mut OpacfdState) { let nd = params.nd; let nlvexp = params.nlvexp; let mut dabp0 = vec![0.0; MLEVEL]; let mut demp0 = vec![0.0; MLEVEL]; for id in 0..nd { dabp0.fill(0.0); demp0.fill(0.0); for i in 0..params.nlevel { if params.iifix[params.iatm[i] as usize] == 0 { let ii = params.iiexp[i]; if ii > 0 { let ii_idx = (ii - 1) as usize; dabp0[ii_idx] += state.dabp1[i * MDEPTH + id]; demp0[ii_idx] += state.demp1[i * MDEPTH + id]; } else if ii < 0 { let ii_idx = (-ii - 1) as usize; dabp0[ii_idx] += state.dabp1[i * MDEPTH + id] * params.pp[i * MDEPTH + id]; demp0[ii_idx] += state.demp1[i * MDEPTH + id] * params.pp[i * MDEPTH + id]; } else { let jj = params.iiexp[params.iltref[i * MDEPTH + id] as usize]; if jj > 0 { let jj_idx = (jj - 1) as usize; dabp0[jj_idx] += state.dabp1[i * MDEPTH + id] * params.pp[i * MDEPTH + id]; demp0[jj_idx] += state.demp1[i * MDEPTH + id] * params.pp[i * MDEPTH + id]; } if params.imodl[i].abs() <= 5 { state.dabt1[id] += state.dabp1[i * MDEPTH + id] * params.pt[i * MDEPTH + id]; state.demt1[id] += state.demp1[i * MDEPTH + id] * params.pt[i * MDEPTH + id]; state.dabn1[id] += state.dabp1[i * MDEPTH + id] * params.pn[i * MDEPTH + id]; state.demn1[id] += state.demp1[i * MDEPTH + id] * params.pn[i * MDEPTH + id]; } } } } for ii in 0..nlvexp { state.dabp1[ii * MDEPTH + id] = dabp0[ii]; state.demp1[ii * MDEPTH + id] = demp0[ii]; } } } /// 计算背景不透明度表 fn compute_background_opacity(params: &OpacfdParams, state: &mut OpacfdState, fr: f64) { let nd = params.nd; if fr >= params.frtabm { return; } let _imodf = 0; for id in 0..nd { let t = params.temp[id]; let _t1 = t * (1.0 + DELT); let rho = params.dens[id]; let _rho1 = rho * (1.0 + DELR); let plan = state.xkfb[id] / state.xkf1[id]; let dplan = plan / state.xkf1[id] * params.hkt1[id] * fr / t; // 调用 opctab - 需要完整参数结构体 // let opctab_params = OpctabParams { fr, ij, id: id + 1, t, rho, igram: imodf, iter: params.iter }; // let opctab_output = opctab(&opctab_params, &opctab_table, &mut opctab_model); // let ab = opctab_output.ab; // let sct = opctab_output.sct; let _ = opctab; // 标记函数已导入 // 暂时使用占位值 let ab = 0.0; let ab1 = 0.0; let _ab2 = 0.0; let sct = 0.0; let sct1 = 0.0; state.abso1[id] += ab; state.emis1[id] += ab * plan; state.scat1[id] += sct; // 温度导数 let dabtab = (ab1 - ab) / t / DELT; state.dabt1[id] += dabtab; state.demt1[id] += ab * dplan + dabtab * plan; state.dsct1[id] += (sct1 - sct) / t / DELT; state.dabt1[id] += state.dsct1[id]; // 密度导数 (暂时跳过) let dabn1a = 0.0; let demn1a = 0.0; let dscn1a = 0.0; if params.inhe <= 0 { state.dabt1[id] += dabn1a * params.drhodt[id]; state.demt1[id] += demn1a * params.drhodt[id]; state.dsct1[id] += dscn1a * params.drhodt[id]; } else { state.dabn1[id] += dabn1a; state.demn1[id] += demn1a; state.dscn1[id] += dscn1a; } if params.ifryb > 5 { state.abso1[id] /= params.dens[id]; state.emis1[id] /= params.dens[id]; state.scat1[id] /= params.dens[id]; state.dabt1[id] /= params.dens[id]; state.demt1[id] /= params.dens[id]; state.dsct1[id] /= params.dens[id]; } } } /// 存储显式频率量 fn store_explicit_frequency(params: &OpacfdParams, state: &mut OpacfdState) { let ije = (params.ijex[params.ij - 1] - 1) as usize; let nd = params.nd; for id in 0..nd { state.absoex[ije * MDEPTH + id] = state.abso1[id]; state.emisex[ije * MDEPTH + id] = state.emis1[id]; state.scatex[ije * MDEPTH + id] = state.scat1[id]; state.dabtex[ije * MDEPTH + id] = state.dabt1[id]; state.demtex[ije * MDEPTH + id] = state.demt1[id]; state.dabnex[ije * MDEPTH + id] = state.dabn1[id]; state.demnex[ije * MDEPTH + id] = state.demn1[id]; state.dabmex[ije * MDEPTH + id] = state.dabm1[id]; state.demmex[ije * MDEPTH + id] = state.demm1[id]; for ii in 0..params.nlvexp { state.drchex[ii * MFREQ * MDEPTH + ije * MDEPTH + id] = state.dabp1[ii * MDEPTH + id]; state.dretex[ii * MFREQ * MDEPTH + ije * MDEPTH + id] = state.demp1[ii * MDEPTH + id]; } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_opacfd_initialization() { // 基本初始化测试 let output = OpacfdOutput::default(); assert_eq!(output.abso1.len(), MDEPTH); assert_eq!(output.emis1.len(), MDEPTH); assert_eq!(output.scat1.len(), MDEPTH); } #[test] fn test_constants() { // 验证常量 assert!((C14 - 2.99793e14).abs() < 1e8); assert!((CFF1 - 1.3727e-25).abs() < 1e-30); assert!((DELT - 1e-3).abs() < 1e-10); assert!((DELR - 1e-3).abs() < 1e-10); } }