SpectraRust/src/tlusty/math/alisk1.rs
2026-03-25 13:31:23 +08:00

900 lines
26 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 迭代简化版本。
//!
//! 重构自 TLUSTY `alisk1.f`
//!
//! # 功能
//!
//! 简化版 ALIST1用于 Kantorovich 迭代。
//! 计算所有必要的 ALI 参数和辐射跃迁率。
//!
//! # 算法
//!
//! 1. 初始化速率和其他量
//! 2. 确定是否计算 Rosseland 平均不透明度
//! 3. 遍历所有频率点:
//! - 计算不透明度 (OPACF1)
//! - 求解辐射转移方程 (RTEFR1)
//! - 计算 ALI 系数 (ALIFRK)
//! - 可选:计算 Rosseland 贡献 (ROSSTD)
//! - 处理连续谱跃迁
//! - 处理线跃迁
//! 4. 后处理:乘以频率无关常数
//! 5. 辐射压力计算
//! 6. Rosseland 平均不透明度
use crate::tlusty::state::constants::{MDEPTH, MFREQ, MTRANS, UN, HK, PCK};
// ============================================================================
// 配置结构体
// ============================================================================
/// ALISK1 配置参数。
#[derive(Debug, Clone)]
pub struct Alisk1Config {
/// 深度修正数(负值表示不计算 Rosseland
pub ndre: i32,
/// 当前迭代次数
pub iter: i32,
/// 最终迭代标志
pub lfin: bool,
/// 混合参数 (>0 强制计算 Rosseland)
pub hmix0: f64,
/// 不透明度表格标志 (<0 跳过跃迁处理)
pub ioptab: i32,
/// 盘模式标志
pub idisk: i32,
}
impl Default for Alisk1Config {
fn default() -> Self {
Self {
ndre: 0,
iter: 1,
lfin: false,
hmix0: 0.0,
ioptab: 0,
idisk: 0,
}
}
}
// ============================================================================
// 输入/输出结构体
// ============================================================================
/// ALISK1 频率相关参数。
pub struct Alisk1FreqParams<'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],
}
/// ALISK1 原子参数。
pub struct Alisk1AtomicParams<'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],
/// 线线型 [nfreq × nd] - PRFLIN
pub prflin: &'a [f64],
/// 重叠线跃迁索引 [maxlines × nfreq], 1-indexed
pub trlin: &'a [i32],
/// 跃迁起始频率索引 [ntrans]
pub ifr0: &'a [i32],
/// 跃迁结束频率索引 [ntrans]
pub ifr1: &'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],
}
/// ALISK1 模型状态参数。
pub struct Alisk1ModelState<'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],
}
/// ALISK1 输出状态。
pub struct Alisk1OutputState<'a> {
// 累积量 [nd]
/// 冷却率积分
pub fcooli: &'a mut [f64],
/// 固定辐射通量
pub flfix: &'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],
}
/// ALISK1 输出结果。
#[derive(Debug, Clone)]
pub struct Alisk1Output {
/// 是否执行了计算
pub computed: bool,
/// Rosseland 标志
pub lross: bool,
/// 最小辐射压力比
pub prdx: f64,
}
// ============================================================================
// 核心计算函数
// ============================================================================
/// ALI Kantorovich 迭代简化版本 (ALISK1)。
///
/// 计算所有必要的 ALI 参数和辐射跃迁率。
///
/// # 参数
///
/// * `config` - 配置参数
/// * `freq_params` - 频率相关参数
/// * `atomic_params` - 原子参数
/// * `model_state` - 模型状态
/// * `output_state` - 输出状态(可变)
///
/// # 返回值
///
/// 返回 `Alisk1Output`,包含计算结果信息。
///
/// # 注意
///
/// 此函数是一个框架实现,实际调用 OPACF1、RTEFR1、ALIFRK、ROSSTD
/// 需要在完整系统中实现。当前版本主要用于结构验证。
pub fn alisk1_pure(
config: &Alisk1Config,
freq_params: &Alisk1FreqParams,
atomic_params: &Alisk1AtomicParams,
model_state: &Alisk1ModelState,
output_state: &mut Alisk1OutputState,
) -> Alisk1Output {
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.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 标志
// ========================================================================
// LROSS = NDRE.LE.0.AND.ITER.EQ.1.OR.LFIN
// IF(HMIX0.GT.0.) LROSS=.TRUE.
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 函数
// 这里只是框架,假设 abso1, emis1, scat1 已填充
// ----------------------------------------------------------------
// 3b. 存储扩展频率数据
// ----------------------------------------------------------------
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];
}
}
// ----------------------------------------------------------------
// 3c. 调用 RTEFR1(IJ) - 辐射转移
// ----------------------------------------------------------------
// 注意:实际实现需要调用 rtefr1 函数
// ----------------------------------------------------------------
// 3d. 调用 ALIFRK(IJ) - ALI 系数
// ----------------------------------------------------------------
// 注意:实际实现需要调用 alifrk 函数
// ----------------------------------------------------------------
// 3e. 可选:调用 ROSSTD(IJ) - Rosseland 贡献
// ----------------------------------------------------------------
// if lross { rosstd_contribute(...); }
// 跳过跃迁处理(如果 ioptab < 0
if config.ioptab < 0 {
continue;
}
// ----------------------------------------------------------------
// 3f. 处理连续谱跃迁
// ----------------------------------------------------------------
process_continuum_transitions(
ij,
fr,
w0,
nd,
freq_params,
atomic_params,
model_state,
output_state,
);
// ----------------------------------------------------------------
// 3g. 处理线跃迁
// ----------------------------------------------------------------
process_line_transitions(
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)
// 注意:这里更新的是 fcooli完整的 fcool 计算在外部
// 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]);
}
}
}
Alisk1Output {
computed: true,
lross,
prdx,
}
}
/// 处理连续谱跃迁。
fn process_continuum_transitions(
ij: usize,
fr: f64,
w0: f64,
nd: usize,
freq_params: &Alisk1FreqParams,
atomic_params: &Alisk1AtomicParams,
model_state: &Alisk1ModelState,
output_state: &mut Alisk1OutputState,
) {
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; // 1-indexed to 0-indexed
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 jc = (atomic_params.itra[jj * ii + jj] - 1) as usize; // ITRA(JJ, II)
let icdw = atomic_params.mcdw[itr];
let imer = atomic_params.imrg[ii] as usize;
let mut sg_local = sg;
// 频率加权修正
if atomic_params.ifwop[ii] >= 0 {
if icdw >= 1 {
let icdw_idx = (icdw - 1) as usize;
sg_local *= atomic_params.dwf1[icdw_idx * nd + id];
}
} else {
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(
ij: usize,
fr: f64,
w0: f64,
nd: usize,
freq_params: &Alisk1FreqParams,
atomic_params: &Alisk1AtomicParams,
model_state: &Alisk1ModelState,
output_state: &mut Alisk1OutputState,
) {
// 主线跃迁
let ijlin_ij = freq_params.ijlin[ij];
if ijlin_ij > 0 {
let itr = (ijlin_ij - 1) as usize; // 1-indexed to 0-indexed
for id in 0..nd {
let sgw0 = atomic_params.prflin[ij * nd + id] * w0;
let rbnu = output_state.rad1[id] * (-fr * HK / model_state.temp[id]).exp();
output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id];
output_state.rrd[itr * nd + id] += sgw0 * rbnu;
}
}
// 重叠线
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 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 {
let sgw0 = a1 * atomic_params.prflin[ij1_idx * nd + id]
+ a2 * atomic_params.prflin[ij0_idx * nd + id];
let rbnu = output_state.rad1[id] * (-fr * HK / model_state.temp[id]).exp();
output_state.rru[itr * nd + id] += sgw0 * output_state.rad1[id];
output_state.rrd[itr * nd + id] += sgw0 * rbnu;
}
}
}
// ============================================================================
// 测试
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
fn create_test_config() -> Alisk1Config {
Alisk1Config {
ndre: 0,
iter: 1,
lfin: false,
hmix0: 0.0,
ioptab: -1, // 跳过跃迁处理
idisk: 0,
}
}
#[test]
fn test_alisk1_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 freq_params = Alisk1FreqParams {
nfreq,
freq: &freq,
w0e: &w0e,
ijx: &ijx,
ijex: &ijex,
ijlin: &ijlin,
nlines: &nlines,
bnue: &bnue,
};
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 prflin = vec![0.0; nfreq * nd];
let trlin = vec![0; 10 * nfreq];
let ifr0 = vec![0; ntrans];
let ifr1 = 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 atomic_params = Alisk1AtomicParams {
ntranc: 3,
ntrans,
itrbf: &itrbf,
ilow: &ilow,
iup: &iup,
mcdw: &mcdw,
imrg: &imrg,
ifwop: &ifwop,
cross: &cross,
prflin: &prflin,
trlin: &trlin,
ifr0: &ifr0,
ifr1: &ifr1,
linexp: &linexp,
sgmg: &sgmg,
dwf1: &dwf1,
itra: &itra,
};
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 model_state = Alisk1ModelState {
nd,
temp: &temp,
elec: &elec,
dens: &dens,
dens1: &dens1,
dm: &dm,
hkt1: &hkt1,
reint: &reint,
redif: &redif,
crsw: &crsw,
ipzero: &ipzero,
};
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; 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 output_state = Alisk1OutputState {
fcooli: &mut fcooli,
flfix: &mut flfix,
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,
};
let output = alisk1_pure(&config, &freq_params, &atomic_params, &model_state, &mut output_state);
assert!(output.computed);
assert!(output.lross); // 因为 iter=1 且 ndre=0
}
#[test]
fn test_alisk1_skip_frequency() {
let mut config = create_test_config();
let nfreq = 5;
let nd = 3;
let ntrans = 2;
// 设置 IJX[0] = -1应该跳过第一个频率
let freq = vec![1e14; nfreq];
let w0e = vec![1.0; nfreq];
let ijx = vec![-1, 0, 0, 0, 0];
let ijex = vec![0; nfreq];
let ijlin = vec![0; nfreq];
let nlines = vec![0; nfreq];
let bnue = vec![0.0; nfreq * nd];
let freq_params = Alisk1FreqParams {
nfreq,
freq: &freq,
w0e: &w0e,
ijx: &ijx,
ijex: &ijex,
ijlin: &ijlin,
nlines: &nlines,
bnue: &bnue,
};
let itrbf = vec![1, 2];
let ilow = vec![1, 2];
let iup = vec![2, 3];
let mcdw = vec![0; ntrans];
let imrg = vec![0; 10];
let ifwop = vec![0; 10];
let cross = vec![0.0; 2 * nfreq];
let prflin = vec![0.0; nfreq * nd];
let trlin = vec![0; 10 * nfreq];
let ifr0 = vec![0; ntrans];
let ifr1 = 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 atomic_params = Alisk1AtomicParams {
ntranc: 2,
ntrans,
itrbf: &itrbf,
ilow: &ilow,
iup: &iup,
mcdw: &mcdw,
imrg: &imrg,
ifwop: &ifwop,
cross: &cross,
prflin: &prflin,
trlin: &trlin,
ifr0: &ifr0,
ifr1: &ifr1,
linexp: &linexp,
sgmg: &sgmg,
dwf1: &dwf1,
itra: &itra,
};
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 model_state = Alisk1ModelState {
nd,
temp: &temp,
elec: &elec,
dens: &dens,
dens1: &dens1,
dm: &dm,
hkt1: &hkt1,
reint: &reint,
redif: &redif,
crsw: &crsw,
ipzero: &ipzero,
};
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; 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 output_state = Alisk1OutputState {
fcooli: &mut fcooli,
flfix: &mut flfix,
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,
};
let output = alisk1_pure(&config, &freq_params, &atomic_params, &model_state, &mut output_state);
assert!(output.computed);
}
#[test]
fn test_lross_determination() {
// 测试 LROSS 标志的各种条件
// 条件 1: ndre <= 0 AND iter == 1
let config1 = Alisk1Config {
ndre: 0,
iter: 1,
lfin: false,
hmix0: 0.0,
ioptab: -1,
idisk: 0,
};
// LROSS 应该为 true
// 条件 2: lfin = true
let config2 = Alisk1Config {
ndre: 1,
iter: 2,
lfin: true,
hmix0: 0.0,
ioptab: -1,
idisk: 0,
};
// LROSS 应该为 true
// 条件 3: hmix0 > 0
let config3 = Alisk1Config {
ndre: 1,
iter: 2,
lfin: false,
hmix0: 1.0,
ioptab: -1,
idisk: 0,
};
// LROSS 应该为 true
// 条件 4: 所有条件都不满足
let config4 = Alisk1Config {
ndre: 1,
iter: 2,
lfin: false,
hmix0: 0.0,
ioptab: -1,
idisk: 0,
};
// LROSS 应该为 false
// 简单验证配置创建
assert!(config1.ndre <= 0 && config1.iter == 1);
assert!(config2.lfin);
assert!(config3.hmix0 > 0.0);
assert!(!(config4.ndre <= 0 && config4.iter == 1)
&& !config4.lfin
&& !(config4.hmix0 > 0.0));
}
}