//! 模型参数初始化,用于 RESOLV。 //! //! 重构自 TLUSTY `inilam.f` //! //! # 功能 //! //! RESOLV 的辅助过程,初始化模型参数以供后续使用。 //! //! # 两个主要分支 //! //! 1. **INIT=1** (第一次完全线性化迭代前): //! - 计算所有跃迁、所有深度的碰撞速率 //! - 初始化 b 因子、固定电荷等 //! //! 2. **INIT≠1** (完全线性化迭代完成后): //! - 更新温度、电子密度、密度等 //! - 计算新的占据数 //! - 求解辐射转移方程 use crate::tlusty::state::constants::{BOLK, HALF, MDEPTH, MFREQ, MLEVEL, MTRANS, PCK, SIG4P, UN}; // f2r_depends: COLIS, COMSET, CONCOR, DIETOT, ELCOR, ODFMER, OPACF1, OPAINI, OSCCOR, OUTPUT, RATES1, RTECOM, RTEFR1, RYBHEQ, SABOLF, STEQEQ, TDPINI, VISINI, WNSTOR // ============================================================================ // 配置参数 // ============================================================================ /// INILAM 配置参数(只读)。 #[derive(Debug, Clone)] pub struct InilamConfig { /// 初始化标志 (1=第一次迭代前) pub init: i32, /// 迭代次数 pub iter: i32, /// LTE 模式标志 pub lte: bool, /// IPSLTE 参数 pub ipslte: i32, /// IDLTE 参数 pub idlte: i32, /// IOPABT 参数(选项表) pub ioptab: i32, /// IDISK 参数(盘模型) pub idisk: i32, /// 有效温度 (K) pub teff: f64, /// IFPOPR 参数 pub ifpopr: i32, /// IFRYB 参数 pub ifryb: i32, /// IOSCOR 参数(振荡修正) pub ioscor: i32, /// IHECOR 参数(流体静力平衡修正) pub ihecor: i32, /// IFIXDE 参数(固定密度) pub ifixde: i32, /// ISPLIN 参数 pub isplin: i32, /// IFDIEL 参数(双电子复合) pub ifdiel: i32, /// ICOMPT 参数(康普顿散射) pub icompt: i32, /// IPRIND 参数(打印控制) pub iprind: i32, /// LCHC 参数 pub lchc: bool, /// IELCOR 参数(电子修正迭代) pub ielcor: i32, /// INRE 参数(辐射平衡) pub inre: i32, /// INPC 参数(粒子守恒) pub inpc: i32, /// INHE 参数(流体静力平衡) pub inhe: i32, /// INMP 参数(大质量粒子) pub inmp: i32, /// INZD 参数(几何距离) pub inzd: i32, /// INDL 参数(温度对数梯度) pub indl: i32, /// NFREQE 参数(线性化频率数) pub nfreqe: usize, /// DPSILN 参数(密度变化限制) pub dpsiln: f64, } impl Default for InilamConfig { fn default() -> Self { Self { init: 1, iter: 0, lte: false, ipslte: 0, idlte: 100, ioptab: 0, idisk: 0, teff: 10000.0, ifpopr: 0, ifryb: 0, ioscor: 0, ihecor: 0, ifixde: 0, isplin: 0, ifdiel: 0, icompt: 0, iprind: 0, lchc: false, ielcor: 10, inre: 0, inpc: 0, inhe: 0, inmp: 0, inzd: 0, indl: 0, nfreqe: 0, dpsiln: 10.0_f64.exp(), // e^10 } } } // ============================================================================ // 模型状态参数 // ============================================================================ /// INILAM 模型状态参数。 #[derive(Debug)] pub struct InilamModelState<'a> { /// 深度点数 pub nd: usize, /// 能级数 pub nlevel: usize, /// 离子数 pub nion: usize, /// 跃迁数 pub ntrans: usize, /// 频率点数 pub nfreq: usize, // 深度相关数组 [nd] /// 柱质量密度 (g/cm²) pub dm: &'a [f64], /// 温度 (K) pub temp: &'a mut [f64], /// 电子密度 (cm⁻³) pub elec: &'a mut [f64], /// 总粒子密度 (cm⁻³) pub dens: &'a mut [f64], /// 总粒子数 pub totn: &'a mut [f64], /// 总原子密度 pub anto: &'a mut [f64], /// 金属原子密度 pub anma: &'a mut [f64], /// 气压 pub pgs: &'a mut [f64], /// 辐射压力导数 pub pradt: &'a mut [f64], /// 湍流速度 pub vturb: &'a [f64], /// 平均分子量 pub wmm: &'a [f64], // 能级相关数组 [nlevel × nd] /// 占据数 pub popul: &'a mut [f64], // [nlevel * nd] /// b 因子 pub bfac: &'a mut [f64], // [nlevel * nd] // 跃迁相关数组 [ntrans × nd] /// 碰撞速率 pub colrat: &'a mut [f64], // [ntrans * nd] /// 碰撞速率目标 pub coltar: &'a mut [f64], // [ntrans * nd] // 频率相关数组 [nfreq × nd] /// 辐射强度 pub rad: &'a mut [f64], // [nfreq * nd] // 辅助数组 /// FCOOL 数组 [nd] pub fcool: &'a mut [f64], /// FPRD 数组 [nd] pub fprd: &'a mut [f64], /// QFIX 数组 [nd] pub qfix: &'a mut [f64], // PSY0 数组 [总变量数 × nd] pub psy0: &'a [f64], // 气体压力 (用于 EOS) pub ptotal: &'a [f64], // 距离变量 pub zd: &'a mut [f64], // 温度梯度 pub delta: &'a mut [f64], } /// INILAM 原子参数。 #[derive(Debug)] pub struct InilamAtomicParams<'a> { /// 能级原子索引 [nlevel] pub iatm: &'a [i32], /// 能级离子索引 [nlevel] pub iel: &'a [i32], /// 能级类型 [nlevel] pub ilk: &'a [i32], /// 固定丰度标志 [natom] pub iifix: &'a [i32], /// 能级模型标志 [nlevel] pub imodl: &'a [i32], /// LTE 能级标志 [nlevel] pub iltlev: &'a [i32], /// 显式能级索引 [nlevel] pub iiexp: &'a [i32], /// 非零索引 [nlvexp] pub iinonz: &'a [i32], /// LTE 参考能级 [nlevel × nd] pub iltref: &'a [i32], /// SBPSI 数组 [nlevel × nd] pub sbpsi: &'a [f64], /// 离子电荷 [nion] pub iz: &'a [i32], /// 离子起始能级 [nion] pub nfirst: &'a [i32], /// 离子终止能级 [nion] pub nlast: &'a [i32], /// 下一个离子能级 [nion] pub nnext: &'a [i32], /// SBF 数组 [nlevel] pub sbf: &'a [f64], /// WOP 数组 [nlevel × nd] pub wop: &'a [f64], /// USUM 数组 [nion] pub usum: &'a [f64], } /// INILAM 频率参数。 #[derive(Debug)] pub struct InilamFreqParams<'a> { /// 频率数组 [nfreq] pub freq: &'a [f64], /// BNUE 数组 [nfreq] pub bnue: &'a [f64], /// FH 数组 [nfreq] pub fh: &'a [f64], /// HEXTRD 数组 [nfreq] pub hextrd: &'a [f64], /// 权重数组 [nfreq] pub w: &'a [f64], /// h/(kT) 数组 [nd] pub hkt1: &'a [f64], } /// INILAM 当前频率输出。 #[derive(Debug, Clone)] pub struct InilamFreqOutput { /// ABSO1 数组 [nd] pub abso1: Vec, /// RAD1 数组 [nd] pub rad1: Vec, /// FAK1 数组 [nd] pub fak1: Vec, } // ============================================================================ // 输出结构体 // ============================================================================ /// INILAM 输出结构体。 #[derive(Debug, Clone)] pub struct InilamOutput { /// PRAD 参数 pub prad: f64, /// PRD0 参数 pub prd0: f64, /// ANEREL 参数 pub anerel: f64, /// AMUV0 参数 pub amuv0: f64, /// AMUV1 参数 pub amuv1: f64, /// DMTOT 参数 pub dmtot: f64, /// EDISC 参数 pub edisc: f64, /// GRD 数组 [nd] pub grd: Vec, /// PRA 数组 [nd] pub pra: Vec, } impl Default for InilamOutput { fn default() -> Self { Self { prad: 0.0, prd0: 0.0, anerel: 0.5, amuv0: 0.0, amuv1: 1.0, dmtot: 0.0, edisc: 0.0, grd: vec![0.0; MDEPTH], pra: vec![0.0; MDEPTH], } } } // ============================================================================ // 辅助函数 // ============================================================================ /// 获取二维数组的元素(Fortran 列优先顺序)。 #[inline] fn get_2d(arr: &[T], i: usize, j: usize, nrows: usize) -> &T { &arr[j * nrows + i] } /// 获取二维数组的可变元素(Fortran 列优先顺序)。 #[inline] fn get_2d_mut(arr: &mut [T], i: usize, j: usize, nrows: usize) -> &mut T { &mut arr[j * nrows + i] } /// 设置二维数组的元素(Fortran 列优先顺序)。 #[inline] fn set_2d(arr: &mut [T], i: usize, j: usize, nrows: usize, val: T) { arr[j * nrows + i] = val; } // ============================================================================ // 主函数 // ============================================================================ /// INILAM 纯计算函数。 /// /// # 参数 /// - `config`: 配置参数 /// - `model`: 模型状态(会被修改) /// - `atomic`: 原子参数 /// - `freq`: 频率参数 /// /// # 返回值 /// 返回 InilamOutput 结构体 /// /// # 注意 /// 此函数仅实现核心计算逻辑,不包含 I/O 操作。 /// 外部函数调用(如 TDPINI、WNSTOR 等)需要通过回调实现。 pub fn inilam_pure( config: &InilamConfig, model: &mut InilamModelState, atomic: &InilamAtomicParams, freq: &InilamFreqParams, ) -> InilamOutput { let nd = model.nd; let nlevel = model.nlevel; let nion = model.nion; let ntrans = model.ntrans; let nfreq = model.nfreq; let mut output = InilamOutput::default(); output.grd.truncate(nd); output.grd.resize(nd, 0.0); output.pra.truncate(nd); output.pra.resize(nd, 0.0); // 初始化 ANEREL output.anerel = 0.5; if config.teff < 8000.0 { output.anerel = 0.01; } // ================================================================ // INIT = 1 分支:第一次迭代前 // ================================================================ if config.init == 1 { // 盘模型参数 if config.idisk == 1 { // AMUV0 = DMVISC**(ZETA0+UN) - 这里需要外部参数 // AMUV1 = UN - AMUV0 output.dmtot = model.dm[nd - 1]; // Fortran DM(ND) output.edisc = SIG4P * config.teff.powi(4) / output.dmtot; } // 对每个深度点进行初始化 for id in 0..nd { // FCOOL 和 FPRD 初始化 model.fcool[id] = 0.0; model.fprd[id] = 0.0; // 初始化 b 因子 for i in 0..nlevel { set_2d(&mut model.bfac, i, id, nlevel, UN); // SBW(I) = ELEC(ID) * SBF(I) * WOP(I,ID) let sbw = model.elec[id] * atomic.sbf[i] * *get_2d(atomic.wop, i, id, nlevel); // 如果非 LTE 且 IPSLTE=0 且 id < idlte if !config.lte && config.ipslte == 0 && id < config.idlte as usize { // 对每个离子 for ion in 0..nion { let nf = atomic.nfirst[ion] as usize; let nl = atomic.nlast[ion] as usize; let nn = atomic.nnext[ion] as usize; if nn > 0 && nn <= nlevel { let pop_next = *get_2d(model.popul, nn, id, nlevel); if pop_next > 0.0 && atomic.iltlev[i] == 0 { let pop_i = *get_2d(model.popul, i, id, nlevel); let bfac_val = pop_i / (pop_next * sbw); set_2d(&mut model.bfac, i, id, nlevel, bfac_val); } } } } } // 固定电荷部分 QFIX model.qfix[id] = 0.0; for i in 0..nlevel { let imodl = atomic.imodl[i]; let iatm = atomic.iatm[i] as usize; if imodl < 0 || (iatm < atomic.iifix.len() && atomic.iifix[iatm] > 0) { let mut ch = (atomic.iz[atomic.iel[i] as usize] - 1) as f64; let il = atomic.ilk[i]; if il > 0 { let il_usize = il as usize; ch = (atomic.iz[il_usize] as f64) + (atomic.iz[il_usize] as f64 - 1.0) * atomic.usum[il_usize] * model.elec[id]; } model.qfix[id] += ch * *get_2d(model.popul, i, id, nlevel); } } // 碰撞速率(非 LTE 情况) if !config.lte { // COLIS 调用需要外部实现 // 这里只初始化数组 for it in 0..ntrans { set_2d(&mut model.colrat, it, id, ntrans, 0.0); set_2d(&mut model.coltar, it, id, ntrans, 0.0); } } } // ISPLIN >= 5: 电子散射源函数的 Planck 函数估计 if config.isplin >= 5 { for id in 0..nd { for ij in 0..nfreq { let rad_val = freq.bnue[ij] / (freq.hkt1[id] * freq.freq[ij]).exp() - UN; set_2d(&mut model.rad, ij, id, nfreq, rad_val); } } } return output; } // ================================================================ // INIT ≠ 1 分支:迭代后更新 // ================================================================ // PRAD 初始化 output.prad = 0.0; // 工作数组 let mut xe = vec![0.0; nd]; let mut antc = vec![0.0; nd]; // 保存旧量并更新 for id in 0..nd { // AOLD = DENS(ID)/WMM(ID) + ELEC(ID) let aold = model.dens[id] / model.wmm[id] + model.elec[id]; xe[id] = UN - model.elec[id] / aold; // 更新温度(如果求解辐射平衡) if config.inre != 0 { let psy_idx = (config.nfreqe + config.inre as usize) * nd + id; if psy_idx < model.psy0.len() { model.temp[id] = model.psy0[psy_idx]; } } // 更新电子密度(如果求解粒子守恒) if config.inpc != 0 { let psy_idx = (config.nfreqe + config.inpc as usize) * nd + id; if psy_idx < model.psy0.len() { model.elec[id] = model.psy0[psy_idx]; } } // 更新总粒子数(如果求解流体静力平衡) if config.inhe != 0 { let psy_idx = (config.nfreqe + config.inhe as usize) * nd + id; if psy_idx < model.psy0.len() { model.totn[id] = model.psy0[psy_idx]; } } // 密度更新 if config.ifixde == 0 { let dens0 = model.dens[id]; if config.inhe != 0 { let psy_idx = (config.nfreqe + config.inhe as usize) * nd + id; if psy_idx < model.psy0.len() { model.dens[id] = model.wmm[id] * (model.psy0[psy_idx] - model.elec[id]); } let dplp = dens0 * config.dpsiln; let dplm = dens0 / config.dpsiln; if model.dens[id] > dplp { model.dens[id] = dplp; } if model.dens[id] < dplm { model.dens[id] = dplm; } } else if config.ioptab < -1 { model.pgs[id] = model.ptotal[id]; // DENS(ID) = RHOEOS(TEMP(ID), PGS(ID)) - 需要外部调用 } } // 大质量粒子密度更新 if config.inmp != 0 { let psy_idx = (config.nfreqe + config.inmp as usize) * nd + id; if psy_idx < model.psy0.len() { model.dens[id] = model.wmm[id] * model.psy0[psy_idx]; } } // 几何距离 if config.inzd > 0 { let psy_idx = (config.nfreqe + config.inzd as usize) * nd + id; if psy_idx < model.psy0.len() { model.zd[id] = model.psy0[psy_idx]; } } // 温度对数梯度 if config.indl != 0 { let psy_idx = (config.nfreqe + config.indl as usize) * nd + id; if psy_idx < model.psy0.len() { model.delta[id] = model.psy0[psy_idx]; } } // 更新 ANMA 和 ANTO model.anma[id] = model.dens[id] / model.wmm[id]; model.anto[id] = model.anma[id] + model.elec[id]; } // 流体静力平衡修正(如果需要) if config.ihecor >= 2 { // ID = 1 let ptur = HALF * model.vturb[0] * model.vturb[0] * model.dens[0]; antc[0] = (model.dm[0] * config.teff * 0.0 - output.prd0 - ptur) // GRAV 需要外部传入 / BOLK / model.temp[0]; if antc[0] <= 0.0 { antc[0] = model.dens[0] / model.wmm[0] + model.elec[0]; } for id in 1..nd { let ptur = HALF * model.vturb[id] * model.vturb[id] * model.dens[id]; let pturm = HALF * model.vturb[id - 1] * model.vturb[id - 1] * model.dens[id - 1]; // 简化计算,GRAV 需要外部传入 antc[id] = (model.temp[id - 1] * antc[id - 1] * BOLK - model.pradt[id] + model.pradt[id - 1] - ptur + pturm) / BOLK / model.temp[id]; } for id in 0..nd { model.elec[id] = (UN - xe[id]) * antc[id]; model.dens[id] = model.wmm[id] * (antc[id] - model.elec[id]); model.anma[id] = model.dens[id] / model.wmm[id]; model.anto[id] = model.anma[id] + model.elec[id]; } } // 更新 PGS for id in 0..nd { model.pgs[id] = (model.dens[id] / model.wmm[id] + model.elec[id]) * BOLK * model.temp[id]; } // IOPTAB >= 0 时的处理 if config.ioptab >= 0 { for id in 0..nd { // 碰撞速率更新(非 LTE) if !config.lte { for it in 0..ntrans { set_2d(&mut model.colrat, it, id, ntrans, 0.0); set_2d(&mut model.coltar, it, id, ntrans, 0.0); } } } } // 新占据数计算 // 分支 1: IFPOPR <= 0 或 LTE 或 IFRYB > 0 if config.ifpopr <= 0 || config.lte || config.ifryb > 0 { // RATES1 调用需要外部实现 // 深度遍历求解统计平衡 for id in 0..nd { // STEQEQ 和 ELCOR 需要外部实现 } } else { // 分支 2: 从线性化修正获取占据数 for id in 0..nd { for i in 0..nlevel { let iatm = atomic.iatm[i] as usize; if iatm < atomic.iifix.len() && atomic.iifix[iatm] != 1 { let ii = atomic.iiexp[i]; if ii > 0 { let iii = atomic.iinonz[ii as usize]; if iii > 0 { let psy_idx = (config.nfreqe + config.inre as usize + iii as usize - 1) * nd + id; if psy_idx < model.psy0.len() { set_2d(&mut model.popul, i, id, nlevel, model.psy0[psy_idx]); } } else { set_2d(&mut model.popul, i, id, nlevel, 0.0); } } else if ii < 0 { let iii = atomic.iinonz[(-ii) as usize]; if iii > 0 { let psy_idx = (config.nfreqe + config.inre as usize + iii as usize - 1) * nd + id; if psy_idx < model.psy0.len() { let pop_val = model.psy0[psy_idx] * *get_2d(atomic.sbpsi, i, id, nlevel); set_2d(&mut model.popul, i, id, nlevel, pop_val); } } else { set_2d(&mut model.popul, i, id, nlevel, 0.0); } } else { // II = 0 情况 let iltref_val = *get_2d(atomic.iltref, i, id, nlevel); if iltref_val >= 0 && (iltref_val as usize) < atomic.iiexp.len() { let ii_ref = atomic.iiexp[iltref_val as usize]; if ii_ref > 0 && (ii_ref as usize) < atomic.iinonz.len() { let iii = atomic.iinonz[ii_ref as usize]; if iii > 0 { let psy_idx = (config.nfreqe + config.inre as usize + iii as usize - 1) * nd + id; if psy_idx < model.psy0.len() { let pop_val = model.psy0[psy_idx] * *get_2d(atomic.sbpsi, i, id, nlevel); set_2d(&mut model.popul, i, id, nlevel, pop_val); } } else { set_2d(&mut model.popul, i, id, nlevel, 0.0); } } } } } } } } // 康普顿散射 if config.icompt > 0 { // OPAINI, COMSET, RTECOM 需要外部实现 } // 辐射转移求解 // OPAINI(1) for id in 0..nd { output.grd[id] = 0.0; output.pra[id] = 0.0; model.pradt[id] = 0.0; } output.prd0 = 0.0; // 频率循环(完整版本需要 OPACF1 和 RTEFR1 回调) for ij in 0..nfreq { // OPACF1(IJ) 和 RTEFR1(IJ) 需要外部实现 // 计算 GRD 和 PRA } // GRD(1) = PCK * GRD(1) / DENS(1) if nd > 0 && model.dens[0] != 0.0 { output.grd[0] = PCK * output.grd[0] / model.dens[0]; } // PRA 和 PRADT 更新 for id in 0..nd { output.pra[id] *= PCK; model.pradt[id] *= PCK; } // PGS 更新(非盘模型) if config.idisk == 0 { // 需要外部 GRAV 参数 // PGS(1) = DM(1) * (GRAV - GRD(1)) // PGS(ID) = PGS(ID-1) - PCK*GRD(ID) + GRAV*(DM(ID)-DM(ID-1)) } output } // ============================================================================ // 测试 // ============================================================================ #[cfg(test)] mod tests { use super::*; use approx::assert_relative_eq; #[test] fn test_inilam_config_default() { let config = InilamConfig::default(); assert_eq!(config.init, 1); assert!(!config.lte); assert_relative_eq!(config.teff, 10000.0); } #[test] fn test_inilam_output_default() { let output = InilamOutput::default(); assert_relative_eq!(output.prad, 0.0); assert_relative_eq!(output.anerel, 0.5); } #[test] fn test_inilam_init_branch() { let config = InilamConfig { init: 1, teff: 10000.0, ..Default::default() }; let nd = 3; let nlevel = 2; let nion = 1; let ntrans = 1; let nfreq = 2; let dm = vec![1e-4, 1e-3, 1e-2]; let mut temp = vec![10000.0, 15000.0, 20000.0]; let mut elec = vec![1e10, 1e11, 1e12]; let mut dens = vec![1e14, 1e15, 1e16]; let mut totn = vec![0.0; 3]; let mut anto = vec![0.0; 3]; let mut anma = vec![0.0; 3]; let mut pgs = vec![0.0; 3]; let mut pradt = vec![0.0; 3]; let vturb = vec![0.0; 3]; let wmm = vec![1.0; 3]; let mut popul = vec![0.5; nlevel * nd]; let mut bfac = vec![1.0; nlevel * nd]; let mut colrat = vec![0.0; ntrans * nd]; let mut coltar = vec![0.0; ntrans * nd]; let mut rad = vec![0.0; nfreq * nd]; let mut fcool = vec![0.0; 3]; let mut fprd = vec![0.0; 3]; let mut qfix = vec![0.0; 3]; let psy0 = vec![0.0; 100]; let ptotal = vec![0.0; 3]; let mut zd = vec![0.0; 3]; let mut delta = vec![0.0; 3]; let mut model = InilamModelState { nd, nlevel, nion, ntrans, nfreq, dm: &dm, temp: &mut temp, elec: &mut elec, dens: &mut dens, totn: &mut totn, anto: &mut anto, anma: &mut anma, pgs: &mut pgs, pradt: &mut pradt, vturb: &vturb, wmm: &wmm, popul: &mut popul, bfac: &mut bfac, colrat: &mut colrat, coltar: &mut coltar, rad: &mut rad, fcool: &mut fcool, fprd: &mut fprd, qfix: &mut qfix, psy0: &psy0, ptotal: &ptotal, zd: &mut zd, delta: &mut delta, }; let atomic = InilamAtomicParams { iatm: &[0, 0], iel: &[0, 0], ilk: &[0, 0], iifix: &[0], imodl: &[0, 0], iltlev: &[0, 0], iiexp: &[0, 0], iinonz: &[0], iltref: &[0; 6], sbpsi: &[1.0; 6], iz: &[1], nfirst: &[0], nlast: &[1], nnext: &[1], sbf: &[1.0, 1.0], wop: &[1.0; 6], usum: &[1.0], }; let freq_data = vec![1e14, 2e14]; let bnue = vec![1e-10, 2e-10]; let fh = vec![1.0, 1.0]; let hextrd = vec![0.0; 2]; let w = vec![0.5, 0.5]; let hkt1 = vec![4.8e-11 / 10000.0, 4.8e-11 / 15000.0, 4.8e-11 / 20000.0]; let freq = InilamFreqParams { freq: &freq_data, bnue: &bnue, fh: &fh, hextrd: &hextrd, w: &w, hkt1: &hkt1, }; let output = inilam_pure(&config, &mut model, &atomic, &freq); // INIT=1 分支应该返回 assert_relative_eq!(output.anerel, 0.5); // TEFF >= 8000 } #[test] fn test_inilam_cold_star() { // 冷星 (TEFF < 8000K) let config = InilamConfig { init: 1, teff: 6000.0, ..Default::default() }; assert!(config.teff < 8000.0); let output = InilamOutput::default(); // 对于冷星,anerel 应该是 0.01(在函数内部设置) } }