This commit is contained in:
fmq
2026-03-19 22:16:23 +08:00
parent 1e30b7bc63
commit 8e21522d2d
41 changed files with 14497 additions and 26 deletions
+250
View File
@@ -0,0 +1,250 @@
//! ALI (加速 Lambda 迭代) 相关数组。
//!
//! 重构自 TLUSTY `ALIPAR.FOR`
use super::constants::*;
// ============================================================================
// FIXALP - 固定 ALI 参数
// ============================================================================
/// ALI 固定参数和数组。
/// 对应 COMMON /FIXALP/
///
/// 包含大量辐射转移计算中间变量:
/// - ABSO, EMIS, SCAT: 吸收/发射/散射系数
/// - REIT, REIN, REIM, REIP: 辐射等效项
/// - AREIT, AREIN, AREIM, AREIP: A 相关
/// - HEIT, HEIN, HEIM, HEIP: He 相关
#[derive(Debug, Clone)]
pub struct FixAlp {
// 频率相关 (MFREQ)
/// 吸收系数
pub abso: Vec<f64>,
/// 发射系数
pub emis: Vec<f64>,
/// 散射系数
pub scat: Vec<f64>,
// 深度相关 (MDEPTH)
/// 辐射等效 - T 导数
pub reit: Vec<f64>,
/// 辐射等效 - N 导数
pub rein: Vec<f64>,
/// 辐射等效 - M 导数
pub reim: Vec<f64>,
// 能级导数 (MLVEXP × MDEPTH)
pub reip: Vec<Vec<f64>>,
// A 矩阵相关
pub areit: Vec<f64>,
pub arein: Vec<f64>,
pub areim: Vec<f64>,
pub areip: Vec<Vec<f64>>,
// C 矩阵相关
pub creit: Vec<f64>,
pub crein: Vec<f64>,
pub creim: Vec<f64>,
pub creip: Vec<Vec<f64>>,
// 辐射等效 X
pub reix: Vec<f64>,
pub creix: Vec<f64>,
// Red 相关 - T
pub redx: Vec<f64>,
pub redt: Vec<f64>,
pub redn: Vec<f64>,
pub redm: Vec<f64>,
pub redp: Vec<Vec<f64>>,
// Red 相关 - M
pub redxm: Vec<f64>,
pub redtm: Vec<f64>,
pub rednm: Vec<f64>,
pub redmm: Vec<f64>,
pub redpm: Vec<Vec<f64>>,
// Red 相关 - P
pub redtp: Vec<f64>,
pub rednp: Vec<f64>,
pub redxp: Vec<f64>,
pub redmp: Vec<f64>,
pub redpp: Vec<Vec<f64>>,
// He 相关 - T
pub heit: Vec<f64>,
pub hein: Vec<f64>,
pub heim: Vec<f64>,
pub heip: Vec<Vec<f64>>,
// He 相关 - M
pub heitm: Vec<f64>,
pub heinm: Vec<f64>,
pub heimm: Vec<f64>,
pub heipm: Vec<Vec<f64>>,
// He 相关 - P
pub heitp: Vec<f64>,
pub heinp: Vec<f64>,
pub heimp: Vec<f64>,
pub heipp: Vec<Vec<f64>>,
// Ehe/Ere 相关
pub ehet: Vec<f64>,
pub ehen: Vec<f64>,
pub eret: Vec<f64>,
pub eren: Vec<f64>,
pub ehep: Vec<Vec<f64>>,
pub erep: Vec<Vec<f64>>,
// AP 相关
pub apt: Vec<Vec<f64>>,
pub apn: Vec<Vec<f64>>,
pub aapt: Vec<Vec<f64>>,
pub aapn: Vec<Vec<f64>>,
pub capt: Vec<Vec<f64>>,
pub capn: Vec<Vec<f64>>,
// APP 矩阵 (MLVEXP × MLVEXP × MDEPTH)
pub app: Vec<Vec<Vec<f64>>>,
pub aapp: Vec<Vec<Vec<f64>>>,
pub capp: Vec<Vec<Vec<f64>>>,
// 控制参数
pub qtlas: f64,
pub ifali: i32,
pub ifpopr: i32,
pub irprec: i32,
pub ifprec: i32,
pub itold1: i32,
pub itold2: i32,
pub itlas: i32,
}
impl Default for FixAlp {
fn default() -> Self {
Self {
abso: vec![0.0; MFREQ],
emis: vec![0.0; MFREQ],
scat: vec![0.0; MFREQ],
reit: vec![0.0; MDEPTH],
rein: vec![0.0; MDEPTH],
reim: vec![0.0; MDEPTH],
reip: vec![vec![0.0; MDEPTH]; MLVEXP],
areit: vec![0.0; MDEPTH],
arein: vec![0.0; MDEPTH],
areim: vec![0.0; MDEPTH],
areip: vec![vec![0.0; MDEPTH]; MLVEXP],
creit: vec![0.0; MDEPTH],
crein: vec![0.0; MDEPTH],
creim: vec![0.0; MDEPTH],
creip: vec![vec![0.0; MDEPTH]; MLVEXP],
reix: vec![0.0; MDEPTH],
creix: vec![0.0; MDEPTH],
redx: vec![0.0; MDEPTH],
redt: vec![0.0; MDEPTH],
redn: vec![0.0; MDEPTH],
redm: vec![0.0; MDEPTH],
redp: vec![vec![0.0; MDEPTH]; MLVEXP],
redxm: vec![0.0; MDEPTH],
redtm: vec![0.0; MDEPTH],
rednm: vec![0.0; MDEPTH],
redmm: vec![0.0; MDEPTH],
redpm: vec![vec![0.0; MDEPTH]; MLVEXP],
redtp: vec![0.0; MDEPTH],
rednp: vec![0.0; MDEPTH],
redxp: vec![0.0; MDEPTH],
redmp: vec![0.0; MDEPTH],
redpp: vec![vec![0.0; MDEPTH]; MLVEXP],
heit: vec![0.0; MDEPTH],
hein: vec![0.0; MDEPTH],
heim: vec![0.0; MDEPTH],
heip: vec![vec![0.0; MDEPTH]; MLVEXP],
heitm: vec![0.0; MDEPTH],
heinm: vec![0.0; MDEPTH],
heimm: vec![0.0; MDEPTH],
heipm: vec![vec![0.0; MDEPTH]; MLVEXP],
heitp: vec![0.0; MDEPTH],
heinp: vec![0.0; MDEPTH],
heimp: vec![0.0; MDEPTH],
heipp: vec![vec![0.0; MDEPTH]; MLVEXP],
ehet: vec![0.0; MDEPTH],
ehen: vec![0.0; MDEPTH],
eret: vec![0.0; MDEPTH],
eren: vec![0.0; MDEPTH],
ehep: vec![vec![0.0; MDEPTH]; MLVEX3],
erep: vec![vec![0.0; MDEPTH]; MLVEX3],
apt: vec![vec![0.0; MDEPTH]; MLVEXP],
apn: vec![vec![0.0; MDEPTH]; MLVEXP],
aapt: vec![vec![0.0; MDEPTH]; MLVEX3],
aapn: vec![vec![0.0; MDEPTH]; MLVEX3],
capt: vec![vec![0.0; MDEPTH]; MLVEX3],
capn: vec![vec![0.0; MDEPTH]; MLVEX3],
app: vec![vec![vec![0.0; MDEPTH]; MLVEXP]; MLVEXP],
aapp: vec![vec![vec![0.0; MDEPTH]; MLVEX3]; MLVEX3],
capp: vec![vec![vec![0.0; MDEPTH]; MLVEX3]; MLVEX3],
qtlas: 0.0,
ifali: 0,
ifpopr: 0,
irprec: 0,
ifprec: 0,
itold1: 0,
itold2: 0,
itlas: 0,
}
}
}
impl FixAlp {
/// 估算内存使用 (MB)
pub fn memory_usage_mb(&self) -> f64 {
// 主要数组大小估算
let freq_size = 3 * MFREQ * std::mem::size_of::<f64>();
let depth_1d = 22 * MDEPTH * std::mem::size_of::<f64>();
let depth_2d_lvexp = 17 * MLVEXP * MDEPTH * std::mem::size_of::<f64>();
let depth_2d_lvex3 = 10 * MLVEX3 * MDEPTH * std::mem::size_of::<f64>();
let depth_3d_lvexp = 3 * MLVEXP * MLVEXP * MDEPTH * std::mem::size_of::<f64>();
let depth_3d_lvex3 = 3 * MLVEX3 * MLVEX3 * MDEPTH * std::mem::size_of::<f64>();
(freq_size + depth_1d + depth_2d_lvexp + depth_2d_lvex3 + depth_3d_lvexp + depth_3d_lvex3) as f64
/ (1024.0 * 1024.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fixalp_creation() {
let fixalp = FixAlp::default();
assert_eq!(fixalp.abso.len(), MFREQ);
assert_eq!(fixalp.reit.len(), MDEPTH);
assert_eq!(fixalp.reip.len(), MLVEXP);
}
#[test]
fn test_fixalp_memory() {
let fixalp = FixAlp::default();
let mem = fixalp.memory_usage_mb();
println!("FixAlp memory usage: {:.2} MB", mem);
assert!(mem > 0.0);
}
}
+329
View File
@@ -0,0 +1,329 @@
//! 大型计算数组。
//!
//! 重构自 TLUSTY `ARRAY1.FOR` 中的 COMMON 块。
//! 包含辐射转移方程求解所需的大型矩阵和向量。
use super::constants::*;
// ============================================================================
// 主矩阵数组 (无标签 COMMON)
// ============================================================================
/// 主计算数组。
/// 对应 ARRAY1.FOR 中的无标签 COMMON 块
#[derive(Debug, Clone)]
pub struct MainArrays {
// 矩阵 (MTOT × MTOT)
/// A 矩阵
pub a: Vec<Vec<f64>>,
/// B 矩阵
pub b: Vec<Vec<f64>>,
/// C 矩阵
pub c: Vec<Vec<f64>>,
/// E 矩阵
pub e: Vec<Vec<f64>>,
// 向量 (MTOT)
/// 左向量
pub vecl: Vec<f64>,
/// Y1 向量
pub y1: Vec<f64>,
/// Y2 向量
pub y2: Vec<f64>,
// Ψ 相关向量 (MTOT)
/// Ψ 在前深度
pub psi0: Vec<f64>,
/// Ψ 在当前深度
pub psim: Vec<f64>,
/// Ψ 在后深度
pub psip: Vec<f64>,
// 辐射相关向量 (MTOT)
pub rad0: Vec<f64>,
pub radm: Vec<f64>,
pub radp: Vec<f64>,
// 频率相关数组 (MFREX)
/// FK 在前深度
pub fkm: Vec<f64>,
/// FK 在当前深度
pub fk0: Vec<f64>,
/// FK 在后深度
pub fkp: Vec<f64>,
// 吸收系数 (MFREX)
pub absom: Vec<f64>,
pub abso0: Vec<f64>,
pub absop: Vec<f64>,
// 发射系数 (MFREX)
pub emism: Vec<f64>,
pub emis0: Vec<f64>,
pub emisp: Vec<f64>,
// 散射系数 (MFREX)
pub scatm: Vec<f64>,
pub scat0: Vec<f64>,
pub scatp: Vec<f64>,
// 温度导数 (MFREX)
pub dabtm: Vec<f64>,
pub dabt0: Vec<f64>,
pub dabtp: Vec<f64>,
pub demtm: Vec<f64>,
pub demt0: Vec<f64>,
pub demtp: Vec<f64>,
// 密度导数 (MFREX)
pub dabnm: Vec<f64>,
pub dabn0: Vec<f64>,
pub dabnp: Vec<f64>,
pub demnm: Vec<f64>,
pub demn0: Vec<f64>,
pub demnp: Vec<f64>,
// 质量导数 (MFREX)
pub dabmm: Vec<f64>,
pub dabm0: Vec<f64>,
pub dabmp: Vec<f64>,
pub demmm: Vec<f64>,
pub demm0: Vec<f64>,
pub demmp: Vec<f64>,
// 深度权重 (MFREX)
pub wdepm: Vec<f64>,
pub wdep0: Vec<f64>,
pub wdepp: Vec<f64>,
// 能级相关 (MLEVEL)
/// 束缚-自由源函数 (前)
pub sbfm: Vec<f64>,
/// 束缚-自由源函数 (当前)
pub sbf0: Vec<f64>,
/// 束缚-自由源函数 (后)
pub sbfp: Vec<f64>,
/// 氦激发速率
pub hex: Vec<f64>,
/// 复合激发速率
pub rex: Vec<f64>,
pub rexa: Vec<f64>,
/// 束缚-自由导数
pub dsbfm: Vec<f64>,
pub dsbf0: Vec<f64>,
pub dsbfp: Vec<f64>,
/// 电荷求和
pub sumdch: Vec<f64>,
// 二维导数数组 (MLEVEL × MFREX)
pub drchm: Vec<Vec<f64>>,
pub dretm: Vec<Vec<f64>>,
pub drch0: Vec<Vec<f64>>,
pub dret0: Vec<Vec<f64>>,
pub drchp: Vec<Vec<f64>>,
pub dretp: Vec<Vec<f64>>,
}
impl Default for MainArrays {
fn default() -> Self {
Self {
a: vec![vec![0.0; MTOT]; MTOT],
b: vec![vec![0.0; MTOT]; MTOT],
c: vec![vec![0.0; MTOT]; MTOT],
e: vec![vec![0.0; MTOT]; MTOT],
vecl: vec![0.0; MTOT],
y1: vec![0.0; MTOT],
y2: vec![0.0; MTOT],
psi0: vec![0.0; MTOT],
psim: vec![0.0; MTOT],
psip: vec![0.0; MTOT],
rad0: vec![0.0; MTOT],
radm: vec![0.0; MTOT],
radp: vec![0.0; MTOT],
fkm: vec![0.0; MFREX],
fk0: vec![0.0; MFREX],
fkp: vec![0.0; MFREX],
absom: vec![0.0; MFREX],
abso0: vec![0.0; MFREX],
absop: vec![0.0; MFREX],
emism: vec![0.0; MFREX],
emis0: vec![0.0; MFREX],
emisp: vec![0.0; MFREX],
scatm: vec![0.0; MFREX],
scat0: vec![0.0; MFREX],
scatp: vec![0.0; MFREX],
dabtm: vec![0.0; MFREX],
dabt0: vec![0.0; MFREX],
dabtp: vec![0.0; MFREX],
demtm: vec![0.0; MFREX],
demt0: vec![0.0; MFREX],
demtp: vec![0.0; MFREX],
dabnm: vec![0.0; MFREX],
dabn0: vec![0.0; MFREX],
dabnp: vec![0.0; MFREX],
demnm: vec![0.0; MFREX],
demn0: vec![0.0; MFREX],
demnp: vec![0.0; MFREX],
dabmm: vec![0.0; MFREX],
dabm0: vec![0.0; MFREX],
dabmp: vec![0.0; MFREX],
demmm: vec![0.0; MFREX],
demm0: vec![0.0; MFREX],
demmp: vec![0.0; MFREX],
wdepm: vec![0.0; MFREX],
wdep0: vec![0.0; MFREX],
wdepp: vec![0.0; MFREX],
sbfm: vec![0.0; MLEVEL],
sbf0: vec![0.0; MLEVEL],
sbfp: vec![0.0; MLEVEL],
hex: vec![0.0; MLEVEL],
rex: vec![0.0; MLEVEL],
rexa: vec![0.0; MLEVEL],
dsbfm: vec![0.0; MLEVEL],
dsbf0: vec![0.0; MLEVEL],
dsbfp: vec![0.0; MLEVEL],
sumdch: vec![0.0; MLEVEL],
drchm: vec![vec![0.0; MFREX]; MLEVEL],
dretm: vec![vec![0.0; MFREX]; MLEVEL],
drch0: vec![vec![0.0; MFREX]; MLEVEL],
dret0: vec![vec![0.0; MFREX]; MLEVEL],
drchp: vec![vec![0.0; MFREX]; MLEVEL],
dretp: vec![vec![0.0; MFREX]; MLEVEL],
}
}
}
// ============================================================================
// EXPRAD - 扩展辐射数组
// ============================================================================
/// 扩展辐射数组。
/// 对应 COMMON /EXPRAD/
#[derive(Debug, Clone)]
pub struct ExpRad {
/// 吸收系数扩展 (频率 × 深度)
pub absoex: Vec<Vec<f64>>,
/// 发射系数扩展
pub emisex: Vec<Vec<f64>>,
/// 散射系数扩展
pub scatex: Vec<Vec<f64>>,
// 导数扩展
pub dabtex: Vec<Vec<f64>>,
pub demtex: Vec<Vec<f64>>,
pub dabcex: Vec<Vec<f64>>,
pub demnex: Vec<Vec<f64>>,
pub dabmex: Vec<Vec<f64>>,
pub demmex: Vec<Vec<f64>>,
// 能级导数扩展 (线性化能级 × 频率 × 深度)
pub drchex: Vec<Vec<Vec<f64>>>,
pub dretex: Vec<Vec<Vec<f64>>>,
}
impl Default for ExpRad {
fn default() -> Self {
Self {
absoex: vec![vec![0.0; MDEPTH]; MFREX],
emisex: vec![vec![0.0; MDEPTH]; MFREX],
scatex: vec![vec![0.0; MDEPTH]; MFREX],
dabtex: vec![vec![0.0; MDEPTH]; MFREX],
demtex: vec![vec![0.0; MDEPTH]; MFREX],
dabcex: vec![vec![0.0; MDEPTH]; MFREX],
demnex: vec![vec![0.0; MDEPTH]; MFREX],
dabmex: vec![vec![0.0; MDEPTH]; MFREX],
demmex: vec![vec![0.0; MDEPTH]; MFREX],
drchex: vec![vec![vec![0.0; MDEPTH]; MFREX]; MLVEXP],
dretex: vec![vec![vec![0.0; MDEPTH]; MFREX]; MLVEXP],
}
}
}
// ============================================================================
// BPOCOM - 束缚-占据矩阵
// ============================================================================
/// 束缚-占据矩阵。
/// 对应 COMMON /BPOCOM/
#[derive(Debug, Clone, Default)]
pub struct BpoCom {
/// 电子散射矩阵
pub esemat: Vec<Vec<f64>>,
/// 束缚-电子散射
pub bese: Vec<f64>,
/// 衰减
pub att: Vec<f64>,
/// Ann 矩阵对角
pub ann: Vec<f64>,
}
impl BpoCom {
pub fn new() -> Self {
Self {
esemat: vec![vec![0.0; MLEVEL]; MLEVEL],
bese: vec![0.0; MLEVEL],
att: vec![0.0; MLEVEL],
ann: vec![0.0; MLEVEL],
}
}
}
// ============================================================================
// 综合数组结构
// ============================================================================
/// TLUSTY 计算数组。
#[derive(Debug, Clone, Default)]
pub struct ComputeArrays {
pub main: MainArrays,
pub exprad: ExpRad,
pub bpocom: BpoCom,
}
impl ComputeArrays {
pub fn new() -> Self {
Self {
bpocom: BpoCom::new(),
..Default::default()
}
}
/// 估算内存使用量 (MB)
pub fn memory_usage_mb(&self) -> f64 {
let main_size = std::mem::size_of::<MainArrays>();
let exprad_size = std::mem::size_of::<ExpRad>();
let bpocom_size = std::mem::size_of::<BpoCom>();
(main_size + exprad_size + bpocom_size) as f64 / (1024.0 * 1024.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_main_arrays_creation() {
let arrays = MainArrays::default();
assert_eq!(arrays.a.len(), MTOT);
assert_eq!(arrays.a[0].len(), MTOT);
assert_eq!(arrays.vecl.len(), MTOT);
}
#[test]
fn test_exprad_creation() {
let exprad = ExpRad::default();
assert_eq!(exprad.absoex.len(), MFREX);
assert_eq!(exprad.absoex[0].len(), MDEPTH);
}
#[test]
fn test_compute_arrays() {
let arrays = ComputeArrays::new();
let mem = arrays.memory_usage_mb();
println!("ComputeArrays memory usage: {:.2} MB", mem);
assert!(mem > 0.0);
}
}
+422
View File
@@ -0,0 +1,422 @@
//! 原子、离子、能级数据。
//!
//! 重构自 TLUSTY `ATOMIC.FOR` 中的 COMMON 块。
use super::constants::*;
// ============================================================================
// ATOPAR - 原子参数
// ============================================================================
/// 原子参数。
/// 对应 COMMON /ATOPAR/
#[derive(Debug, Clone)]
pub struct AtoPar {
/// 原子质量
pub amass: Vec<f64>,
/// 丰度 (原子/深度点)
pub abund: Vec<Vec<f64>>,
/// 原子序数
pub numat: Vec<i32>,
/// 原子起始能级索引
pub n0a: Vec<i32>,
/// 原子终止能级索引
pub nka: Vec<i32>,
/// 参考原子
pub nref: Vec<i32>,
/// 原子提取标志
pub iatex: Vec<i32>,
/// 参考丰度 (深度点)
pub nrefs: Vec<Vec<i32>>,
/// 采用的原子
pub iadop: Vec<i32>,
/// 固定丰度标志
pub iifix: Vec<i32>,
/// 参考原子索引
pub iatref: i32,
/// 参考模型
pub modref: i32,
}
impl Default for AtoPar {
fn default() -> Self {
Self {
amass: vec![0.0; MATOM],
abund: vec![vec![0.0; MDEPTH]; MATOM],
numat: vec![0; MATOM],
n0a: vec![0; MATOM],
nka: vec![0; MATOM],
nref: vec![0; MATOM],
iatex: vec![0; MATOM],
nrefs: vec![vec![0; MDEPTH]; MATOM],
iadop: vec![0; MATOM],
iifix: vec![0; MATOM],
iatref: 0,
modref: 0,
}
}
}
// ============================================================================
// IONPAR - 离子参数
// ============================================================================
/// 离子参数。
/// 对应 COMMON /IONPAR/
#[derive(Debug, Clone)]
pub struct IonPar {
/// 电离势 (Ry)
pub ff: Vec<f64>,
/// 电荷²
pub charg2: Vec<f64>,
/// 离子起始能级索引
pub nfirst: Vec<i32>,
/// 离子终止能级索引
pub nlast: Vec<i32>,
/// 下一个能级索引
pub nnext: Vec<i32>,
/// 原子序数 Z
pub iz: Vec<i32>,
/// 上能级求和索引
pub iupsum: Vec<i32>,
/// 碰撞耦合索引
pub icup: Vec<i32>,
/// LTE 标志
pub ilte: Vec<i32>,
/// LTE 离子标志
pub iltion: Vec<i32>,
}
impl Default for IonPar {
fn default() -> Self {
Self {
ff: vec![0.0; MION],
charg2: vec![0.0; MION],
nfirst: vec![0; MION],
nlast: vec![0; MION],
nnext: vec![0; MION],
iz: vec![0; MION],
iupsum: vec![0; MION],
icup: vec![0; MION],
ilte: vec![0; MION],
iltion: vec![0; MION],
}
}
}
// ============================================================================
// LEVPAR - 能级参数
// ============================================================================
/// 能级参数。
/// 对应 COMMON /LEVPAR/
#[derive(Debug, Clone)]
pub struct LevPar {
/// 电离能 (cm⁻¹)
pub enion: Vec<f64>,
/// 统计权重 g
pub g: Vec<f64>,
/// 主量子数
pub nquant: Vec<i32>,
/// 所属原子索引
pub iatm: Vec<i32>,
/// 所属离子索引
pub iel: Vec<i32>,
/// 能级类型
pub ilk: Vec<i32>,
/// 线性化标志
pub ilin: Vec<i32>,
/// LTE 能级标志
pub iltlev: Vec<i32>,
/// 能级索引
pub indlev: Vec<i32>,
/// 模型能级
pub imodl: Vec<i32>,
/// 显式能级标志
pub iiexp: Vec<i32>,
/// Fortran 能级标志
pub iifor: Vec<i32>,
/// 零占据概率标志
pub ipzert: Vec<i32>,
/// 零 g 标志
pub igzert: Vec<i32>,
/// 零 g 能级索引
pub indlgz: Vec<i32>,
/// 非零能级标志
pub iinonz: Vec<i32>,
/// 显式能级数
pub nlvexp: i32,
/// Fortran 能级数
pub nlvfor: i32,
/// 零能级数
pub nlvexz: i32,
/// 束缚-自由 X 标志
pub lbpfx: i32,
}
impl Default for LevPar {
fn default() -> Self {
Self {
enion: vec![0.0; MLEVEL],
g: vec![0.0; MLEVEL],
nquant: vec![0; MLEVEL],
iatm: vec![0; MLEVEL],
iel: vec![0; MLEVEL],
ilk: vec![0; MLEVEL],
ilin: vec![0; MLEVEL],
iltlev: vec![0; MLEVEL],
indlev: vec![0; MLEVEL],
imodl: vec![0; MLEVEL],
iiexp: vec![0; MLEVEL],
iifor: vec![0; MLEVEL],
ipzert: vec![0; MLEVEL],
igzert: vec![0; MLEVEL],
indlgz: vec![0; MLEVEL],
iinonz: vec![0; MLEVEL],
nlvexp: 0, nlvfor: 0, nlvexz: 0, lbpfx: 0,
}
}
}
// ============================================================================
// TRAPAR - 跃迁参数
// ============================================================================
/// 跃迁参数。
/// 对应 COMMON /TRAPAR/
#[derive(Debug, Clone)]
pub struct TraPar {
/// 跃迁频率 (Hz)
pub fr0: Vec<f64>,
/// 振子强度
pub osc0: Vec<f64>,
/// 线宽参数
pub cpar: Vec<f64>,
/// 最大频率
pub frqmx: Vec<f64>,
/// 跃迁频率 (cm⁻¹)
pub fr0pc: Vec<f64>,
/// 碰撞 Ω 矩阵
pub omecol: Vec<Vec<f64>>,
// 梯度参数
pub xgrad: f64,
pub strl1: f64,
pub strl2: f64,
pub strlx: f64,
// 索引数组
/// 下能级索引
pub ilow: Vec<i32>,
/// 上能级索引
pub iup: Vec<i32>,
/// 指数索引
pub indexp: Vec<i32>,
/// 频率索引
pub kfr0: Vec<i32>,
pub kfr1: Vec<i32>,
/// Luck 跃迁标志
pub iluctr: Vec<i32>,
/// 频率计数
pub ifc0: Vec<i32>,
pub ifc1: Vec<i32>,
pub ifr0: Vec<i32>,
pub ifr1: Vec<i32>,
/// 跃迁矩阵
pub itra: Vec<Vec<i32>>,
/// 轮廓类型
pub iprof: Vec<i32>,
/// 碰撞标志
pub icol: Vec<i32>,
/// 积分模式
pub intmod: Vec<i32>,
/// 连续跃迁标志
pub itrcon: Vec<i32>,
/// 双电子标志
pub idiel: Vec<i32>,
/// 跃迁 J-T 因子
pub ijtf: Vec<i32>,
/// 复合线标志
pub lcomp: Vec<i32>,
/// 谱线索引
pub line: Vec<i32>,
}
impl Default for TraPar {
fn default() -> Self {
Self {
fr0: vec![0.0; MTRANS],
osc0: vec![0.0; MTRANS],
cpar: vec![0.0; MTRANS],
frqmx: vec![0.0; MTRANS],
fr0pc: vec![0.0; MTRANS],
omecol: vec![vec![0.0; MLEVEL]; MLEVEL],
xgrad: 0.0, strl1: 0.0, strl2: 0.0, strlx: 0.0,
ilow: vec![0; MTRANS],
iup: vec![0; MTRANS],
indexp: vec![0; MTRANS],
kfr0: vec![0; MTRANS],
kfr1: vec![0; MTRANS],
iluctr: vec![0; MTRANS],
ifc0: vec![0; MTRANS],
ifc1: vec![0; MTRANS],
ifr0: vec![0; MTRANS],
ifr1: vec![0; MTRANS],
itra: vec![vec![0; MLEVEL]; MLEVEL],
iprof: vec![0; MTRANS],
icol: vec![0; MTRANS],
intmod: vec![0; MTRANS],
itrcon: vec![0; MTRANS],
idiel: vec![0; MTRANS],
ijtf: vec![0; MTRANS],
lcomp: vec![0; MTRANS],
line: vec![0; MTRANS],
}
}
}
// ============================================================================
// PHOSET - 光电离设置
// ============================================================================
/// 光电离设置。
/// 对应 COMMON /PHOSET/
#[derive(Debug, Clone, Default)]
pub struct PhoSet {
/// 截面参数 S₀
pub s0cs: Vec<f64>,
/// 截面参数 α
pub alfcs: Vec<f64>,
/// 截面参数 β
pub betcs: Vec<f64>,
/// 截面参数 γ
pub gamcs: Vec<f64>,
/// 束缚-自由索引
pub ibf: Vec<i32>,
}
impl PhoSet {
pub fn new() -> Self {
Self {
s0cs: vec![0.0; MLEVEL],
alfcs: vec![0.0; MLEVEL],
betcs: vec![0.0; MLEVEL],
gamcs: vec![0.0; MLEVEL],
ibf: vec![0; MLEVEL],
}
}
}
// ============================================================================
// VOIPAR - Voigt 参数
// ============================================================================
/// Voigt 轮廓参数。
/// 对应 COMMON /VOIPAR/
#[derive(Debug, Clone, Default)]
pub struct VoiPar {
/// 辐射宽度 γ
pub gamar: Vec<f64>,
/// Stark 展宽参数 1
pub stark1: Vec<f64>,
/// Stark 展宽参数 2
pub stark2: Vec<f64>,
/// Stark 展宽参数 3
pub stark3: Vec<f64>,
/// van der Waals 宽度
pub vdwh: Vec<f64>,
}
impl VoiPar {
pub fn new() -> Self {
Self {
gamar: vec![0.0; MVOIGT],
stark1: vec![0.0; MVOIGT],
stark2: vec![0.0; MVOIGT],
stark3: vec![0.0; MVOIGT],
vdwh: vec![0.0; MVOIGT],
}
}
}
// ============================================================================
// HECRAT - 氦碰撞速率
// ============================================================================
/// 氦碰撞速率系数。
/// 对应 COMMON /HECRAT/
#[derive(Debug, Clone, Default)]
pub struct HeCrat {
/// 氦碰撞速率矩阵 (19×19)
pub colhe1: [[f64; 19]; 19],
}
// ============================================================================
// 综合原子数据结构
// ============================================================================
/// TLUSTY 原子数据。
/// 包含所有原子、离子、能级、跃迁信息。
#[derive(Debug, Clone, Default)]
pub struct AtomicData {
pub atopar: AtoPar,
pub ionpar: IonPar,
pub levpar: LevPar,
pub trapar: TraPar,
pub phoset: PhoSet,
pub voipar: VoiPar,
pub hecrat: HeCrat,
}
impl AtomicData {
pub fn new() -> Self {
Self {
phoset: PhoSet::new(),
voipar: VoiPar::new(),
..Default::default()
}
}
/// 获取指定能级的原子序数 Z
pub fn get_z(&self, level: usize) -> i32 {
if level < MLEVEL {
let ion_idx = self.levpar.iel[level] as usize;
if ion_idx < MION {
return self.ionpar.iz[ion_idx];
}
}
0
}
/// 获取指定能级的电离电荷
pub fn get_charge(&self, level: usize) -> f64 {
if level < MLEVEL {
let ion_idx = self.levpar.iel[level] as usize;
if ion_idx < MION {
return self.ionpar.charg2[ion_idx].sqrt();
}
}
0.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_atomic_data_creation() {
let data = AtomicData::new();
assert_eq!(data.atopar.amass.len(), MATOM);
assert_eq!(data.ionpar.ff.len(), MION);
assert_eq!(data.levpar.g.len(), MLEVEL);
}
#[test]
fn test_get_z() {
let mut data = AtomicData::new();
data.levpar.iel[0] = 1;
data.ionpar.iz[1] = 2; // He
assert_eq!(data.get_z(0), 2);
}
}
+428
View File
@@ -0,0 +1,428 @@
//! 运行时配置参数。
//!
//! 重构自 TLUSTY `BASICS.FOR` 中的控制 COMMON 块。
use super::constants::*;
// ============================================================================
// BASNUM - 基本数值计数器
// ============================================================================
/// 基本数值计数器。
/// 对应 COMMON /BASNUM/
#[derive(Debug, Clone)]
pub struct BasNum {
/// 显式原子数
pub natom: i32,
/// 显式离子数
pub nion: i32,
/// 显式能级数
pub nlevel: i32,
/// 跃迁数
pub ntrans: i32,
/// 深度点数
pub nd: i32,
/// 频率点数
pub nfreq: i32,
/// 连续谱频率数
pub nfreqc: i32,
/// 线性化频率数
pub nfreqe: i32,
// 各种选项标志
pub ioptab: i32,
pub idisk: i32,
pub izscal: i32,
pub idmfix: i32,
pub iheso6: i32,
pub ifmol: i32,
pub ifentr: i32,
pub nfreql: i32,
pub nlev0: i32,
pub icolhn: i32,
pub ioscor: i32,
pub ilgder: i32,
pub ifryb: i32,
pub ifrset: i32,
pub nfread: i32,
pub nelsc: i32,
pub ntranc: i32,
pub iover: i32,
pub jali: i32,
pub ibc: i32,
pub iubc: i32,
pub intens: i32,
pub irder: i32,
pub ilmcor: i32,
pub ifdiel: i32,
pub ifalih: i32,
pub iftene: i32,
pub itndre: i32,
pub ilpsct: i32,
pub ilasct: i32,
pub irte: i32,
pub idlte: i32,
pub ibfint: i32,
pub intrpl: i32,
pub ichang: i32,
pub natoms: i32,
pub ipslte: i32,
pub ispodf: i32,
pub itlucy: i32,
pub nretc: i32,
pub ifrayl: i32,
pub ifprad: i32,
}
impl Default for BasNum {
fn default() -> Self {
Self {
natom: 0, nion: 0, nlevel: 0, ntrans: 0,
nd: 0, nfreq: 0, nfreqc: 0, nfreqe: 0,
ioptab: 0, idisk: 0, izscal: 0, idmfix: 0,
iheso6: 0, ifmol: 0, ifentr: 0, nfreql: 0,
nlev0: 0, icolhn: 0, ioscor: 0, ilgder: 0,
ifryb: 0, ifrset: 0, nfread: 0, nelsc: 0,
ntranc: 0, iover: 0, jali: 0, ibc: 0,
iubc: 0, intens: 0, irder: 0, ilmcor: 0,
ifdiel: 0, ifalih: 0, iftene: 0, itndre: 0,
ilpsct: 0, ilasct: 0, irte: 0, idlte: 0,
ibfint: 0, intrpl: 0, ichang: 0, natoms: 0,
ipslte: 0, ispodf: 0, itlucy: 0, nretc: 0,
ifrayl: 0, ifprad: 0,
}
}
}
// ============================================================================
// INPPAR - 输入参数
// ============================================================================
/// 输入参数。
/// 对应 COMMON /INPPAR/
#[derive(Debug, Clone)]
pub struct InpPar {
/// 有效温度 (K)
pub teff: f64,
/// 表面重力 (cm/s²)
pub grav: f64,
/// 总 He 丰度 (质量分数)
pub ytot: Vec<f64>,
/// 平均分子量
pub wmm: Vec<f64>,
/// He 质量分数
pub wmy: Vec<f64>,
/// 分子温度极限
pub tmolim: f64,
// 恒星风参数
pub xmstar: f64,
pub xmdot: f64,
pub rstar: f64,
pub alpha0: f64,
pub reynum: f64,
// 引力相关
pub qgrav: f64,
pub edisc: f64,
pub dzeta: f64,
pub reldst: f64,
// 粘性参数
pub visc: f64,
pub zeta0: f64,
pub zeta1: f64,
pub dmvisc: f64,
pub fractv: f64,
// 自转参数
pub omeg32: f64,
pub wbarm: f64,
pub wbar: f64,
pub alphav: f64,
pub pgas0: f64,
// 控制参数
pub bergfc: f64, // β 引力因子 (wn.f 使用)
pub cutlym: f64,
pub cutbal: f64,
// 选项标志
pub isplin: i32,
pub irsplt: i32,
pub ivisc: i32,
pub ibche: i32,
pub lte: bool,
pub ltgrey: bool,
pub lchc: bool,
pub lresc: bool,
}
impl InpPar {
pub fn new() -> Self {
Self {
teff: 10000.0,
grav: 4.44, // log g = 4.44 (太阳)
ytot: vec![0.0; MDEPTH],
wmm: vec![0.0; MDEPTH],
wmy: vec![0.0; MDEPTH],
tmolim: 0.0,
xmstar: 0.0, xmdot: 0.0, rstar: 0.0, alpha0: 0.0, reynum: 0.0,
qgrav: 0.0, edisc: 0.0, dzeta: 0.0, reldst: 0.0,
visc: 0.0, zeta0: 0.0, zeta1: 0.0, dmvisc: 0.0, fractv: 0.0,
omeg32: 0.0, wbarm: 0.0, wbar: 0.0, alphav: 0.0, pgas0: 0.0,
bergfc: 1.0, // 默认值
cutlym: 0.0, cutbal: 0.0,
isplin: 0, irsplt: 0, ivisc: 0, ibche: 0,
lte: false, ltgrey: false, lchc: false, lresc: false,
}
}
}
impl Default for InpPar {
fn default() -> Self {
Self::new()
}
}
// ============================================================================
// MATKEY - 材料键
// ============================================================================
/// 材料键。
/// 对应 COMMON /MATKEY/
#[derive(Debug, Clone, Default)]
pub struct MatKey {
pub nn: i32,
pub nn0: i32,
pub inhe: i32,
pub inre: i32,
pub inpc: i32,
pub inse: i32,
pub inzd: i32,
pub inmp: i32,
pub ndre: i32,
pub insel: i32,
}
// ============================================================================
// RUNKEY - 运行控制
// ============================================================================
/// 运行控制键。
/// 对应 COMMON /RUNKEY/
#[derive(Debug, Clone, Default)]
pub struct RunKey {
pub chmax: f64,
pub iter: i32,
pub niter: i32,
pub nitzer: i32,
pub init: i32,
pub lac2: i32,
pub lfin: i32,
}
// ============================================================================
// CONKEY - 收敛控制
// ============================================================================
/// 收敛控制键。
/// 对应 COMMON /CONKEY/
#[derive(Debug, Clone, Default)]
pub struct ConKey {
pub hmix0: f64,
pub crflim: f64,
pub nconit: i32,
pub iconv: i32,
pub indl: i32,
pub ipress: i32,
pub itemp: i32,
pub icbeg: i32,
pub itmcor: i32,
pub iconre: i32,
pub ideepc: i32,
pub ndcgap: i32,
pub idconz: i32,
}
// ============================================================================
// OPCPAR - 额外不透明度控制
// ============================================================================
/// 额外不透明度控制。
/// 对应 COMMON /OPCPAR/
#[derive(Debug, Clone, Default)]
pub struct OpcPar {
pub iophmi: i32, // H⁻
pub ioph2p: i32, // H₂⁺
pub iophem: i32, // He⁻
pub iopch: i32, // CH
pub iopoh: i32, // OH
pub ioph2m: i32, // H₂⁻
pub ioh2h2: i32, // H₂-H₂ CIA
pub ioh2he: i32, // H₂-He CIA
pub ioh2h: i32, // H₂-H CIA
pub iohhe: i32, // H-He CIA
pub iophli: i32, // H⁻ 自由-自由
pub irsct: i32, // 汤姆逊散射
pub irsche: i32, // He 散射
pub irsch2: i32, // H₂ 散射
pub keepop: i32,
pub iopold: i32,
}
// ============================================================================
// PRINTS - 打印控制
// ============================================================================
/// 打印控制。
/// 对应 COMMON /PRINTS/
#[derive(Debug, Clone, Default)]
pub struct Prints {
pub iprint: i32,
pub ipring: i32,
pub iprind: i32,
pub iprinp: i32,
pub icoolp: i32,
pub ichckp: i32,
pub ipopac: i32,
pub iprini: i32,
}
// ============================================================================
// ANGLES - 角度设置
// ============================================================================
/// 角度设置。
/// 对应 COMMON /ANGLES/
#[derive(Debug, Clone)]
pub struct Angles {
/// 角度余弦值
pub amu: Vec<f64>,
/// 角度权重
pub wtmu: Vec<f64>,
/// 角度函数
pub fmu: Vec<f64>,
/// 角度点数
pub nmu: i32,
}
impl Default for Angles {
fn default() -> Self {
Self {
amu: vec![0.0; MMU],
wtmu: vec![0.0; MMU],
fmu: vec![0.0; MMU],
nmu: 0,
}
}
}
// ============================================================================
// COMPTN - Compton 散射角度参数
// ============================================================================
/// Compton 散射角度参数。
/// 对应 COMMON /COMPTN/ 和 /ANGNUM/
#[derive(Debug, Clone)]
pub struct Comptn {
/// 角度余弦值
pub amuc: Vec<f64>,
/// 角度权重
pub wtmuc: Vec<f64>,
/// amuc * wtmuc
pub amuc1: Vec<f64>,
/// amuc² * wtmuc
pub amuc2: Vec<f64>,
/// amuc³ * wtmuc
pub amuc3: Vec<f64>,
/// 角度相关量
pub amuj: Vec<f64>,
pub amuk: Vec<f64>,
pub amuh: Vec<f64>,
pub amun: Vec<f64>,
/// Compton 散射 α 系数
pub calph: Vec<Vec<f64>>,
/// Compton 散射 β 系数
pub cbeta: Vec<Vec<f64>>,
/// Compton 散射 γ 系数
pub cgamm: Vec<Vec<f64>>,
/// 辐射零点
pub radzer: f64,
/// Compton 频率
pub frlcom: f64,
/// Compton 截面
pub sigec: Vec<f64>,
/// 原始频率索引
pub ijorig: Vec<i32>,
/// Compton 角度点数
pub nmuc: i32,
}
impl Default for Comptn {
fn default() -> Self {
Self {
amuc: vec![0.0; MMUC],
wtmuc: vec![0.0; MMUC],
amuc1: vec![0.0; MMUC],
amuc2: vec![0.0; MMUC],
amuc3: vec![0.0; MMUC],
amuj: vec![0.0; MMUC],
amuk: vec![0.0; MMUC],
amuh: vec![0.0; MMUC],
amun: vec![0.0; MMUC],
calph: vec![vec![0.0; MMUC]; MMUC],
cbeta: vec![vec![0.0; MMUC]; MMUC],
cgamm: vec![vec![0.0; MMUC]; MMUC],
radzer: 0.0,
frlcom: 0.0,
sigec: vec![0.0; MFREQ],
ijorig: vec![0; MFREQ],
nmuc: 0,
}
}
}
// ============================================================================
// 综合配置结构
// ============================================================================
/// TLUSTY 综合配置。
/// 包含所有控制参数。
#[derive(Debug, Clone, Default)]
pub struct TlustyConfig {
pub basnum: BasNum,
pub inppar: InpPar,
pub matkey: MatKey,
pub runkey: RunKey,
pub conkey: ConKey,
pub opcpar: OpcPar,
pub prints: Prints,
pub angles: Angles,
pub comptn: Comptn,
}
impl TlustyConfig {
pub fn new() -> Self {
Self::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_creation() {
let config = TlustyConfig::new();
assert_eq!(config.basnum.natom, 0);
assert_eq!(config.inppar.teff, 10000.0);
}
#[test]
fn test_inppar_arrays() {
let inppar = InpPar::new();
assert_eq!(inppar.ytot.len(), MDEPTH);
}
}
+164
View File
@@ -0,0 +1,164 @@
//! 物理常数和维度参数。
//!
//! 重构自 TLUSTY `BASICS.FOR` 中的 PARAMETER 定义。
// ============================================================================
// 维度参数 (数组大小)
// ============================================================================
/// 最大原子数
pub const MATOM: usize = 99;
/// 最大离子数
pub const MION: usize = 170;
/// 最大能级数
pub const MLEVEL: usize = 1134;
/// 最大线性化能级数
pub const MLVEXP: usize = 233;
/// 最大跃迁数
pub const MTRANS: usize = 21000;
/// 最大深度点数
pub const MDEPTH: usize = 100;
/// 最大频率点数
pub const MFREQ: usize = 135000;
/// 工作频率数组大小
pub const MFREQP: usize = 220000;
/// 连续谱频率点数
pub const MFREQC: usize = 125000;
/// 线性化频率数
pub const MFREX: usize = 54;
/// 每条谱线频率数
pub const MFREQL: usize = 25798;
/// 最大线性化参数数
pub const MTOT: usize = 280;
/// 最大角度点数
pub const MMU: usize = 6;
/// Compton 散射最大角度点数
pub const MMUC: usize = 2;
/// 光电离截面拟合点数
pub const MFIT: usize = 357;
/// 重叠跃迁数
pub const MITJ: usize = 380;
/// 伪连续能级数
pub const MMCDW: usize = 26;
/// 合并能级数
pub const MMER: usize = 12;
/// Voigt 轮廓谱线数
pub const MVOIGT: usize = 8080;
/// 占据概率离子最大电荷
pub const MZZ: usize = 10;
/// 最高氢能级
pub const NLMX: usize = 80;
/// 对角预处理能级数
pub const MLEVE3: usize = 1;
/// 对角/三对角操作能级数
pub const MLVEX3: usize = 1;
/// 对角/三对角操作跃迁数
pub const MTRAN3: usize = 1;
/// 光电离截面数
pub const MCROSS: usize = MLEVEL + 5;
/// 束缚-自由跃迁数
pub const MBF: usize = MLEVEL;
// ============================================================================
// 物理常数 (CGS 单位)
// ============================================================================
/// 普朗克常数 h (erg·s)
pub const H: f64 = 6.6256e-27;
/// 玻尔兹曼常数 k (erg/K)
pub const BOLK: f64 = 1.38054e-16;
/// h/k (s·K)
pub const HK: f64 = 4.79928144e-11;
/// 光速 c (Å/s)
pub const CAS: f64 = 2.997925e18;
/// 氢电离能 (erg)
pub const EH: f64 = 2.17853041e-11;
/// 2*h/c³
pub const BN: f64 = 1.4743e-2;
/// 汤姆逊散射截面 (cm²)
pub const SIGE: f64 = 6.6516e-25;
/// 斯特藩-玻尔兹曼常数/4π
pub const SIG4P: f64 = 4.5114062e-6;
/// 4π/h
pub const PI4H: f64 = 1.8966e27;
/// 4π/c
pub const PCK: f64 = 4.19168946e-10;
/// 氢原子质量 (g)
pub const HMASS: f64 = 1.67333e-24;
// ============================================================================
// 数学常数
// ============================================================================
/// 单位 1
pub const UN: f64 = 1.0;
/// 二分之一
pub const HALF: f64 = 0.5;
/// 二
pub const TWO: f64 = 2.0;
/// π
pub const PI: f64 = std::f64::consts::PI;
/// 2π
pub const TWOPI: f64 = 2.0 * std::f64::consts::PI;
/// 4π
pub const FOURPI: f64 = 4.0 * std::f64::consts::PI;
/// ln(10)
pub const LN10: f64 = std::f64::consts::LN_10;
// ============================================================================
// 辅助函数
// ============================================================================
/// 安全指数函数,避免溢出。
/// 重构自 TLUSTY `expo.f`
#[inline]
pub fn expo(x: f64) -> f64 {
const MAX_EXP: f64 = 700.0;
if x > MAX_EXP {
(MAX_EXP).exp()
} else if x < -MAX_EXP {
0.0
} else {
x.exp()
}
}
/// 安全对数函数,避免 log(0)。
#[inline]
pub fn safe_log(x: f64) -> f64 {
if x <= 0.0 {
f64::NEG_INFINITY
} else {
x.ln()
}
}
/// 安全对数10函数。
#[inline]
pub fn safe_log10(x: f64) -> f64 {
if x <= 0.0 {
f64::NEG_INFINITY
} else {
x.log10()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expo() {
assert!((expo(0.0) - 1.0).abs() < 1e-15);
assert!((expo(1.0) - std::f64::consts::E).abs() < 1e-15);
assert_eq!(expo(-1000.0), 0.0);
assert!(expo(1000.0).is_finite());
}
#[test]
fn test_constants() {
assert!(H > 0.0);
assert!(BOLK > 0.0);
assert!(CAS > 0.0);
}
}
+246
View File
@@ -0,0 +1,246 @@
//! 迭代控制参数。
//!
//! 重构自 TLUSTY `ITERAT.FOR`
use super::constants::*;
// ============================================================================
// 迭代参数维度
// ============================================================================
/// 最大迭代次数
pub const MITER: usize = 200;
/// 最大 Lambda 点数
pub const MLAMBD: usize = 100;
// ============================================================================
// LAMBDA - Lambda 迭代参数
// ============================================================================
/// Lambda 迭代控制。
/// 对应 COMMON /LAMBDA/
#[derive(Debug, Clone, Default)]
pub struct Lambda {
/// Lambda 点数
pub nlambd: i32,
/// 固定频率标志
pub iffix: Vec<i32>,
/// 显式净跃迁
pub netexp: Vec<i32>,
/// 固定净跃迁
pub netfix: Vec<i32>,
/// 显式能级跃迁
pub ietexp: Vec<Vec<i32>>,
/// 固定能级跃迁
pub ietfix: Vec<Vec<i32>>,
/// Lambda 索引
pub nitlam: Vec<i32>,
/// 能级修正标志
pub ielcor: i32,
}
impl Lambda {
pub fn new() -> Self {
Self {
nlambd: 0,
iffix: vec![0; MITER],
netexp: vec![0; MITER],
netfix: vec![0; MITER],
ietexp: vec![vec![0; MLAMBD]; MITER],
ietfix: vec![vec![0; MLAMBD]; MITER],
nitlam: vec![0; MITER + 1],
ielcor: 0,
}
}
}
// ============================================================================
// CHNMAT - 材料变化控制
// ============================================================================
/// 材料变化控制。
/// 对应 COMMON /CHNMAT/
#[derive(Debug, Clone, Default)]
pub struct ChnMat {
/// He 变化索引
pub inhe0: Vec<i32>,
/// 辐射变化索引
pub inre0: Vec<i32>,
/// PC 变化索引
pub inpc0: Vec<i32>,
/// 深度变化索引
pub indl0: Vec<i32>,
/// SE 变化索引
pub inse0: Vec<i32>,
/// MP 变化索引
pub inmp0: Vec<i32>,
/// NN 变化
pub nn00: Vec<i32>,
/// 深度修正
pub ndre0: Vec<i32>,
/// 材料变化标志
pub lchmat: i32,
/// 辐射存储
pub lirost: i32,
}
impl ChnMat {
pub fn new() -> Self {
Self {
inhe0: vec![0; MITER],
inre0: vec![0; MITER],
inpc0: vec![0; MITER],
indl0: vec![0; MITER],
inse0: vec![0; MITER],
inmp0: vec![0; MITER],
nn00: vec![0; MITER],
ndre0: vec![0; MITER],
lchmat: 0,
lirost: 0,
}
}
}
// ============================================================================
// ACCEL - 加速参数
// ============================================================================
/// 加速收敛参数。
/// 对应 COMMON /ACCEL/
#[derive(Debug, Clone, Default)]
pub struct Accel {
/// 过松弛因子
pub orelax: f64,
/// 迭代计数
pub itek: i32,
/// 加速标志
pub iacc: i32,
/// 初始加速
pub iacc0: i32,
/// 加速方向
pub iacd: i32,
/// Kantorovich 向量
pub kant: Vec<i32>,
/// 奇异点计数
pub ksng: i32,
/// 奇异点位置
pub lsng: Vec<i32>,
/// Aitken 步
pub laso: i32,
/// 重启动标志
pub lres2: i32,
}
impl Accel {
pub fn new() -> Self {
Self {
orelax: 1.0,
itek: 0,
iacc: 0,
iacc0: 0,
iacd: 0,
kant: vec![0; MITER],
ksng: 0,
lsng: vec![0; MTOT],
laso: 0,
lres2: 0,
}
}
}
// ============================================================================
// ACCLP - 加速 Lambda 参数
// ============================================================================
/// 加速 Lambda 迭代参数。
/// 对应 COMMON /ACCLP/
#[derive(Debug, Clone, Default)]
pub struct Acclp {
pub ilam: i32,
pub iacpp: i32,
pub iacc0p: i32,
pub iacdp: i32,
pub lac2p: i32,
}
// ============================================================================
// ACCLT - 温度加速
// ============================================================================
/// 温度加速参数。
/// 对应 COMMON /ACCLT/
#[derive(Debug, Clone, Default)]
pub struct Acclt {
pub iaclt: i32,
pub iacldt: i32,
}
// ============================================================================
// CHNAD - 变化附加
// ============================================================================
/// 变化附加参数。
/// 对应 COMMON /CHNAD/
#[derive(Debug, Clone, Default)]
pub struct ChnAd {
/// 最大变化
pub chmaxt: f64,
/// Lambda 计数
pub nlamt: i32,
/// 导数标志
pubilder: i32,
/// BPOP 标志
pub ibpope: i32,
}
// ============================================================================
// 综合迭代控制
// ============================================================================
/// TLUSTY 迭代控制。
#[derive(Debug, Clone, Default)]
pub struct IterControl {
pub lambda: Lambda,
pub chnmat: ChnMat,
pub accel: Accel,
pub acclp: Acclp,
pub acclt: Acclt,
pub chnad: ChnAd,
}
impl IterControl {
pub fn new() -> Self {
Self {
lambda: Lambda::new(),
chnmat: ChnMat::new(),
accel: Accel::new(),
..Default::default()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lambda_creation() {
let lambda = Lambda::new();
assert_eq!(lambda.iffix.len(), MITER);
assert_eq!(lambda.ietexp.len(), MITER);
assert_eq!(lambda.nitlam.len(), MITER + 1);
}
#[test]
fn test_accel_creation() {
let accel = Accel::new();
assert_eq!(accel.kant.len(), MITER);
assert_eq!(accel.lsng.len(), MTOT);
}
#[test]
fn test_iter_control() {
let ctrl = IterControl::new();
assert_eq!(ctrl.lambda.nlambd, 0);
}
}
+32
View File
@@ -0,0 +1,32 @@
//! TLUSTY 状态管理模块。
//!
//! 将 Fortran COMMON 块转换为 Rust struct。
//!
//! # 模块结构
//!
//! - `constants`: 物理和数学常数 (compile-time)
//! - `config`: 运行时配置参数
//! - `atomic`: 原子/离子/能级数据
//! - `model`: 大气模型状态
//! - `arrays`: 大型计算数组
//! - `iterat`: 迭代控制参数
//! - `alipar`: ALI (加速 Lambda 迭代) 数组
//! - `odfpar`: ODF (不透明度分布函数) 数据
pub mod constants;
pub mod config;
pub mod atomic;
pub mod model;
pub mod arrays;
pub mod iterat;
pub mod alipar;
pub mod odfpar;
pub use constants::*;
pub use config::*;
pub use atomic::*;
pub use model::*;
pub use arrays::*;
pub use iterat::*;
pub use alipar::*;
pub use odfpar::*;
+524
View File
@@ -0,0 +1,524 @@
//! 大气模型状态。
//!
//! 重构自 TLUSTY `MODELQ.FOR` 中的 COMMON 块。
//! 包含温度、密度、电子密度、占据数等物理状态。
use super::constants::*;
// ============================================================================
// MODPAR - 模型参数
// ============================================================================
/// 模型基本参数。
/// 对应 COMMON /MODPAR/
#[derive(Debug, Clone)]
pub struct ModPar {
/// 深度 (柱质量密度, g/cm²)
pub dm: Vec<f64>,
/// 温度 (K)
pub temp: Vec<f64>,
/// 电子密度 (cm⁻³)
pub elec: Vec<f64>,
/// 总粒子密度 (cm⁻³)
pub dens: Vec<f64>,
/// 总粒子数
pub totn: Vec<f64>,
/// 总原子密度
pub anto: Vec<f64>,
/// 金属原子密度
pub anma: Vec<f64>,
/// 中性氢密度
pub anh1: Vec<f64>,
/// 深度变量
pub zd: Vec<f64>,
// 辅助温度量
/// h/kT
pub hkt1: Vec<f64>,
/// 1/T
pub tk1: Vec<f64>,
/// h/(kT)²
pub hkt21: Vec<f64>,
/// sqrt(T)
pub sqt1: Vec<f64>,
// 迭代中间量
pub temp1: Vec<f64>,
pub elec1: Vec<f64>,
pub dens1: Vec<f64>,
pub densi: Vec<f64>,
pub densim: Vec<f64>,
// 散射相关
/// 电子散射不透明度
pub elscat: Vec<f64>,
/// 线性化辐射参数
pub alab: Vec<f64>,
// 深度差分
pub deldm: Vec<f64>,
pub dedm1: f64,
pub deldmz: Vec<f64>,
// 速度场
pub thetav: Vec<f64>,
pub viscd: Vec<f64>,
pub dalpmx: f64,
pub xhyd: f64,
// 全局量
pub dmtot: f64,
pub rrdil: f64,
pub tempbd: f64,
pub alptav: f64,
pub alpgav: f64,
pub nalp: i32,
pub ibeta: i32,
}
impl Default for ModPar {
fn default() -> Self {
Self {
dm: vec![0.0; MDEPTH],
temp: vec![0.0; MDEPTH],
elec: vec![0.0; MDEPTH],
dens: vec![0.0; MDEPTH],
totn: vec![0.0; MDEPTH],
anto: vec![0.0; MDEPTH],
anma: vec![0.0; MDEPTH],
anh1: vec![0.0; MDEPTH],
zd: vec![0.0; MDEPTH],
hkt1: vec![0.0; MDEPTH],
tk1: vec![0.0; MDEPTH],
hkt21: vec![0.0; MDEPTH],
sqt1: vec![0.0; MDEPTH],
temp1: vec![0.0; MDEPTH],
elec1: vec![0.0; MDEPTH],
dens1: vec![0.0; MDEPTH],
densi: vec![0.0; MDEPTH],
densim: vec![0.0; MDEPTH],
elscat: vec![0.0; MDEPTH],
alab: vec![0.0; MDEPTH],
deldm: vec![0.0; MDEPTH],
dedm1: 0.0,
deldmz: vec![0.0; MDEPTH],
thetav: vec![0.0; MDEPTH],
viscd: vec![0.0; MDEPTH],
dalpmx: 0.0,
xhyd: 0.0,
dmtot: 0.0,
rrdil: 0.0,
tempbd: 0.0,
alptav: 0.0,
alpgav: 0.0,
nalp: 0,
ibeta: 0,
}
}
}
// ============================================================================
// LEVPOP - 能级占据数
// ============================================================================
/// 能级占据数。
/// 对应 COMMON /LEVPOP/
#[derive(Debug, Clone)]
pub struct LevPop {
/// 占据数 (能级 × 深度)
pub popul: Vec<Vec<f64>>,
/// Boltzmann 因子
pub bfac: Vec<Vec<f64>>,
/// 逆占据数
pub popinv: Vec<Vec<f64>>,
/// 当前深度占据数
pub popgrp: Vec<f64>,
pub pop: Vec<f64>,
/// 束缚-自由源函数
pub sbf: Vec<f64>,
pub dsbf: Vec<f64>,
/// 离子配分函数
pub usum: Vec<f64>,
}
impl Default for LevPop {
fn default() -> Self {
Self {
popul: vec![vec![0.0; MDEPTH]; MLEVEL],
bfac: vec![vec![0.0; MDEPTH]; MLEVEL],
popinv: vec![vec![0.0; MDEPTH]; MLEVEL],
popgrp: vec![0.0; MLEVEL],
pop: vec![0.0; MLEVEL],
sbf: vec![0.0; MLEVEL],
dsbf: vec![0.0; MLEVEL],
usum: vec![0.0; MION],
}
}
}
// ============================================================================
// GFFPAR - 自由-自由 Gaunt 因子
// ============================================================================
/// 自由-自由 Gaunt 因子参数。
/// 对应 COMMON /GFFPAR/
#[derive(Debug, Clone, Default)]
pub struct GffPar {
/// Gaunt 因子 (深度)
pub gf0: Vec<f64>,
pub gf1: Vec<f64>,
pub gf2: Vec<f64>,
pub gf3: Vec<f64>,
pub gf4: Vec<f64>,
pub gf5: Vec<f64>,
pub gf6: Vec<f64>,
/// Gaunt 因子导数
pub gf0d: Vec<f64>,
pub gf1d: Vec<f64>,
pub gf2d: Vec<f64>,
pub gf3d: Vec<f64>,
pub gf4d: Vec<f64>,
pub gf5d: Vec<f64>,
pub gf6d: Vec<f64>,
/// 温度步长
pub deltt: Vec<f64>,
}
impl GffPar {
pub fn new() -> Self {
Self {
gf0: vec![0.0; MDEPTH],
gf1: vec![0.0; MDEPTH],
gf2: vec![0.0; MDEPTH],
gf3: vec![0.0; MDEPTH],
gf4: vec![0.0; MDEPTH],
gf5: vec![0.0; MDEPTH],
gf6: vec![0.0; MDEPTH],
gf0d: vec![0.0; MDEPTH],
gf1d: vec![0.0; MDEPTH],
gf2d: vec![0.0; MDEPTH],
gf3d: vec![0.0; MDEPTH],
gf4d: vec![0.0; MDEPTH],
gf5d: vec![0.0; MDEPTH],
gf6d: vec![0.0; MDEPTH],
deltt: vec![0.0; MDEPTH],
}
}
}
// ============================================================================
// TOTRAD - 总辐射场
// ============================================================================
/// 总辐射场。
/// 对应 COMMON /TOTRAD/
#[derive(Debug, Clone)]
pub struct TotRad {
/// 辐射强度 (频率 × 深度)
pub rad: Vec<Vec<f64>>,
/// 频率相关深度
pub fhd: Vec<f64>,
/// 吸收系数 × 辐射
pub fak: Vec<Vec<f64>>,
pub radk: Vec<Vec<f64>>,
/// 外辐射
pub extrad: Vec<f64>,
/// 外辐射强度 (频率 × 角度)
pub extint: Vec<Vec<f64>>,
/// 氦外辐射
pub hextrd: Vec<f64>,
// 全局量
pub trad: f64,
pub wdil: f64,
pub extot: f64,
pub tstar: f64,
}
impl Default for TotRad {
fn default() -> Self {
Self {
rad: vec![vec![0.0; MDEPTH]; MFREQ],
fhd: vec![0.0; MFREQ],
fak: vec![vec![0.0; MDEPTH]; MFREQ],
radk: vec![vec![0.0; MDEPTH]; MFREQ],
extrad: vec![0.0; MFREQ],
extint: vec![vec![0.0; MMU]; MFREQ],
hextrd: vec![0.0; MFREQ],
trad: 0.0,
wdil: 0.0,
extot: 0.0,
tstar: 0.0,
}
}
}
// ============================================================================
// CURRAD - 当前深度辐射
// ============================================================================
/// 当前深度辐射。
/// 对应 COMMON /CURRAD/
#[derive(Debug, Clone, Default)]
pub struct CurRad {
pub rad1: Vec<f64>,
pub ali1: Vec<f64>,
pub fak1: Vec<f64>,
pub radcm: Vec<Vec<f64>>,
pub radl: Vec<Vec<f64>>,
pub absali: Vec<Vec<f64>>,
pub alih1: Vec<f64>,
}
impl CurRad {
pub fn new() -> Self {
Self {
rad1: vec![0.0; MDEPTH],
ali1: vec![0.0; MDEPTH],
fak1: vec![0.0; MDEPTH],
radcm: vec![vec![0.0; MDEPTH]; MFREQ],
radl: vec![vec![0.0; MDEPTH]; MFREQL],
absali: vec![vec![0.0; MDEPTH]; MFREQL],
alih1: vec![0.0; MDEPTH],
}
}
}
// ============================================================================
// FRQALL - 频率相关数组
// ============================================================================
/// 频率相关数组。
/// 对应 COMMON /FRQALL/
#[derive(Debug, Clone)]
pub struct FrqAll {
/// 频率网格 (Hz)
pub freq: Vec<f64>,
/// 频率权重
pub w: Vec<f64>,
/// 谱线轮廓
pub prof: Vec<f64>,
/// 谱线权重
pub wch: Vec<f64>,
// 索引数组
pub jik: Vec<i32>,
pub ijx: Vec<i32>,
pub ijbf: Vec<i32>,
pub ifs0: i32,
pub kij: Vec<i32>,
pub lskip: Vec<Vec<i32>>,
}
impl Default for FrqAll {
fn default() -> Self {
Self {
freq: vec![0.0; MFREQ],
w: vec![0.0; MFREQ],
prof: vec![0.0; MFREQP],
wch: vec![0.0; MFREQ],
jik: vec![0; MFREQ],
ijx: vec![0; MFREQ],
ijbf: vec![0; MFREQ],
ifs0: 0,
kij: vec![0; MFREQ],
lskip: vec![vec![0; MFREQ]; MDEPTH],
}
}
}
// ============================================================================
// TOTPRF - 总谱线轮廓
// ============================================================================
/// 谱线轮廓数组。
/// 对应 COMMON /TOTPRF/
#[derive(Debug, Clone, Default)]
pub struct TotPrf {
/// 谱线轮廓 (深度 × 频率)
pub prflin: Vec<Vec<f32>>,
}
impl TotPrf {
pub fn new() -> Self {
Self {
prflin: vec![vec![0.0; MFREQP]; MDEPTH],
}
}
}
// ============================================================================
// PHOEXP - 光电离截面展开
// ============================================================================
/// 光电离截面展开参数。
/// 对应 COMMON /PHOEXP/
#[derive(Debug, Clone, Default)]
pub struct PhoExp {
/// 频率插值系数
pub aijbf: Vec<f64>,
/// 束缚-自由截面 (MCROSS × MFREQC)
pub bfcs: Vec<Vec<f32>>,
/// 频率索引
pub ifreqb: Vec<i32>,
}
impl PhoExp {
pub fn new() -> Self {
Self {
aijbf: vec![0.0; MFREQ],
bfcs: vec![vec![0.0; MFREQC]; MCROSS],
ifreqb: vec![0; MFREQC],
}
}
}
// ============================================================================
// OBFPAR - 束缚-自由跃迁参数
// ============================================================================
/// 束缚-自由跃迁参数。
/// 对应 COMMON /OBFPAR/
#[derive(Debug, Clone, Default)]
pub struct ObfPar {
/// 束缚-自由跃迁对应的跃迁索引
pub itrbf: Vec<i32>,
}
impl ObfPar {
pub fn new() -> Self {
Self {
itrbf: vec![0; MBF],
}
}
}
// ============================================================================
// LEVADD - 能级附加数组
// ============================================================================
/// 能级附加数组。
/// 对应 COMMON /LEVADD/
#[derive(Debug, Clone, Default)]
pub struct LevAdd {
/// 离子配分函数和 (离子 × 深度)
pub usums: Vec<Vec<f64>>,
/// 配分函数温度导数
pub dusmt: Vec<Vec<f64>>,
/// 配分函数密度导数
pub dusmn: Vec<Vec<f64>>,
/// 双电子复合截面 (离子 × 深度)
pub diesig: Vec<Vec<f64>>,
}
impl LevAdd {
pub fn new() -> Self {
Self {
usums: vec![vec![0.0; MDEPTH]; MION],
dusmt: vec![vec![0.0; MDEPTH]; MION],
dusmn: vec![vec![0.0; MDEPTH]; MION],
diesig: vec![vec![0.0; MDEPTH]; MION],
}
}
}
// ============================================================================
// 综合模型状态
// ============================================================================
/// TLUSTY 大气模型状态。
#[derive(Debug, Clone, Default)]
pub struct ModelState {
pub modpar: ModPar,
pub levpop: LevPop,
pub gffpar: GffPar,
pub totrad: TotRad,
pub currad: CurRad,
pub frqall: FrqAll,
pub totprf: TotPrf,
pub phoexp: PhoExp,
pub obfpar: ObfPar,
pub levadd: LevAdd,
}
impl ModelState {
pub fn new() -> Self {
Self {
gffpar: GffPar::new(),
currad: CurRad::new(),
totprf: TotPrf::new(),
phoexp: PhoExp::new(),
obfpar: ObfPar::new(),
levadd: LevAdd::new(),
..Default::default()
}
}
/// 获取指定深度的温度
pub fn temperature(&self, depth: usize) -> f64 {
if depth < MDEPTH {
self.modpar.temp[depth]
} else {
0.0
}
}
/// 获取指定深度的电子密度
pub fn electron_density(&self, depth: usize) -> f64 {
if depth < MDEPTH {
self.modpar.elec[depth]
} else {
0.0
}
}
/// 获取指定深度的总粒子密度
pub fn total_density(&self, depth: usize) -> f64 {
if depth < MDEPTH {
self.modpar.dens[depth]
} else {
0.0
}
}
/// 获取指定能级在指定深度的占据数
pub fn population(&self, level: usize, depth: usize) -> f64 {
if level < MLEVEL && depth < MDEPTH {
self.levpop.popul[level][depth]
} else {
0.0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_model_state_creation() {
let state = ModelState::new();
assert_eq!(state.modpar.temp.len(), MDEPTH);
assert_eq!(state.levpop.popul.len(), MLEVEL);
}
#[test]
fn test_temperature_accessor() {
let mut state = ModelState::new();
state.modpar.temp[0] = 10000.0;
assert!((state.temperature(0) - 10000.0).abs() < 1e-10);
assert_eq!(state.temperature(MDEPTH), 0.0); // 越界
}
#[test]
fn test_population_accessor() {
let mut state = ModelState::new();
state.levpop.popul[0][0] = 1e10;
assert!((state.population(0, 0) - 1e10).abs() < 1e-5);
}
}
+466
View File
@@ -0,0 +1,466 @@
//! ODF (不透明度分布函数) 相关参数。
//!
//! 重构自 TLUSTY `ODFPAR.FOR`
use super::constants::*;
// ============================================================================
// ODF 维度参数
// ============================================================================
/// ODF 频率点数
pub const MFODF: usize = 180;
/// ODF 热点数
pub const MHOD: usize = 3;
/// ODF 频率范围
pub const MFRO: usize = MFREQL;
/// ODF 深度维度
pub const MDODF: usize = 3;
/// Kurucz 能级数
pub const MKULEV: usize = 7000;
/// 谱线数
pub const MLINE: usize = 1140000;
/// Fe 系数数
pub const MCFE: usize = 7824000;
// ============================================================================
// ODFION - ODF 离子控制
// ============================================================================
/// ODF 离子控制。
/// 对应 COMMON /ODFION/
#[derive(Debug, Clone, Default)]
pub struct OdfIon {
/// ODF 起始索引 1
pub inodf1: Vec<i32>,
/// ODF 起始索引 2
pub inodf2: Vec<i32>,
/// 束缚-自由截面索引
pub inbfcs: Vec<i32>,
/// Kurucz 观测标志
pub ikobs: Vec<i32>,
}
impl OdfIon {
pub fn new() -> Self {
Self {
inodf1: vec![0; MION],
inodf2: vec![0; MION],
inbfcs: vec![0; MION],
ikobs: vec![0; MION],
}
}
}
// ============================================================================
// ODFCTR - ODF 控制
// ============================================================================
/// ODF 控制参数。
/// 对应 COMMON /ODFCTR/
#[derive(Debug, Clone, Default)]
pub struct OdfCtr {
/// ODF 频率
pub frodf: Vec<f64>,
/// ODF 频率计数
pub nfrodf: Vec<i32>,
/// 能级 ODF 索引
pub indodf: Vec<i32>,
/// 跃迁 ODF 索引
pub jndodf: Vec<i32>,
}
impl OdfCtr {
pub fn new() -> Self {
Self {
frodf: vec![0.0; MLEVEL],
nfrodf: vec![0; MHOD],
indodf: vec![0; MLEVEL],
jndodf: vec![0; MTRANS],
}
}
}
// ============================================================================
// ODFFRQ - ODF 频率数据
// ============================================================================
/// ODF 频率数据。
/// 对应 COMMON /ODFFRQ/
#[derive(Debug, Clone, Default)]
pub struct OdfFrq {
/// ODF 频率 (起点)
pub fros: Vec<Vec<f64>>,
/// 波数
pub wnus: Vec<Vec<f64>>,
/// XDO
pub xdo: Vec<Vec<f64>>,
/// KDO
pub kdo: Vec<Vec<i32>>,
}
impl OdfFrq {
pub fn new() -> Self {
Self {
fros: vec![vec![0.0; MHOD]; MFRO],
wnus: vec![vec![0.0; MHOD]; MFRO],
xdo: vec![vec![0.0; 3]; MHOD],
kdo: vec![vec![0; 4]; MHOD],
}
}
}
// ============================================================================
// ODFMOD - ODF 模型数据
// ============================================================================
/// ODF 模型数据。
/// 对应 COMMON /ODFMOD/
#[derive(Debug, Clone, Default)]
pub struct OdfMod {
pub i1odf: Vec<i32>,
pub i2odf: Vec<i32>,
pub nqlodf: Vec<i32>,
}
impl OdfMod {
pub fn new() -> Self {
Self {
i1odf: vec![0; MLEVEL],
i2odf: vec![0; MLEVEL],
nqlodf: vec![0; MLEVEL],
}
}
}
// ============================================================================
// ODFSTK - ODF Stark 数据
// ============================================================================
/// ODF Stark 展宽数据。
/// 对应 COMMON /ODFSTK/
#[derive(Debug, Clone, Default)]
pub struct OdfStk {
/// XKIJ
pub xkij: Vec<Vec<f64>>,
/// 波长
pub wl0: Vec<Vec<f64>>,
/// FIJ
pub fij: Vec<Vec<f64>>,
}
impl OdfStk {
pub fn new(nlmx: usize) -> Self {
Self {
xkij: vec![vec![0.0; nlmx]; MHOD],
wl0: vec![vec![0.0; nlmx]; MHOD],
fij: vec![vec![0.0; nlmx]; MHOD],
}
}
}
// ============================================================================
// SPLCOM - 样条/Fe 线数据
// ============================================================================
/// Fe 线样条数据。
/// 对应 COMMON /SPLCOM/
///
/// 注意:SIGFE 是非常大的数组 (3 × 7,824,000 = 23,472,000 个 f32)
#[derive(Debug, Clone)]
pub struct SplCom {
/// Fe 截面 (f32 节省内存)
pub sigfe: Vec<Vec<Vec<f32>>>,
/// 频率起点 1
pub frs1: f64,
/// 频率终点 2
pub frs2: f64,
/// 频率间隔
pub dxnu: f64,
/// J 积分
pub xjid: Vec<f64>,
/// J ID
pub jidi: Vec<i32>,
/// J ID 半径
pub jidr: Vec<i32>,
/// J ID 起始
pub jids: i32,
/// J ID 数量
pub jidn: i32,
/// 频率起始索引
pub nfrs1: i32,
/// 频率表总数
pub nftt: i32,
}
impl Default for SplCom {
fn default() -> Self {
Self {
// 使用较小的测试大小,实际运行时需要调整
sigfe: vec![vec![vec![0.0; 100]; MDODF]; 100],
frs1: 0.0,
frs2: 0.0,
dxnu: 0.0,
xjid: vec![0.0; MDEPTH],
jidi: vec![0; MDEPTH],
jidr: vec![0; MDODF],
jids: 0,
jidn: 0,
nfrs1: 0,
nftt: 0,
}
}
}
impl SplCom {
/// 创建完整大小的数组 (需要大量内存)
pub fn new_full() -> Self {
Self {
sigfe: vec![vec![vec![0.0; MCFE]; MDODF]; 1],
frs1: 0.0,
frs2: 0.0,
dxnu: 0.0,
xjid: vec![0.0; MDEPTH],
jidi: vec![0; MDEPTH],
jidr: vec![0; MDODF],
jids: 0,
jidn: 0,
nfrs1: 0,
nftt: 0,
}
}
/// 估算完整内存使用 (MB)
pub fn full_memory_mb() -> f64 {
// SIGFE: MDODF × MCFE × sizeof(f32)
(MDODF * MCFE * std::mem::size_of::<f32>()) as f64 / (1024.0 * 1024.0)
}
}
// ============================================================================
// OPALIM - 不透明度限制
// ============================================================================
/// 不透明度限制参数。
/// 对应 COMMON /OPALIM/
#[derive(Debug, Clone, Default)]
pub struct OpaLim {
pub m1file: Vec<Vec<i32>>,
pub m2file: Vec<Vec<i32>>,
pub imerg: i32,
}
impl OpaLim {
pub fn new(nlmx: usize) -> Self {
Self {
m1file: vec![vec![0; MHOD]; nlmx],
m2file: vec![vec![0; MHOD]; nlmx],
imerg: 0,
}
}
}
// ============================================================================
// OPLIMT - 不透明度限制 T
// ============================================================================
/// 不透明度限制温度相关。
/// 对应 COMMON /OPLIMT/
#[derive(Debug, Clone, Default)]
pub struct OpLimT {
pub allim1: f64,
pub ablim1: f64,
pub ablim2: f64,
pub ablim3: f64,
}
// ============================================================================
// LEVCOM - 能级 ODF 数据
// ============================================================================
/// 能级 ODF 综合数据。
/// 对应 COMMON /LEVCOM/
#[derive(Debug, Clone)]
pub struct LevCom {
/// EMKU
pub emku: Vec<Vec<f64>>,
/// YMKU
pub ymku: Vec<Vec<f64>>,
/// XEV
pub xev: Vec<Vec<f64>>,
/// XOD
pub xod: Vec<Vec<f64>>,
/// EU
pub eu: Vec<f64>,
/// JEN
pub jen: Vec<i32>,
// Kurucz 能级数据
/// EEV
pub eev: Vec<f64>,
/// AEV
pub aev: Vec<f64>,
/// SEV
pub sev: Vec<f64>,
/// WEV
pub wev: Vec<f64>,
/// EOD
pub eod: Vec<f64>,
/// AOD
pub aod: Vec<f64>,
/// SOD
pub sod: Vec<f64>,
/// WOD
pub wod: Vec<f64>,
/// KSEV
pub ksev: Vec<i32>,
/// KSOD
pub ksod: Vec<i32>,
/// NEVKU
pub nevku: Vec<i32>,
/// NODKU
pub nodku: Vec<i32>,
// 计数器
pub nlevku: i32,
pub nlinku: i32,
pub keve: i32,
pub kodd: i32,
}
impl Default for LevCom {
fn default() -> Self {
// 使用较小的测试大小
Self {
emku: vec![vec![0.0; 2]; MLEVEL],
ymku: vec![vec![0.0; 2]; MLEVEL],
xev: vec![vec![0.0; MION]; MLEVEL],
xod: vec![vec![0.0; MION]; MLEVEL],
eu: vec![0.0; 2 * MLEVEL],
jen: vec![0; 2 * MLEVEL],
// Kurucz 数据使用较小的默认大小
eev: vec![0.0; 1000],
aev: vec![0.0; 1000],
sev: vec![0.0; 1000],
wev: vec![0.0; 1000],
eod: vec![0.0; 1000],
aod: vec![0.0; 1000],
sod: vec![0.0; 1000],
wod: vec![0.0; 1000],
ksev: vec![0; 1000],
ksod: vec![0; 1000],
nevku: vec![0; MION],
nodku: vec![0; MION],
nlevku: 0,
nlinku: 0,
keve: 0,
kodd: 0,
}
}
}
impl LevCom {
/// 创建完整大小的数组
pub fn new_full() -> Self {
Self {
emku: vec![vec![0.0; 2]; MLEVEL],
ymku: vec![vec![0.0; 2]; MLEVEL],
xev: vec![vec![0.0; MION]; MLEVEL],
xod: vec![vec![0.0; MION]; MLEVEL],
eu: vec![0.0; 2 * MLEVEL],
jen: vec![0; 2 * MLEVEL],
eev: vec![0.0; MKULEV],
aev: vec![0.0; MKULEV],
sev: vec![0.0; MKULEV],
wev: vec![0.0; MKULEV],
eod: vec![0.0; MKULEV],
aod: vec![0.0; MKULEV],
sod: vec![0.0; MKULEV],
wod: vec![0.0; MKULEV],
ksev: vec![0; MKULEV],
ksod: vec![0; MKULEV],
nevku: vec![0; MION],
nodku: vec![0; MION],
nlevku: 0,
nlinku: 0,
keve: 0,
kodd: 0,
}
}
/// 估算完整内存使用 (MB)
pub fn full_memory_mb() -> f64 {
let main_size = (4 * MLEVEL * MION + 4 * MLEVEL + 2 * 2 * MLEVEL) * std::mem::size_of::<f64>();
let kurucz_size = 8 * MKULEV * std::mem::size_of::<f64>();
(main_size + kurucz_size) as f64 / (1024.0 * 1024.0)
}
}
// ============================================================================
// 综合 ODF 数据结构
// ============================================================================
/// TLUSTY ODF 综合数据。
#[derive(Debug, Clone, Default)]
pub struct OdfData {
pub odfion: OdfIon,
pub odfctr: OdfCtr,
pub odffrq: OdfFrq,
pub odfmod: OdfMod,
pub splcom: SplCom,
pub opalim: OpaLim,
pub oplimt: OpLimT,
pub levcom: LevCom,
}
impl OdfData {
pub fn new() -> Self {
Self {
odfion: OdfIon::new(),
odfctr: OdfCtr::new(),
odffrq: OdfFrq::new(),
odfmod: OdfMod::new(),
..Default::default()
}
}
/// 估算完整内存使用 (MB)
pub fn full_memory_mb() -> f64 {
SplCom::full_memory_mb() + LevCom::full_memory_mb()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_odfion_creation() {
let odfion = OdfIon::new();
assert_eq!(odfion.inodf1.len(), MION);
}
#[test]
fn test_odfctr_creation() {
let odfctr = OdfCtr::new();
assert_eq!(odfctr.frodf.len(), MLEVEL);
assert_eq!(odfctr.nfrodf.len(), MHOD);
}
#[test]
fn test_memory_estimates() {
println!("SplCom full memory: {:.2} MB", SplCom::full_memory_mb());
println!("LevCom full memory: {:.2} MB", LevCom::full_memory_mb());
println!("Total ODF memory: {:.2} MB", OdfData::full_memory_mb());
}
#[test]
fn test_odf_data_creation() {
let odf = OdfData::new();
assert_eq!(odf.odfion.inodf1.len(), MION);
}
}