SpectraRust/src/tlusty/io/nstpar.rs
2026-04-04 09:36:14 +08:00

1577 lines
41 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.

//! 非标准参数输入模块。
//!
//! 重构自 TLUSTY `nstpar.f`
//!
//! 设置各种输入标志的默认值,并从文件读取非标准值。
//! 共有 236 个可配置参数。
use super::{FortranReader, FortranWriter, Result};
use crate::tlusty::math::getwrd;
// f2r_depends: GETWRD
// NOTE: Fortran NSTPAR conditionally calls GETLAL (if iquasi>0);
// in Rust, GETLAL is called by the main program based on iquasi value.
// ============================================================================
// 参数常量
// ============================================================================
/// 可配置变量数量
pub const MVAR: usize = 236;
/// 非标准参数输入文件单元号
pub const INPFI: u8 = 4;
// ============================================================================
// 变量名表
// ============================================================================
/// 所有可配置参数的名称
pub const VARNAM: [&str; MVAR] = [
"ISPLIN", "IRTE ", "IBC ", "ILMCOR", "ILPSCT",
"ILASCT", "DJMAX ", "NTRALI", "IPSLTE", "IOPTAB",
"IFMOL ", "IFENTR", "NFRECL", "IFRYB ", "IFRAYL",
"HCMASS", "RADSTR", "BERGFC", "IHYDPR", "IIRWIN",
"ICOMPT", "IZSCAL", "IBCHE ", "IVISC ", "ALPHAV",
"ZETA0 ", "ZETA1 ", "FRACTV", "DMVISC", "REYNUM",
"IFZ0 ", "IHESO6", "ICOLHN",
"IFALI ", "IFPOPR", "JALI ", "IFRALI", "IFALIH",
"IFPREC", "IELCOR", "ICHC ", "IRSPLT", "IATREF",
"MODREF", "IACPP ", "IACDP ", "IFLEV ", "IDLTE ",
"POPZER", "POPZR2", "POPZCH", "NITZER", "RADZER",
"IFDIEL", "IFCHTR", "SHFAC ",
"QTLAS ", "ITLUCY", "IACLT ", "IACLDT", "IFMOFF",
"IOVER ", "ITLAS ", "NITER ", "NLAMBD", "IFRSET",
"ND ", "JIDS ", "IDMFIX", "ITNDRE",
"NMU ", "IOSCOR",
"NELSC ", "IHECOR", "IBFINT", "IRDER ",
"CHMAX ", "ILDER ", "IBPOPE", "CHMAXT", "NLAMT ",
"INTRPL", "ICHANG", "IFIXMO", "IFIXDE",
"INHE ", "INRE ", "INPC ", "INZD ", "INSE ",
"INMP ", "INDL ", "NDRE ", "TAUDIV", "IDLST ",
"NRETC ", "ICONV ", "IPRESS", "ITEMP ",
"ITMCOR", "ICONRE", "IDEEPC", "NDCGAP", "CRFLIM",
"IOPHMI", "IOPH2P", "IOPHEM", "IOPCH ", "IOPOH ",
"IOPH2M", "IOH2H2", "IOH2HE", "IOH2H ", "IOHHE ",
"IOPLYM",
"IOPOLD", "IRWTAB", "MOLTAB",
"IRSCT ", "IRSCH2", "IRSCHE", "KEEPOP",
"IQUASI", "NUNALP", "NUNBET", "TQMPRF",
"IACC ", "IACD ", "KSNG ", "ITEK ", "ORELAX",
"IWINBL", "ICOMGR",
"ICRSW ", "SWPFAC", "SWPLIM", "SWPINC",
"TAUFIR", "TAULAS", "ABROS0", "TSURF ", "ALBAVE",
"DION0 ", "NDGREY", "IDGREY", "NCONIT", "IPRING",
"DM1 ", "ABPLA0", "ABPMIN", "ITGMAX", "NNEWD ",
"IHM ", "IH2 ", "IH2P ", "IFTENE",
"TRAD ", "WDIL ",
"TDISK ", "TFLOOR", "TMOLIM",
"HMIX0 ", "MLTYPE", "VTB ", "IPTURB", "ILGDER",
"XGRAD ", "STRL1 ", "STRL2 ", "STRLX ",
"FRCMAX", "FRCMIN", "FRLMAX", "FRLMIN", "CFRMAX",
"DFTAIL", "NFTAIL", "TSNU ", "VTNU ", "DDNU ",
"IELNU ", "CNU1 ", "CNU2 ", "ISPODF",
"DPSILG", "DPSILT", "DPSILN", "DPSILD",
"ICOMST", "ICOMDE", "ICOMBC", "ICOMVE", "ICOMRT",
"ICMDRA", "KNISH ", "FRLCOM", "ICHCOO",
"NCFOR1", "NCFOR2", "NCCOUP", "NCITOT", "NCFULL",
"IFPRD ", "XPDIV ", "IFPZEV",
"IPRINI", "IDCONZ", "INTENS",
"ICOOLP", "IPRIND", "IPRINP", "ICHCKP", "IPOPAC",
"ILBC ", "IUBC ", "DERT ", "ICONRS", "IMUCON",
"IFPRAD", "ICHANM", "CUTLYM", "CUTBAL", "IHXENB",
"IHGOM ", "HGLIM ", "IPRCRS", "NPRCRS", "FRTLIM",
"DIFT ", "DIFP ", "GRDAD0", "ITGRAD",
"IPRYBH", "IPELCH", "IPELDO", "IPCONF"
];
// ============================================================================
// 默认值表
// ============================================================================
/// 所有参数的默认值(字符串格式,与 Fortran DATA 语句一致)
pub const PVALUE_DEFAULT: [&str; MVAR] = [
" 0", " 0", " 3", " 3", " 1",
" 0", " 1.D-3", " 3", " 0", " 0",
" 0", " 1", " 0", " 0", " 1",
" 0.", " 0.", " 1.", " 0", " 1",
" 0", " 0", " 1", " 0", " 0.1",
" 0.0", " 0.0", " -1", " 0.01", " 0.",
" 9", " 0", " 0",
" 5", " 4", " 1", " 0", " 0",
" 1", " -1", " 1", " 1", " 1",
" 1", " 7", " 4", " 0", " 1000",
"1.D-20", "1.D-20", "1.D-15", " 1", "1.D-20",
" 0", " 0", " 0.",
" 1.D30", " 0", " 7", " 4", " 0",
" 1", " 100", " 30", " 2", " 0",
" 70", " 0", " 1", " 1",
" 3", " 0",
" 0", " 0", " 1", " 3",
" 1.D-3", " 0", " 1", " 0.01", " 1",
" 0", " 0", " 0", " 0",
" 1", " 2", " 3", " 0", " 4",
" 0", " 0", " 0", " 0.5", " 5",
" 0", " 0", " 0", " 0",
" 0", " 1", " 2", " 2", " 0.7",
" 1", " 1", " 1", " 1", " 1",
" 1", " 1", " 1", " 1", " 1",
" 0",
" 0", " 1", " 1",
" 1", " 1", " 1", " 0",
" 0", " 3", " 0", " 0.",
" 7", " 4", " 0", " 4", " 1.D0",
" -1", " 0",
" 0", " 1.D-1", " 1.D-3", " 3.D0",
" 1.D-7", "316.0", " 0.4", " 0.", " 0.",
" 1.", " 0", " 0", " 0", " 0",
" 1.D-3", "3.D-1", "1.D-5", " 10", " 0",
" 0", " 0", " 0", " 0",
" 0.", " 0.",
" 0.", " 8000.", " 9000.",
" -1.", " 1", " 0.", " 1", " 0",
" 0.", "0.001", " 0.02", "1.D-10",
" 0.", "1.D12", " 0.", "1.D13", " 0.",
" 0.25", " 21", " 0.", " 0.", " 0.75",
" 0", " 4.5", " 3.", " 0",
" 10.", " 1.25", " 10.", " 1.25",
" 1", " 1", " 1", " 0", " 0",
" 0", " 0", "8.2D14", " 1",
" 0", " 1", " 0", " 1", " 1",
" 0", " 3.D0", " 0",
" 0", " 31", " 10",
" 0", " 0", " 1", " 0", " 0",
" 0", " 0", " 0.01", " 10", " 10",
" 1", " 1", " 0.", " 0.", " 0",
" 0", "1.D18", " 0", " 0", "3.2880",
" 0.01", " 0.01", " 0.", " 0",
" 0", " 0", " 0", " 0"
];
// ============================================================================
// NstparParams - 非标准参数结构
// ============================================================================
/// 非标准参数配置。
///
/// 包含 TLUSTY 运行的所有可配置参数。
/// 参数按功能分组,便于理解。
#[derive(Debug, Clone)]
pub struct NstparParams {
// === 基本控制参数 ===
pub isplin: i32,
pub irte: i32,
pub ibc: i32,
pub ilmcor: i32,
pub ilpsct: i32,
pub ilasct: i32,
pub djmax: f64,
pub ntrali: i32,
pub ipslte: i32,
pub ioptab: i32,
// === 分子和能量参数 ===
pub ifmol: i32,
pub ifentr: i32,
pub nfrecl: i32,
pub ifryb: i32,
pub ifrayl: i32,
// === 恒星风/He参数 ===
pub hcmass: f64,
pub radstr: f64,
pub bergfc: f64,
pub ihydpr: i32,
pub iirwin: i32,
// === Compton/标度参数 ===
pub icompt: i32,
pub izscal: i32,
pub ibche: i32,
pub ivisc: i32,
pub alphav: f64,
// === 粘性参数 ===
pub zeta0: f64,
pub zeta1: f64,
pub fractv: i32,
pub dmvisc: f64,
pub reynum: f64,
// === 其他控制 ===
pub ifz0: i32,
pub iheso6: i32,
pub icolhn: i32,
// === ALI (加速Lambda迭代) 参数 ===
pub ifali: i32,
pub ifpopr: i32,
pub jali: i32,
pub ifrali: i32,
pub ifalih: i32,
pub ifprec: i32,
pub ielcor: i32,
pub ichc: i32,
pub irsplt: i32,
pub iatref: i32,
pub modref: i32,
pub iacpp: i32,
pub iacdp: i32,
pub iflev: i32,
pub idlte: i32,
// === 种群零点参数 ===
pub popzer: f64,
pub popzr2: f64,
pub popzch: f64,
pub nitzer: i32,
pub radzer: f64,
// === 介电/电荷转移 ===
pub ifdiel: i32,
pub ifchtr: i32,
pub shfac: f64,
// === 温度加速 ===
pub qtlas: f64,
pub itlucy: i32,
pub iaclt: i32,
pub iacldt: i32,
pub ifmoff: i32,
// === 迭代控制 ===
pub iover: i32,
pub itlas: i32,
pub niter: i32,
pub nlambd: i32,
pub ifrset: i32,
// === 深度/几何 ===
pub nd: i32,
pub jids: i32,
pub idmfix: i32,
pub itndre: i32,
pub nmu: i32,
pub ioscor: i32,
// === He/相关性 ===
pub nelsc: i32,
pub ihecor: i32,
pub ibfint: i32,
pub irder: i32,
// === 变化控制 ===
pub chmax: f64,
pub ilder: i32,
pub ibpope: i32,
pub chmaxt: f64,
pub nlamt: i32,
pub intrpl: i32,
pub ichang: i32,
pub ifixmo: i32,
pub ifixde: i32,
// === 材料变化索引 ===
pub inhe: i32,
pub inre: i32,
pub inpc: i32,
pub inzd: i32,
pub inse: i32,
pub inmp: i32,
pub indl: i32,
pub ndre: i32,
pub taudiv: f64,
pub idlst: i32,
// === 收敛控制 ===
pub nretc: i32,
pub iconv: i32,
pub ipress: i32,
pub itemp: i32,
pub itmcor: i32,
pub iconre: i32,
pub ideepc: i32,
pub ndcgap: i32,
pub crflim: f64,
// === 不透明度开关 ===
pub iophmi: i32,
pub ioph2p: i32,
pub iophem: i32,
pub iopch: i32,
pub iopoh: i32,
pub ioph2m: i32,
pub ioh2h2: i32,
pub ioh2he: i32,
pub ioh2h: i32,
pub iohhe: i32,
pub ioplym: i32,
// === 不透明度/分子表 ===
pub iopold: i32,
pub irwtab: i32,
pub moltab: i32,
// === 散射 ===
pub irsct: i32,
pub irsch2: i32,
pub irsche: i32,
pub keepop: i32,
// === 准静态 ===
pub iquasi: i32,
pub nunalp: i32,
pub nunbet: i32,
pub tqmprf: f64,
// === 加速控制 ===
pub iacc: i32,
pub iacd: i32,
pub ksng: i32,
pub itek: i32,
pub orelax: f64,
pub iwinbl: i32,
pub icomgr: i32,
// === 交换参数 ===
pub icrsw: i32,
pub swpfac: f64,
pub swplim: f64,
pub swpinc: f64,
// === 大气边界 ===
pub taufir: f64,
pub taulas: f64,
pub abros0: f64,
pub tsurf: f64,
pub albave: f64,
pub dion0: f64,
pub ndgrey: i32,
pub idgrey: i32,
pub nconit: i32,
pub ipring: i32,
// === 密度/丰度 ===
pub dm1: f64,
pub abpla0: f64,
pub abpmin: f64,
pub itgmax: i32,
pub nnewd: i32,
// === H/He 物种 ===
pub ihm: i32,
pub ih2: i32,
pub ih2p: i32,
pub iftene: i32,
// === 辐射稀释 ===
pub trad: f64,
pub wdil: f64,
// === 盘模型 ===
pub tdisk: f64,
pub tfloor: f64,
pub tmolim: f64,
// === 对流 ===
pub hmix0: f64,
pub mltype: i32,
pub vtb: f64,
pub ipturb: i32,
pub ilgder: i32,
// === 梯度 ===
pub xgrad: f64,
pub strl1: f64,
pub strl2: f64,
pub strlx: f64,
// === 频率范围 ===
pub frcmax: f64,
pub frcmin: f64,
pub frlmax: f64,
pub frlmin: f64,
pub cfrmax: f64,
// === 线尾参数 ===
pub dftail: f64,
pub nftail: i32,
pub tsnu: f64,
pub vtnu: f64,
pub ddnu: f64,
pub ielnu: i32,
pub cnu1: f64,
pub cnu2: f64,
pub ispodf: i32,
// === Psi 限制 ===
pub dpsilg: f64,
pub dpsilt: f64,
pub dpsiln: f64,
pub dpsild: f64,
// === Compton 控制 ===
pub icomst: i32,
pub icomde: i32,
pub icombc: i32,
pub icomve: i32,
pub icomrt: i32,
pub icmdra: i32,
pub knish: i32,
pub frlcom: f64,
pub ichcoo: i32,
// === 耦合迭代 ===
pub ncfor1: i32,
pub ncfor2: i32,
pub nccoup: i32,
pub ncitot: i32,
pub ncfull: i32,
// === 其他 ===
pub ifprd: i32,
pub xpdiv: f64,
pub ifpzev: i32,
// === 打印控制 ===
pub iprini: i32,
pub idconz: i32,
pub intens: i32,
pub icoolp: i32,
pub iprind: i32,
pub iprinp: i32,
pub ichckp: i32,
pub ipopac: i32,
// === 边界条件 ===
pub ilbc: i32,
pub iubc: i32,
pub dert: f64,
pub iconrs: i32,
pub imucon: i32,
pub ifprad: i32,
pub ichanm: i32,
pub cutlym: f64,
pub cutbal: f64,
pub ihxenb: i32,
// === He/H 梯度 ===
pub ihgom: i32,
pub hglim: f64,
pub iprcrs: i32,
pub nprcrs: i32,
pub frtlim: f64,
// === 扩散 ===
pub dift: f64,
pub difp: f64,
pub grdad0: f64,
pub itgrad: i32,
// === 打印键 ===
pub iprybh: i32,
pub ipelch: i32,
pub ipeldo: i32,
pub ipconf: i32,
}
impl Default for NstparParams {
fn default() -> Self {
Self {
// 基本控制
isplin: 0,
irte: 0,
ibc: 3,
ilmcor: 3,
ilpsct: 1,
ilasct: 0,
djmax: 1e-3,
ntrali: 3,
ipslte: 0,
ioptab: 0,
// 分子/能量
ifmol: 0,
ifentr: 1,
nfrecl: 0,
ifryb: 0,
ifrayl: 1,
// 恒星风/He
hcmass: 0.0,
radstr: 0.0,
bergfc: 1.0,
ihydpr: 0,
iirwin: 1,
// Compton/标度
icompt: 0,
izscal: 0,
ibche: 1,
ivisc: 0,
alphav: 0.1,
// 粘性
zeta0: 0.0,
zeta1: 0.0,
fractv: -1,
dmvisc: 0.01,
reynum: 0.0,
// 其他控制
ifz0: 9,
iheso6: 0,
icolhn: 0,
// ALI
ifali: 5,
ifpopr: 4,
jali: 1,
ifrali: 0,
ifalih: 0,
ifprec: 1,
ielcor: -1,
ichc: 1,
irsplt: 1,
iatref: 1,
modref: 1,
iacpp: 7,
iacdp: 4,
iflev: 0,
idlte: 1000,
// 种群零点
popzer: 1e-20,
popzr2: 1e-20,
popzch: 1e-15,
nitzer: 1,
radzer: 1e-20,
// 介电/电荷转移
ifdiel: 0,
ifchtr: 0,
shfac: 0.0,
// 温度加速
qtlas: 1e30,
itlucy: 0,
iaclt: 7,
iacldt: 4,
ifmoff: 0,
// 迭代控制
iover: 1,
itlas: 100,
niter: 30,
nlambd: 2,
ifrset: 0,
// 深度/几何
nd: 70,
jids: 0,
idmfix: 1,
itndre: 1,
nmu: 3,
ioscor: 0,
// He/相关性
nelsc: 0,
ihecor: 0,
ibfint: 1,
irder: 3,
// 变化控制
chmax: 1e-3,
ilder: 0,
ibpope: 1,
chmaxt: 0.01,
nlamt: 1,
intrpl: 0,
ichang: 0,
ifixmo: 0,
ifixde: 0,
// 材料变化
inhe: 1,
inre: 2,
inpc: 3,
inzd: 0,
inse: 4,
inmp: 0,
indl: 0,
ndre: 0,
taudiv: 0.5,
idlst: 5,
// 收敛
nretc: 0,
iconv: 0,
ipress: 0,
itemp: 0,
itmcor: 0,
iconre: 1,
ideepc: 2,
ndcgap: 2,
crflim: 0.7,
// 不透明度
iophmi: 1,
ioph2p: 1,
iophem: 1,
iopch: 1,
iopoh: 1,
ioph2m: 1,
ioh2h2: 1,
ioh2he: 1,
ioh2h: 1,
iohhe: 1,
ioplym: 0,
// 不透明度/分子表
iopold: 0,
irwtab: 1,
moltab: 1,
// 散射
irsct: 1,
irsch2: 1,
irsche: 1,
keepop: 0,
// 准静态
iquasi: 0,
nunalp: 3,
nunbet: 0,
tqmprf: 0.0,
// 加速
iacc: 7,
iacd: 4,
ksng: 0,
itek: 4,
orelax: 1.0,
iwinbl: -1,
icomgr: 0,
// 交换
icrsw: 0,
swpfac: 0.1,
swplim: 1e-3,
swpinc: 3.0,
// 大气边界
taufir: 1e-7,
taulas: 316.0,
abros0: 0.4,
tsurf: 0.0,
albave: 0.0,
dion0: 1.0,
ndgrey: 0,
idgrey: 0,
nconit: 0,
ipring: 0,
// 密度/丰度
dm1: 0.0,
abpla0: 1e-3,
abpmin: 0.3,
itgmax: 10,
nnewd: 0,
// H/He
ihm: 0,
ih2: 0,
ih2p: 0,
iftene: 0,
// 辐射稀释
trad: 0.0,
wdil: 0.0,
// 盘模型
tdisk: 0.0,
tfloor: 8000.0,
tmolim: 9000.0,
// 对流
hmix0: -1.0,
mltype: 1,
vtb: 0.0,
ipturb: 1,
ilgder: 0,
// 梯度
xgrad: 0.0,
strl1: 0.001,
strl2: 0.02,
strlx: 1e-10,
// 频率范围
frcmax: 0.0,
frcmin: 1e12,
frlmax: 0.0,
frlmin: 1e13,
cfrmax: 0.0,
// 线尾
dftail: 0.25,
nftail: 21,
tsnu: 0.0,
vtnu: 0.0,
ddnu: 0.75,
ielnu: 0,
cnu1: 4.5,
cnu2: 3.0,
ispodf: 0,
// Psi 限制
dpsilg: 10.0,
dpsilt: 1.25,
dpsiln: 10.0,
dpsild: 1.25,
// Compton 控制
icomst: 1,
icomde: 1,
icombc: 1,
icomve: 0,
icomrt: 0,
icmdra: 0,
knish: 0,
frlcom: 8.2e14,
ichcoo: 1,
// 耦合迭代
ncfor1: 0,
ncfor2: 1,
nccoup: 0,
ncitot: 1,
ncfull: 1,
// 其他
ifprd: 0,
xpdiv: 3.0,
ifpzev: 0,
// 打印控制
iprini: 0,
idconz: 31,
intens: 10,
icoolp: 0,
iprind: 0,
iprinp: 1,
ichckp: 0,
ipopac: 0,
// 边界条件
ilbc: 0,
iubc: 0,
dert: 0.01,
iconrs: 10,
imucon: 10,
ifprad: 1,
ichanm: 1,
cutlym: 0.0,
cutbal: 0.0,
ihxenb: 0,
// He/H 梯度
ihgom: 0,
hglim: 1e18,
iprcrs: 0,
nprcrs: 0,
frtlim: 3.2880,
// 扩散
dift: 0.01,
difp: 0.01,
grdad0: 0.0,
itgrad: 0,
// 打印键
iprybh: 0,
ipelch: 0,
ipeldo: 0,
ipconf: 0,
}
}
}
impl NstparParams {
/// 从字符串数组解析参数值
pub fn from_values(values: &[String; MVAR]) -> Self {
let parse_i32 = |s: &str| -> i32 {
s.trim()
.replace('D', "E")
.replace('d', "e")
.parse()
.unwrap_or(0)
};
let parse_f64 = |s: &str| -> f64 {
s.trim()
.replace('D', "E")
.replace('d', "e")
.parse()
.unwrap_or(0.0)
};
let mut idx = 0;
macro_rules! next_i32 {
() => {{
let v = parse_i32(&values[idx]);
idx += 1;
v
}};
}
macro_rules! next_f64 {
() => {{
let v = parse_f64(&values[idx]);
idx += 1;
v
}};
}
Self {
isplin: next_i32!(),
irte: next_i32!(),
ibc: next_i32!(),
ilmcor: next_i32!(),
ilpsct: next_i32!(),
ilasct: next_i32!(),
djmax: next_f64!(),
ntrali: next_i32!(),
ipslte: next_i32!(),
ioptab: next_i32!(),
ifmol: next_i32!(),
ifentr: next_i32!(),
nfrecl: next_i32!(),
ifryb: next_i32!(),
ifrayl: next_i32!(),
hcmass: next_f64!(),
radstr: next_f64!(),
bergfc: next_f64!(),
ihydpr: next_i32!(),
iirwin: next_i32!(),
icompt: next_i32!(),
izscal: next_i32!(),
ibche: next_i32!(),
ivisc: next_i32!(),
alphav: next_f64!(),
zeta0: next_f64!(),
zeta1: next_f64!(),
fractv: next_i32!(),
dmvisc: next_f64!(),
reynum: next_f64!(),
ifz0: next_i32!(),
iheso6: next_i32!(),
icolhn: next_i32!(),
ifali: next_i32!(),
ifpopr: next_i32!(),
jali: next_i32!(),
ifrali: next_i32!(),
ifalih: next_i32!(),
ifprec: next_i32!(),
ielcor: next_i32!(),
ichc: next_i32!(),
irsplt: next_i32!(),
iatref: next_i32!(),
modref: next_i32!(),
iacpp: next_i32!(),
iacdp: next_i32!(),
iflev: next_i32!(),
idlte: next_i32!(),
popzer: next_f64!(),
popzr2: next_f64!(),
popzch: next_f64!(),
nitzer: next_i32!(),
radzer: next_f64!(),
ifdiel: next_i32!(),
ifchtr: next_i32!(),
shfac: next_f64!(),
qtlas: next_f64!(),
itlucy: next_i32!(),
iaclt: next_i32!(),
iacldt: next_i32!(),
ifmoff: next_i32!(),
iover: next_i32!(),
itlas: next_i32!(),
niter: next_i32!(),
nlambd: next_i32!(),
ifrset: next_i32!(),
nd: next_i32!(),
jids: next_i32!(),
idmfix: next_i32!(),
itndre: next_i32!(),
nmu: next_i32!(),
ioscor: next_i32!(),
nelsc: next_i32!(),
ihecor: next_i32!(),
ibfint: next_i32!(),
irder: next_i32!(),
chmax: next_f64!(),
ilder: next_i32!(),
ibpope: next_i32!(),
chmaxt: next_f64!(),
nlamt: next_i32!(),
intrpl: next_i32!(),
ichang: next_i32!(),
ifixmo: next_i32!(),
ifixde: next_i32!(),
inhe: next_i32!(),
inre: next_i32!(),
inpc: next_i32!(),
inzd: next_i32!(),
inse: next_i32!(),
inmp: next_i32!(),
indl: next_i32!(),
ndre: next_i32!(),
taudiv: next_f64!(),
idlst: next_i32!(),
nretc: next_i32!(),
iconv: next_i32!(),
ipress: next_i32!(),
itemp: next_i32!(),
itmcor: next_i32!(),
iconre: next_i32!(),
ideepc: next_i32!(),
ndcgap: next_i32!(),
crflim: next_f64!(),
iophmi: next_i32!(),
ioph2p: next_i32!(),
iophem: next_i32!(),
iopch: next_i32!(),
iopoh: next_i32!(),
ioph2m: next_i32!(),
ioh2h2: next_i32!(),
ioh2he: next_i32!(),
ioh2h: next_i32!(),
iohhe: next_i32!(),
ioplym: next_i32!(),
iopold: next_i32!(),
irwtab: next_i32!(),
moltab: next_i32!(),
irsct: next_i32!(),
irsch2: next_i32!(),
irsche: next_i32!(),
keepop: next_i32!(),
iquasi: next_i32!(),
nunalp: next_i32!(),
nunbet: next_i32!(),
tqmprf: next_f64!(),
iacc: next_i32!(),
iacd: next_i32!(),
ksng: next_i32!(),
itek: next_i32!(),
orelax: next_f64!(),
iwinbl: next_i32!(),
icomgr: next_i32!(),
icrsw: next_i32!(),
swpfac: next_f64!(),
swplim: next_f64!(),
swpinc: next_f64!(),
taufir: next_f64!(),
taulas: next_f64!(),
abros0: next_f64!(),
tsurf: next_f64!(),
albave: next_f64!(),
dion0: next_f64!(),
ndgrey: next_i32!(),
idgrey: next_i32!(),
nconit: next_i32!(),
ipring: next_i32!(),
dm1: next_f64!(),
abpla0: next_f64!(),
abpmin: next_f64!(),
itgmax: next_i32!(),
nnewd: next_i32!(),
ihm: next_i32!(),
ih2: next_i32!(),
ih2p: next_i32!(),
iftene: next_i32!(),
trad: next_f64!(),
wdil: next_f64!(),
tdisk: next_f64!(),
tfloor: next_f64!(),
tmolim: next_f64!(),
hmix0: next_f64!(),
mltype: next_i32!(),
vtb: next_f64!(),
ipturb: next_i32!(),
ilgder: next_i32!(),
xgrad: next_f64!(),
strl1: next_f64!(),
strl2: next_f64!(),
strlx: next_f64!(),
frcmax: next_f64!(),
frcmin: next_f64!(),
frlmax: next_f64!(),
frlmin: next_f64!(),
cfrmax: next_f64!(),
dftail: next_f64!(),
nftail: next_i32!(),
tsnu: next_f64!(),
vtnu: next_f64!(),
ddnu: next_f64!(),
ielnu: next_i32!(),
cnu1: next_f64!(),
cnu2: next_f64!(),
ispodf: next_i32!(),
dpsilg: next_f64!(),
dpsilt: next_f64!(),
dpsiln: next_f64!(),
dpsild: next_f64!(),
icomst: next_i32!(),
icomde: next_i32!(),
icombc: next_i32!(),
icomve: next_i32!(),
icomrt: next_i32!(),
icmdra: next_i32!(),
knish: next_i32!(),
frlcom: next_f64!(),
ichcoo: next_i32!(),
ncfor1: next_i32!(),
ncfor2: next_i32!(),
nccoup: next_i32!(),
ncitot: next_i32!(),
ncfull: next_i32!(),
ifprd: next_i32!(),
xpdiv: next_f64!(),
ifpzev: next_i32!(),
iprini: next_i32!(),
idconz: next_i32!(),
intens: next_i32!(),
icoolp: next_i32!(),
iprind: next_i32!(),
iprinp: next_i32!(),
ichckp: next_i32!(),
ipopac: next_i32!(),
ilbc: next_i32!(),
iubc: next_i32!(),
dert: next_f64!(),
iconrs: next_i32!(),
imucon: next_i32!(),
ifprad: next_i32!(),
ichanm: next_i32!(),
cutlym: next_f64!(),
cutbal: next_f64!(),
ihxenb: next_i32!(),
ihgom: next_i32!(),
hglim: next_f64!(),
iprcrs: next_i32!(),
nprcrs: next_i32!(),
frtlim: next_f64!(),
dift: next_f64!(),
difp: next_f64!(),
grdad0: next_f64!(),
itgrad: next_i32!(),
iprybh: next_i32!(),
ipelch: next_i32!(),
ipeldo: next_i32!(),
ipconf: next_i32!(),
}
}
}
// ============================================================================
// NstparOutput - 输出状态
// ============================================================================
/// NSTPAR 输出状态。
///
/// 包含解析后的参数和需要更新的状态变量。
#[derive(Debug, Clone)]
pub struct NstparOutput {
pub params: NstparParams,
/// CRSW 数组(初始为 1.0
pub crsw: Vec<f64>,
/// 是否启用 LCHC
pub lchc: bool,
/// 固定频率数
pub nffix: i32,
/// 总不透明度开关
pub iopadd: i32,
/// RRDIL 值
pub rrdil: f64,
/// ITGMX0 值
pub itgmx0: i32,
/// Lambda 迭代计数数组
pub nitlam: Vec<i32>,
/// 对流参数
pub aconml: f64,
pub bconml: f64,
pub cconml: f64,
}
// ============================================================================
// 纯解析函数
// ============================================================================
/// 纯解析函数:从文本行解析关键字-值对。
///
/// # 参数
/// * `lines` - 输入文件的文本行
///
/// # 返回
/// 包含所有参数值的数组
pub fn parse_keyword_values(lines: &[String]) -> [String; MVAR] {
let mut pvalue: [String; MVAR] = std::array::from_fn(|i| PVALUE_DEFAULT[i].to_string());
let mut ivar: isize = -1;
let mut indv: isize = -1;
for text in lines {
let mut k0: usize = 0;
loop {
let (k1, k2) = match getwrd(text, k0) {
Some((k1, k2)) => (k1, k2),
None => break,
};
k0 = k2 + 2;
// 跳过等号
if k2 >= k1 && k2 < text.len() {
let word = &text[k1..=k2];
if word == "=" {
continue;
}
indv = -indv;
if indv == 1 {
// 查找变量名
let mut found = false;
for i in 0..MVAR {
let varnam_trimmed = VARNAM[i].trim();
if word.len() <= varnam_trimmed.len()
&& word == &varnam_trimmed[..word.len()]
{
ivar = i as isize;
found = true;
break;
}
}
if !found {
// 跳过未知变量的值
let result = getwrd(text, k0);
if result.is_none() {
// 需要读取下一行
break;
}
let (k1_next, k2_next) = result.unwrap();
k0 = k2_next + 2;
indv = -indv;
}
} else {
// 设置变量值
if ivar >= 0 && (ivar as usize) < MVAR {
// 右对齐到6字符
let padded = format!("{:>6}", word);
pvalue[ivar as usize] = padded;
}
}
}
}
}
pvalue
}
// ============================================================================
// 后处理函数
// ============================================================================
/// 应用参数后处理逻辑。
///
/// 根据 TLUSTY 的规则调整参数值。
pub fn apply_nstpar_postprocessing(
params: &mut NstparParams,
teff: f64,
idisk: i32,
lte: bool,
ltgrey: bool,
ielhm: i32,
mdepth: usize,
mlambd: usize,
mmu: usize,
) -> NstparOutput {
// 初始化 CRSW 数组
let crsw = vec![1.0; mdepth];
// LTGREY 和 LTE 修正
if ltgrey {
params.ispodf = 0;
}
if lte {
params.iflev = 1;
}
if params.ifryb >= 1 {
params.idlst = 0;
}
// LCHC 标志
let lchc = params.ichc == 1;
// 固定频率数
let nffix = params.ifrali;
// IACC 修正
if params.iacc <= 4 {
params.iacc = 7;
}
// 频率范围修正(转换为 Hz
if params.frtlim < 1e6 {
params.frtlim *= 1e15;
}
if params.frcmax < 1e6 {
params.frcmax *= 1e15;
}
if params.frlmax < 1e6 {
params.frlmax *= 1e15;
}
if params.frcmin < 1e6 {
params.frcmin *= 1e13;
}
if params.frlmin < 1e6 {
params.frlmin *= 1e13;
}
// FRLMAX 默认值
if params.frlmax == 0.0 {
params.frlmax = (1e11 * params.cnu1 * teff).max(3.288e15);
}
// CFRMAX 默认值
if idisk == 0 && params.cfrmax == 0.0 {
params.cfrmax = 2.0;
}
// TRAD 检查
if params.trad != 0.0 {
params.iwinbl = -1;
}
// NITZER 限制
if params.nitzer > params.itek {
params.nitzer = params.itek;
}
if params.nitzer > params.iacc - params.iacd {
params.nitzer = params.iacc - params.iacd;
}
// 高温修正
if teff > 15000.0 {
params.ioph2p = 0;
params.iopch = 0;
params.iopoh = 0;
params.irsch2 = 0;
params.ioph2m = 0;
params.ioh2h2 = 0;
params.ioh2he = 0;
params.ioh2h = 0;
params.iohhe = 0;
}
// 计算总不透明度开关
let iopadd = params.iophmi
+ params.ioph2p
+ params.iophem
+ params.iopch
+ params.iopoh
+ params.ioph2m
+ params.ioh2h2
+ params.ioh2he
+ params.ioh2h
+ params.iohhe
+ params.irsct
+ params.irsch2
+ params.irsche;
// IELCOR 修正
if params.ioptab < 0 || params.ifmol > 0 {
params.ielcor = -1;
}
// RRDIL
let rrdil = 1.0;
// IFZ0 修正
if idisk == 0 {
params.ifz0 = -1;
}
// ITGMX0
let itgmx0 = params.itgmax;
// Lambda 迭代计数
let mut nitlam = vec![0; params.niter as usize + 2];
if params.nlambd < 0 {
params.nlambd = -params.nlambd;
if lte {
params.nlambd = 1;
}
for itl in 0..12.min(nitlam.len()) {
nitlam[itl] = params.nlambd;
}
for itl in 12..nitlam.len() {
nitlam[itl] = 2;
}
} else if params.nlambd > 0 {
if lte {
params.nlambd = 1;
}
for itl in 0..nitlam.len() {
nitlam[itl] = params.nlambd;
}
}
// ILMCOR 修正
if params.ilmcor >= 3 {
params.ilpsct = 1;
}
// INZD/INSE 默认值
if idisk == 1
&& params.inzd == 0
&& params.izscal == 0
&& params.ivisc <= 1
&& params.ifryb == 0
{
params.inzd = 4;
params.inse = 5;
}
// IFIXMO 修正
if params.ifixmo > 0 {
params.inhe = 0;
params.inre = 0;
params.inpc = 0;
params.inzd = 0;
params.inse = 1;
}
// IFIXDE 修正
if params.ifixde > 0 {
params.inhe = 1;
params.inre = 0;
params.inpc = 2;
params.inzd = 0;
params.inse = 3;
}
// IPRCRS 修正
if params.iprcrs > 0 {
params.niter = 0;
params.nlambd = 1;
}
// 对流参数
let (aconml, bconml, cconml) = if params.mltype == 2 {
(1.0, 2.0, 16.0)
} else {
(1.0 / 8.0, 0.5, 16.0)
};
// IELHM 修正
if ielhm > 0 {
params.iophmi = 0;
}
NstparOutput {
params: params.clone(),
crsw,
lchc,
nffix,
iopadd,
rrdil,
itgmx0,
nitlam,
aconml,
bconml,
cconml,
}
}
// ============================================================================
// I/O 函数
// ============================================================================
/// 读取非标准参数文件。
///
/// # 参数
/// * `reader` - FortranReader 实例
/// * `teff` - 有效温度
/// * `idisk` - 盘模型标志
/// * `lte` - LTE 标志
/// * `ltgrey` - LTGREY 标志
/// * `ielhm` - IELHM 参数
/// * `mdepth` - 最大深度点数
/// * `mlambd` - 最大 Lambda 点数
/// * `mmu` - 最大角度点数
///
/// # 返回
/// 解析后的输出状态
pub fn nstpar<R: std::io::BufRead>(
reader: &mut FortranReader<R>,
teff: f64,
idisk: i32,
lte: bool,
ltgrey: bool,
ielhm: i32,
mdepth: usize,
mlambd: usize,
mmu: usize,
) -> Result<NstparOutput> {
// 读取所有行
let mut lines: Vec<String> = Vec::new();
loop {
match reader.read_line() {
Ok(line) => {
// 跳过空行
if !line.trim().is_empty() {
lines.push(line.to_string());
}
}
Err(_) => break, // EOF
}
}
// 解析关键字-值对
let pvalue = parse_keyword_values(&lines);
// 创建参数结构
let mut params = NstparParams::from_values(&pvalue);
// 验证边界
if params.nd > mdepth as i32 {
return Err(super::IoError::FormatError(format!(
"nd ({}) > mdepth ({})",
params.nd, mdepth
)));
}
if params.ndgrey > mdepth as i32 {
return Err(super::IoError::FormatError(format!(
"ndgrey ({}) > mdepth ({})",
params.ndgrey, mdepth
)));
}
if params.nlambd > mlambd as i32 {
return Err(super::IoError::FormatError(format!(
"nlambd ({}) > mlambd ({})",
params.nlambd, mlambd
)));
}
if params.iacc <= 2 {
return Err(super::IoError::FormatError(format!(
"Ng too early: iacc = {}",
params.iacc
)));
}
if params.nmu > mmu as i32 {
return Err(super::IoError::FormatError(format!(
"nmu ({}) > mmu ({})",
params.nmu, mmu
)));
}
// 后处理
Ok(apply_nstpar_postprocessing(
&mut params,
teff,
idisk,
lte,
ltgrey,
ielhm,
mdepth,
mlambd,
mmu,
))
}
// ============================================================================
// 测试
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_params() {
let params = NstparParams::default();
assert_eq!(params.ibc, 3);
assert_eq!(params.ilmcor, 3);
assert!((params.djmax - 1e-3).abs() < 1e-10);
assert_eq!(params.iacc, 7);
assert_eq!(params.niter, 30);
}
#[test]
fn test_parse_empty_input() {
let lines: Vec<String> = vec![];
let pvalue = parse_keyword_values(&lines);
// 应该全部是默认值
assert_eq!(pvalue[0].trim(), "0"); // ISPLIN
assert_eq!(pvalue[2].trim(), "3"); // IBC
}
#[test]
fn test_parse_simple_keyword() {
let lines: Vec<String> = vec!["IBC = 5".to_string()];
let pvalue = parse_keyword_values(&lines);
// IBC 是第3个变量索引2
assert_eq!(pvalue[2].trim(), "5");
}
#[test]
fn test_parse_multiple_keywords() {
let lines: Vec<String> = vec![
"ISPLIN = 1".to_string(),
"IBC = 7".to_string(),
"NITER = 50".to_string(),
];
let pvalue = parse_keyword_values(&lines);
assert_eq!(pvalue[0].trim(), "1"); // ISPLIN
assert_eq!(pvalue[2].trim(), "7"); // IBC
assert_eq!(pvalue[63].trim(), "50"); // NITER (index 63)
}
#[test]
fn test_from_values() {
let mut values: [String; MVAR] = std::array::from_fn(|i| PVALUE_DEFAULT[i].to_string());
values[2] = " 7".to_string(); // IBC
values[63] = " 50".to_string(); // NITER (index 63)
let params = NstparParams::from_values(&values);
assert_eq!(params.ibc, 7);
assert_eq!(params.niter, 50);
}
#[test]
fn test_postprocessing_high_temp() {
let mut params = NstparParams::default();
let output = apply_nstpar_postprocessing(
&mut params,
20000.0, // teff > 15000
0, // idisk
false, // lte
false, // ltgrey
0, // ielhm
100, // mdepth
100, // mlambd
8, // mmu
);
// 高温时应关闭分子不透明度
assert_eq!(output.params.ioph2p, 0);
assert_eq!(output.params.iopch, 0);
assert_eq!(output.params.ioh2h2, 0);
}
#[test]
fn test_postprocessing_lte() {
let mut params = NstparParams::default();
params.nlambd = -5; // 负值表示均匀分布
let output = apply_nstpar_postprocessing(
&mut params,
10000.0,
0,
true, // lte
false,
0,
100,
100,
8,
);
// LTE 时 nlambd = 1
assert_eq!(output.params.nlambd, 1);
// IFLEV = 1
assert_eq!(output.params.iflev, 1);
}
#[test]
fn test_convection_params() {
let mut params = NstparParams::default();
params.mltype = 2;
let output = apply_nstpar_postprocessing(&mut params, 10000.0, 0, false, false, 0, 100, 100, 8);
assert!((output.aconml - 1.0).abs() < 1e-10);
assert!((output.bconml - 2.0).abs() < 1e-10);
}
#[test]
fn test_varnam_count() {
// 确保 VARNAM 和 PVALUE_DEFAULT 长度正确
assert_eq!(VARNAM.len(), MVAR);
assert_eq!(PVALUE_DEFAULT.len(), MVAR);
}
}