Files
SpectraRust/src/math/alisk2.rs
T
fmqandClaude Opus 4.6 a086e313cb 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>
2026-03-25 01:46:29 +08:00

957 lines
29 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 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);
}
}
}