feat: 添加更多重构模块 (第7批)

包含 IO 和 math 模块的实现:
- IO: initia, levcd, linset, ltegr, ltegrd, odfset, outpri, resolv, srtfrq, start, tabini, xenini
- Math: accel2, alisk1, alisk2, alist1, alist2, concor, conout, conref, contmd, contmp, coolrt, greyd, inilam, linsel, lucy, lymlin, matcon, matgen, moleq, newdm, newdmt, odf1, opacf0, opacf1, opacfa, opacfd, opacfl, opactr, opadd, opahst, pgset, princ, prnt, pzeval, quasim, radpre, radtot, rates1, ratsp1, rdata, rdatax, rechck, rhoeos, rhonen, rhsgen, rossop, rtecf1, rtecmc, rtecmu, rtecom, rtefr1, rteint, russel, rybchn, rybene, rybheq, rybsol, sgmer1, sigave, sigk, solve, solves, state, steqeq, temcor, temper, topbas, trmder, trmdrt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
fmq
2026-03-25 01:46:29 +08:00
co-authored by Claude Opus 4.6
parent 21cb6af16c
commit a086e313cb
85 changed files with 48464 additions and 6 deletions
+956
View File
@@ -0,0 +1,956 @@
//! 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);
}
}
}