Phase 1 翻译 (完成): - TLUSTY 350 函数 100% 翻译 - SYNSPEC 168 函数 100% 翻译 - ~495 Rust 模块 Phase 2 集成 (完成): - TLUSTY RESOLV 7 个 TODO 全部清除 - TLUSTY Runner IJALI 频率选择实现 - OPFRAC ioniz.dat 解析完整实现 - SYNSPEC Runner 编排流程连接完成 - SYNSPEC RESOLV OPAC→RTE→OUTPRI 调用链完整 Phase 3 验证 (完成, 修复 8 处 bug): - INITIA: compute_hydrogen_level_bounds 索引混合修复 - INILIN: GAMR0/GS0/GW0 展宽公式修复, 经典 VdW 公式修复 - INIBL0: CNM 常数 2.997925e18→e17 修复 - OPAC: Lyman IJ=2 修正缺失修复 - RTE: minv3 矩阵求逆符号错误修复 自动化脚本改进: - specf2r.sh: 添加 429 限流退避、完成检测、同步等待 - SKILL.md: 三阶段工作流 + 状态文件系统 - references/: Phase 1/2/3 独立参考文档 新增: - src/bin/synspec.rs: SYNSPEC 可执行文件入口 - .f2r_phase/.f2r_tasks/.f2r_complete: 状态管理文件 编译: 0 错误 | Clippy: 0 错误 | 测试: voigt 28 + eldens 5 通过 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
502 lines
18 KiB
Rust
502 lines
18 KiB
Rust
//! 线不透明度和发射率计算(风模型变体)。
|
|
//!
|
|
//! 翻译自 SYNSPEC `LINOPW` 子程序 (synspec54.f:10590)。
|
|
//!
|
|
//! 与 LINOP 类似,但针对风模型做了以下扩展:
|
|
//! - 速度相关的线拒绝
|
|
//! - 辐射场处理 (itrad, trad, wdil)
|
|
//! - 窗口化频率网格的线心索引计算
|
|
//! - DOP1 = DOPA1(IAT,ID)/FR0 (与 LINOP 不同)
|
|
|
|
use super::phe1::{phe1, Phe1Params};
|
|
use super::phe2::{phe2, Phe2Params};
|
|
use super::voigtk::{voigtk, MVOI};
|
|
|
|
/// 物理常数
|
|
const UN: f64 = 1.0;
|
|
const EXT0: f64 = 3.17;
|
|
const TEN: f64 = 10.0;
|
|
const C3: f64 = 1.4387886;
|
|
const XET: f64 = 8067.6;
|
|
const XET3: f64 = XET * C3;
|
|
|
|
/// LINOPW 参数结构体。
|
|
///
|
|
/// 与 LinopParams 类似,但增加了风模型相关参数。
|
|
#[derive(Debug)]
|
|
pub struct LinopwParams<'a> {
|
|
/// 深度索引 (1-indexed)
|
|
pub id: usize,
|
|
/// 温度 (K)
|
|
pub temp: f64,
|
|
/// h/k (erg/K)
|
|
pub hk: f64,
|
|
/// 频率数
|
|
pub nfreq: usize,
|
|
/// 频率数组 (Hz)
|
|
pub freq: &'a [f64],
|
|
/// NOPAC — 不透明度截止频率索引
|
|
pub nopac: usize,
|
|
/// Planck 函数 PLAN(ID)
|
|
pub plan: f64,
|
|
/// 受激辐射修正 STIM(ID) — LINOPW 中未使用,保留接口兼容
|
|
pub stim: f64,
|
|
/// 谱线数 (NLIN)
|
|
pub nlin: usize,
|
|
/// 谱线数据
|
|
pub lines: &'a [LinopwLineData],
|
|
/// RRR(ID,ION,IAT)
|
|
pub rrr: &'a [f64],
|
|
/// RRR 维度: [natom][nion]
|
|
pub rrr_dims: (usize, usize),
|
|
/// DOPA1(IAT, ID) — Doppler 宽度
|
|
pub dopa1: &'a [f64],
|
|
/// DOPA1 维度: [natom]
|
|
pub dopa1_nat: usize,
|
|
/// G(level) — 能级统计权重
|
|
pub g: &'a [f64],
|
|
/// POPUL(level, ID) — 能级布居数
|
|
pub popul: &'a [f64],
|
|
/// POPUL 维度: [nlevel]
|
|
pub popul_nlev: usize,
|
|
/// PNLT(IAT, ION, ID) — NLTE 布居数
|
|
pub pnlt: &'a [f64],
|
|
/// PNLT 维度: [natom][nion]
|
|
pub pnlt_dims: (usize, usize),
|
|
/// ENEV(IAT, ION) — 电离能 (cm^-1)
|
|
pub enev: &'a [f64],
|
|
/// ENEV 维度: [natom]
|
|
pub enev_nat: usize,
|
|
/// ENION(level) — 能级能量 (erg)
|
|
pub enion: &'a [f64],
|
|
/// 激光删除标志 (lasdel)
|
|
pub lasdel: bool,
|
|
/// He II 特殊线数 (NSP)
|
|
pub nsp: usize,
|
|
/// He II 特殊线索引 (ISP0)
|
|
pub isp0: &'a [usize],
|
|
/// Voigt 函数表 H0
|
|
pub h0tab: &'a [f64; MVOI],
|
|
/// Voigt 函数表 H1
|
|
pub h1tab: &'a [f64; MVOI],
|
|
/// Voigt 函数表 H2
|
|
pub h2tab: &'a [f64; MVOI],
|
|
/// PHE1 轮廓表数据
|
|
pub phe1_data: Option<Phe1DataW<'a>>,
|
|
/// PHE2 公共数据
|
|
pub phe2_common: Option<Phe2CommonW<'a>>,
|
|
|
|
// --- 风模型特有参数 ---
|
|
/// 速度场 VEL(ID)
|
|
pub vel: f64,
|
|
/// 最大速度 VELMAX
|
|
pub velmax: f64,
|
|
/// 辐射场模式 (ITRAD)
|
|
pub itrad: i32,
|
|
/// 辐射温度 TRAD(ipotl, ID)
|
|
pub trad: &'a [f64],
|
|
/// TRAD 维度: [npotl]
|
|
pub trad_npotl: usize,
|
|
/// IPOTL(line) — 电离势索引
|
|
pub ipotl: &'a [usize],
|
|
/// BNUE(ij) — 频率相关 Planck 函数
|
|
pub bnue: &'a [f64],
|
|
/// NLTE 关闭标志 (NLTOFF)
|
|
pub nltoff: i32,
|
|
/// 发射关闭标志 (IEMOFF)
|
|
pub iemoff: i32,
|
|
/// 线心 NLTE 关闭标记 ILNE(depth)
|
|
pub ilne: &'a [usize],
|
|
/// 线心速度拒绝标记 ILVI(depth)
|
|
pub ilvi: &'a [usize],
|
|
/// 线心频率索引 IJCNTR(line) — 输出
|
|
pub ijcntr: &'a mut [usize],
|
|
/// 标准线吸收 ABSTDW(ijcont, ID)
|
|
pub abstdw: &'a [f64],
|
|
/// ABSTDW 维度: [nfreq]
|
|
pub abstdw_nfreq: usize,
|
|
/// RELOP — 相对不透明度阈值
|
|
pub relop: f64,
|
|
/// IJCONT(line) — 线心频率索引
|
|
pub ijcont: &'a [usize],
|
|
/// 准直函数 XJCON(ID) — 未使用,保留
|
|
pub xjcon: f64,
|
|
/// 稀释因子 WDIL(ID) — 输出
|
|
pub wdil_out: &'a mut f64,
|
|
}
|
|
|
|
/// 单条谱线数据 (LINOPW 版本)。
|
|
#[derive(Debug, Clone)]
|
|
pub struct LinopwLineData {
|
|
pub il: usize,
|
|
pub innlt: i32,
|
|
pub iat: usize,
|
|
pub ion: usize,
|
|
pub isprf: usize,
|
|
pub freq0: f64,
|
|
pub gf0: f64,
|
|
pub excl0: f64,
|
|
pub excu0: f64,
|
|
pub agam: f64,
|
|
pub dop1_inv: f64,
|
|
pub abcent: f64,
|
|
pub slin: f64,
|
|
pub ilown: usize,
|
|
pub iupn: usize,
|
|
}
|
|
|
|
/// PHE1 轮廓表数据 (LINOPW 版本)。
|
|
#[derive(Debug)]
|
|
pub struct Phe1DataW<'a> {
|
|
pub vturb: f64,
|
|
pub elec: f64,
|
|
pub prf447: &'a [f64],
|
|
pub dlm447: &'a [f64],
|
|
pub xne447: &'a [f64],
|
|
pub nwlam_447: &'a [usize],
|
|
pub prfhe1: &'a [f64],
|
|
pub dlmhe1: &'a [f64],
|
|
pub xnehe1: &'a [f64],
|
|
pub nwlam_he1: &'a [usize],
|
|
pub max_wlam_447: usize,
|
|
pub max_wlam_he1: usize,
|
|
}
|
|
|
|
/// PHE2 公共数据 (LINOPW 版本)。
|
|
#[derive(Debug)]
|
|
pub struct Phe2CommonW<'a> {
|
|
pub ielhe2: i32,
|
|
pub inlte: i32,
|
|
pub he3_pop: f64,
|
|
pub nlhe2: i32,
|
|
pub nfirst_he2: i32,
|
|
pub wlam: &'a [f64],
|
|
pub prfhe2: &'a [f64],
|
|
pub wlhe2: &'a [f64],
|
|
pub nwlhe2: i32,
|
|
pub ilhe2: i32,
|
|
pub iuhe2: i32,
|
|
pub lasdel: bool,
|
|
}
|
|
|
|
/// LINOPW 输出结果。
|
|
#[derive(Debug)]
|
|
pub struct LinopwResult {
|
|
pub ablin: Vec<f64>,
|
|
pub emlin: Vec<f64>,
|
|
}
|
|
|
|
/// 计算线不透明度和发射率(风模型变体)。
|
|
pub fn linopw(params: &mut LinopwParams) -> LinopwResult {
|
|
let nfreq = params.nfreq;
|
|
let mut ablin = vec![0.0f64; nfreq];
|
|
let mut ablinn = vec![0.0f64; nfreq];
|
|
let mut emlin = vec![0.0f64; nfreq];
|
|
|
|
*params.wdil_out = 1.0;
|
|
let _plw = params.plan * 1.0; // wdil=1
|
|
|
|
if params.nlin == 0 {
|
|
return LinopwResult { ablin, emlin };
|
|
}
|
|
|
|
let tem1 = UN / params.temp;
|
|
let hkt = params.hk * tem1;
|
|
|
|
// 计算频率间距因子
|
|
let xx = params.freq[nfreq - 1] - params.freq[0];
|
|
let dfrcon = if xx.abs() > 1e-30 {
|
|
-((params.nopac as f64) - 1.0) / xx
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
for (line_idx, line_data) in params.lines.iter().take(params.nlin).enumerate() {
|
|
let il = line_data.il;
|
|
let innlt = line_data.innlt;
|
|
|
|
// 速度拒绝
|
|
if params.ilvi[params.id - 1] > 0 {
|
|
if innlt == 0 {
|
|
continue;
|
|
} else if params.nltoff != 0 {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// 线心频率索引 (仅深度 1)
|
|
if params.id == 1 {
|
|
let fr0 = line_data.freq0;
|
|
let xjc = 3.0 + dfrcon * (params.freq[0] - fr0);
|
|
let mut ijc = xjc as usize;
|
|
if ijc > 1 && ijc < params.nopac {
|
|
// 在频率网格中找到最近的点
|
|
if fr0 < params.freq[ijc] {
|
|
let mut ijc0 = ijc;
|
|
let mut dfr0 = params.freq[ijc0] - fr0;
|
|
loop {
|
|
ijc0 += 1;
|
|
if ijc0 >= nfreq {
|
|
break;
|
|
}
|
|
let dfr = (params.freq[ijc0] - fr0).abs();
|
|
if dfr < dfr0 {
|
|
ijc = ijc0;
|
|
dfr0 = dfr;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
} else if fr0 > params.freq[ijc] {
|
|
let mut ijc0 = ijc;
|
|
let mut dfr0 = fr0 - params.freq[ijc0];
|
|
loop {
|
|
if ijc0 == 0 {
|
|
break;
|
|
}
|
|
ijc0 -= 1;
|
|
let dfr = (params.freq[ijc0] - fr0).abs();
|
|
if dfr < dfr0 {
|
|
ijc = ijc0;
|
|
dfr0 = dfr;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
params.ijcntr[line_idx] = ijc;
|
|
}
|
|
|
|
let iat = line_data.iat;
|
|
let ion = line_data.ion;
|
|
let fr0 = line_data.freq0;
|
|
let lpr = !(line_data.isprf > 1 && line_data.isprf <= 5);
|
|
if line_data.isprf >= 6 {
|
|
continue;
|
|
}
|
|
|
|
let agam = line_data.agam;
|
|
let dop1 = 1.0 / line_data.dop1_inv / fr0; // DOPA1(IAT,ID)/FR0
|
|
|
|
// 计算 ab0 和 sl0
|
|
let (ab0, sl0) = if innlt == 0 && params.itrad <= 0 {
|
|
// LTE 线 (无辐射场)
|
|
let rrr_idx = params.rrr_dims.0 * params.rrr_dims.1 * (params.id - 1)
|
|
+ ion * params.rrr_dims.0 + iat;
|
|
let rrr_val = if rrr_idx < params.rrr.len() { params.rrr[rrr_idx] } else { 0.0 };
|
|
let ab0 = (line_data.gf0 - line_data.excl0 * tem1).exp()
|
|
* rrr_val * dop1 * (1.0 - (-hkt * fr0).exp());
|
|
(ab0, 0.0)
|
|
} else if innlt == 0 && params.itrad > 0 {
|
|
// LTE 线 (有辐射场)
|
|
let ipotl_idx = if il < params.ipotl.len() { params.ipotl[il] } else { 0 };
|
|
let trad_idx = ipotl_idx * params.trad_npotl + (params.id - 1);
|
|
let trl = if trad_idx < params.trad.len() { params.trad[trad_idx] } else { params.temp };
|
|
let xx = (-hkt * fr0).exp();
|
|
let rrr_idx = params.rrr_dims.0 * params.rrr_dims.1 * (params.id - 1)
|
|
+ ion * params.rrr_dims.0 + iat;
|
|
let rrr_val = if rrr_idx < params.rrr.len() { params.rrr[rrr_idx] } else { 0.0 };
|
|
let mut ab0 = (line_data.gf0 - line_data.excl0 / trl).exp()
|
|
* rrr_val * dop1 * (1.0 - xx);
|
|
if line_data.excl0 > 2000.0 {
|
|
ab0 *= 1.0; // wdil=1
|
|
}
|
|
let pla = 1.4743e-2 * (fr0 * 1e-15).powi(3) * xx / (1.0 - xx);
|
|
let sl0 = pla * 1.0; // wdil=1
|
|
(ab0, sl0)
|
|
} else if innlt > 0 {
|
|
(line_data.abcent, line_data.slin)
|
|
} else {
|
|
// NLTE 线
|
|
let pnlt_idx = params.pnlt_dims.0 * params.pnlt_dims.1 * (params.id - 1)
|
|
+ ion * params.pnlt_dims.0 + iat;
|
|
let pp = if pnlt_idx < params.pnlt.len() { params.pnlt[pnlt_idx] } else { 0.0 };
|
|
|
|
let pi = if line_data.ilown > 0 {
|
|
let pop_idx = (line_data.ilown - 1) * params.popul_nlev + (params.id - 1);
|
|
if pop_idx < params.popul.len() {
|
|
params.popul[pop_idx] / params.g[line_data.ilown - 1]
|
|
} else { 0.0 }
|
|
} else {
|
|
let enev_idx = params.enev_nat * (params.id - 1) + iat;
|
|
let enev_val = if enev_idx < params.enev.len() { params.enev[enev_idx] } else { 0.0 };
|
|
pp * ((enev_val * XET3 - line_data.excl0) * tem1).exp()
|
|
};
|
|
|
|
let (pj, cor) = if line_data.iupn > 0 {
|
|
let pop_idx = (line_data.iupn - 1) * params.popul_nlev + (params.id - 1);
|
|
let pj = if pop_idx < params.popul.len() {
|
|
params.popul[pop_idx] / params.g[line_data.iupn - 1]
|
|
} else { 0.0 };
|
|
let cor = if line_data.ilown > 0 && line_data.iupn > 0 {
|
|
((line_data.excu0 - line_data.excl0
|
|
+ (params.enion[line_data.iupn - 1] - params.enion[line_data.ilown - 1]) / 1.38054e-16)
|
|
* tem1).exp()
|
|
} else { 1.0 };
|
|
(pj, cor)
|
|
} else {
|
|
let enev_idx = params.enev_nat * (params.id - 1) + iat;
|
|
let enev_val = if enev_idx < params.enev.len() { params.enev[enev_idx] } else { 0.0 };
|
|
let pj = pp * ((enev_val * XET3 - line_data.excu0) * tem1).exp();
|
|
(pj, 1.0)
|
|
};
|
|
|
|
let x = if pj > 0.0 { pi / pj * cor } else { UN };
|
|
let x = if x == UN { (4.79928e-11 * fr0 * tem1).exp() } else { x };
|
|
let sl0 = params.plan / (x - UN);
|
|
let ab0 = if pi > 0.0 { pi * (UN - UN / x) * line_data.gf0.exp() * dop1 } else { 0.0 };
|
|
(ab0, sl0)
|
|
};
|
|
|
|
if ab0 <= 0.0 && params.lasdel {
|
|
continue;
|
|
}
|
|
|
|
// 频率贡献范围
|
|
let ijcont_idx = if il < params.ijcont.len() { params.ijcont[il] } else { 0 };
|
|
let abstdw_idx = ijcont_idx * params.abstdw_nfreq + (params.id - 1);
|
|
let avabw = if abstdw_idx < params.abstdw.len() {
|
|
params.abstdw[abstdw_idx] * params.relop
|
|
} else { 0.0 };
|
|
let ex0 = if avabw > 0.0 { ab0 / avabw * agam } else { 0.0 };
|
|
let ext = if ex0 > TEN { ex0.sqrt() } else { EXT0 };
|
|
let ext = ext / dop1;
|
|
let ijext = (dfrcon * ext + 1.5) as usize;
|
|
let ijctr = params.ijcntr[line_idx];
|
|
let ij1 = ijctr.saturating_sub(ijext).max(1);
|
|
let ij2 = (ijctr + ijext).min(nfreq);
|
|
|
|
if ij1 >= nfreq || ij2 <= 2 {
|
|
continue;
|
|
}
|
|
|
|
if innlt == 0 && params.itrad <= 0 {
|
|
// LTE 线
|
|
if lpr {
|
|
for ij in ij1..=ij2.min(nfreq - 1) {
|
|
let xf = (params.freq[ij] - fr0).abs() * dop1;
|
|
ablin[ij] += ab0 * voigtk(agam, xf, params.h0tab, params.h1tab, params.h2tab);
|
|
}
|
|
} else if let Some(ref phe1d) = params.phe1_data {
|
|
for ij in 0..nfreq {
|
|
let phe1_p = Phe1Params {
|
|
id: params.id, freq: params.freq[ij], iline: line_data.isprf - 1,
|
|
temp: params.temp, elec: phe1d.elec, vturb: phe1d.vturb,
|
|
prf447: phe1d.prf447, dlm447: phe1d.dlm447, xne447: phe1d.xne447,
|
|
nwlam_447: phe1d.nwlam_447, prfhe1: phe1d.prfhe1, dlmhe1: phe1d.dlmhe1,
|
|
xnehe1: phe1d.xnehe1, nwlam_he1: phe1d.nwlam_he1,
|
|
max_wlam_447: phe1d.max_wlam_447, max_wlam_he1: phe1d.max_wlam_he1,
|
|
h0tab: params.h0tab, h1tab: params.h1tab, h2tab: params.h2tab,
|
|
};
|
|
ablin[ij] += ab0 * phe1(&phe1_p);
|
|
}
|
|
}
|
|
} else {
|
|
// NLTE 线 或 有辐射场的 LTE 线
|
|
if lpr {
|
|
for ij in ij1..=ij2.min(nfreq - 1) {
|
|
let xf = (params.freq[ij] - fr0).abs() * dop1;
|
|
let abl = ab0 * voigtk(agam, xf, params.h0tab, params.h1tab, params.h2tab);
|
|
ablinn[ij] += abl;
|
|
if params.ilne[params.id - 1] == 0 {
|
|
emlin[ij] += abl * sl0;
|
|
}
|
|
}
|
|
} else if let Some(ref phe1d) = params.phe1_data {
|
|
for ij in 0..nfreq {
|
|
let phe1_p = Phe1Params {
|
|
id: params.id, freq: params.freq[ij], iline: line_data.isprf - 1,
|
|
temp: params.temp, elec: phe1d.elec, vturb: phe1d.vturb,
|
|
prf447: phe1d.prf447, dlm447: phe1d.dlm447, xne447: phe1d.xne447,
|
|
nwlam_447: phe1d.nwlam_447, prfhe1: phe1d.prfhe1, dlmhe1: phe1d.dlmhe1,
|
|
xnehe1: phe1d.xnehe1, nwlam_he1: phe1d.nwlam_he1,
|
|
max_wlam_447: phe1d.max_wlam_447, max_wlam_he1: phe1d.max_wlam_he1,
|
|
h0tab: params.h0tab, h1tab: params.h1tab, h2tab: params.h2tab,
|
|
};
|
|
let abl = ab0 * phe1(&phe1_p);
|
|
ablinn[ij] += abl;
|
|
if params.ilne[params.id - 1] == 0 {
|
|
emlin[ij] += abl * sl0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 连续谱贡献
|
|
if params.vel <= params.velmax {
|
|
for ij in 0..nfreq {
|
|
let pla = if (hkt * params.freq[ij]).exp() - 1.0 > 1e-30 {
|
|
params.bnue[ij] / ((hkt * params.freq[ij]).exp() - 1.0)
|
|
} else { 0.0 };
|
|
emlin[ij] += ablin[ij] * pla; // wdil=1
|
|
ablin[ij] += ablinn[ij];
|
|
}
|
|
}
|
|
|
|
// He II 特殊线
|
|
if params.nsp > 0
|
|
&& let Some(ref phe2c) = params.phe2_common {
|
|
for &isp in params.isp0.iter().take(params.nsp) {
|
|
if (6..=24).contains(&isp) {
|
|
let phe2_p = Phe2Params {
|
|
ispec: isp as i32, id: params.id as i32,
|
|
ielhe2: phe2c.ielhe2, inlte: phe2c.inlte,
|
|
nfreq: nfreq as i32, freq: params.freq, wlam: phe2c.wlam,
|
|
temp: params.temp, elec: 0.0, he3_pop: phe2c.he3_pop,
|
|
nlhe2: phe2c.nlhe2, nfirst_he2: phe2c.nfirst_he2,
|
|
popul: &[], prfhe2: phe2c.prfhe2, wlhe2: phe2c.wlhe2,
|
|
nwlhe2: phe2c.nwlhe2, ilhe2: phe2c.ilhe2, iuhe2: phe2c.iuhe2,
|
|
lasdel: phe2c.lasdel,
|
|
};
|
|
let result = phe2(&phe2_p);
|
|
for ij in 0..nfreq {
|
|
ablin[ij] += result.ablin[ij];
|
|
emlin[ij] += result.emlin[ij];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LinopwResult { ablin, emlin }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_linopw_zero_lines() {
|
|
let freq = vec![1e14; 10];
|
|
let h0tab = [0.0f64; MVOI];
|
|
let h1tab = [0.0f64; MVOI];
|
|
let h2tab = [0.0f64; MVOI];
|
|
let mut wdil = 0.0f64;
|
|
let mut ijcntr = vec![0usize; 1];
|
|
|
|
let mut params = LinopwParams {
|
|
id: 1, temp: 10000.0, hk: 4.79928e-11,
|
|
nfreq: 10, freq: &freq, nopac: 10,
|
|
plan: 1.0, stim: 1.0, nlin: 0, lines: &[],
|
|
rrr: &[], rrr_dims: (0, 0), dopa1: &[], dopa1_nat: 0,
|
|
g: &[], popul: &[], popul_nlev: 0,
|
|
pnlt: &[], pnlt_dims: (0, 0),
|
|
enev: &[], enev_nat: 0, enion: &[],
|
|
lasdel: false, nsp: 0, isp0: &[],
|
|
h0tab: &h0tab, h1tab: &h1tab, h2tab: &h2tab,
|
|
phe1_data: None, phe2_common: None,
|
|
vel: 0.0, velmax: 1e10, itrad: 0,
|
|
trad: &[], trad_npotl: 0, ipotl: &[],
|
|
bnue: &freq, nltoff: 0, iemoff: 0,
|
|
ilne: &[0], ilvi: &[0],
|
|
ijcntr: &mut ijcntr,
|
|
abstdw: &[], abstdw_nfreq: 0, relop: 1.0,
|
|
ijcont: &[0], xjcon: 0.0, wdil_out: &mut wdil,
|
|
};
|
|
let result = linopw(&mut params);
|
|
assert!(result.ablin.iter().all(|&x| x == 0.0));
|
|
assert!(result.emlin.iter().all(|&x| x == 0.0));
|
|
}
|
|
}
|