180 lines
4.9 KiB
Rust
180 lines
4.9 KiB
Rust
//! 温度依赖量初始化。
|
|
//!
|
|
//! 重构自 TLUSTY `tdpini.f`
|
|
|
|
use crate::state::config::BasNum;
|
|
use crate::state::constants::{HALF, H, HK, MDEPTH, UN};
|
|
use crate::state::model::{CurOpa, GffPar, ModPar};
|
|
|
|
use super::gfree0;
|
|
|
|
// ============================================================================
|
|
// TDPINI - 温度依赖量初始化
|
|
// ============================================================================
|
|
|
|
/// 初始化仅依赖温度的量。
|
|
///
|
|
/// # 参数
|
|
///
|
|
/// - `basnum` - 基本数值
|
|
/// - `modpar` - 模型参数 (会被修改)
|
|
/// - `gffpar` - Gaunt 因子参数 (会被修改)
|
|
/// - `curopa` - 当前不透明度 (会被修改)
|
|
///
|
|
/// # Fortran 原始代码
|
|
///
|
|
/// ```fortran
|
|
/// SUBROUTINE TDPINI
|
|
/// DO ID=1,ND
|
|
/// T=TEMP(ID)
|
|
/// T1=UN/T
|
|
/// HKT1(ID)=HK*T1
|
|
/// HKT21(ID)=HKT1(ID)*T1
|
|
/// TK1(ID)=HKT1(ID)/H
|
|
/// SQT1(ID)=SQRT(T)
|
|
/// TEMP1(ID)=T1
|
|
/// CALL GFREE0(ID)
|
|
/// EMEL1(ID)=UN
|
|
/// END DO
|
|
/// DO ID=1,ND-1
|
|
/// DELDM(ID)=HALF*(DM(ID+1)-DM(ID))
|
|
/// deldmz(id)=deldm(id)
|
|
/// if(izscal.eq.1) deldmz(id)=half*(zd(id)-zd(id+1))
|
|
/// END DO
|
|
/// DEDM1=DM(1)/DENS(1)
|
|
/// END
|
|
/// ```
|
|
pub fn tdpini(
|
|
basnum: &BasNum,
|
|
modpar: &mut ModPar,
|
|
gffpar: &mut GffPar,
|
|
curopa: &mut CurOpa,
|
|
) {
|
|
let nd = basnum.nd as usize;
|
|
let izscal = basnum.izscal;
|
|
|
|
// 温度依赖量
|
|
for id in 0..nd {
|
|
let t = modpar.temp[id];
|
|
let t1 = UN / t;
|
|
|
|
modpar.hkt1[id] = HK * t1;
|
|
modpar.hkt21[id] = modpar.hkt1[id] * t1;
|
|
modpar.tk1[id] = modpar.hkt1[id] / H;
|
|
modpar.sqt1[id] = t.sqrt();
|
|
modpar.temp1[id] = t1;
|
|
|
|
// Gaunt 因子初始化
|
|
gfree0(id, &modpar.temp, gffpar);
|
|
|
|
// 电子发射系数初始化
|
|
curopa.emel1[id] = UN;
|
|
}
|
|
|
|
// 深度差分 (用于光学深度评估)
|
|
for id in 0..(nd - 1) {
|
|
modpar.deldm[id] = HALF * (modpar.dm[id + 1] - modpar.dm[id]);
|
|
modpar.deldmz[id] = modpar.deldm[id];
|
|
|
|
// 如果使用几何深度缩放
|
|
if izscal == 1 {
|
|
modpar.deldmz[id] = HALF * (modpar.zd[id] - modpar.zd[id + 1]);
|
|
}
|
|
}
|
|
|
|
// 第一个深度的密度/质量比
|
|
modpar.dedm1 = modpar.dm[0] / modpar.dens[0];
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn create_test_data() -> (BasNum, ModPar, GffPar, CurOpa) {
|
|
let mut basnum = BasNum::default();
|
|
basnum.nd = 5;
|
|
basnum.izscal = 0;
|
|
|
|
let mut modpar = ModPar::default();
|
|
// 设置温度和密度
|
|
for id in 0..5 {
|
|
modpar.temp[id] = 10000.0 + id as f64 * 1000.0;
|
|
modpar.dm[id] = (id + 1) as f64 * 0.1;
|
|
modpar.dens[id] = 1e-7;
|
|
}
|
|
|
|
let gffpar = GffPar::new();
|
|
let curopa = CurOpa::default();
|
|
|
|
(basnum, modpar, gffpar, curopa)
|
|
}
|
|
|
|
#[test]
|
|
fn test_tdpini_basic() {
|
|
let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data();
|
|
|
|
tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa);
|
|
|
|
// 检查温度相关量
|
|
let t0 = 10000.0;
|
|
let t1 = UN / t0;
|
|
|
|
assert!((modpar.hkt1[0] - HK * t1).abs() < 1e-10);
|
|
assert!((modpar.sqt1[0] - t0.sqrt()).abs() < 1e-10);
|
|
assert!((modpar.temp1[0] - t1).abs() < 1e-10);
|
|
}
|
|
|
|
#[test]
|
|
fn test_tdpini_delta_m() {
|
|
let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data();
|
|
|
|
tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa);
|
|
|
|
// 检查深度差分
|
|
// DELDM[0] = 0.5 * (DM[1] - DM[0]) = 0.5 * (0.2 - 0.1) = 0.05
|
|
assert!((modpar.deldm[0] - 0.05).abs() < 1e-10);
|
|
assert!((modpar.deldmz[0] - 0.05).abs() < 1e-10); // izscal = 0
|
|
}
|
|
|
|
#[test]
|
|
fn test_tdpini_emel1() {
|
|
let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data();
|
|
|
|
tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa);
|
|
|
|
// 检查 EMEL1 被初始化为 1
|
|
for id in 0..basnum.nd as usize {
|
|
assert!((curopa.emel1[id] - UN).abs() < 1e-10);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_tdpini_dedm1() {
|
|
let (basnum, mut modpar, mut gffpar, mut curopa) = create_test_data();
|
|
|
|
tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa);
|
|
|
|
// DEDM1 = DM[0] / DENS[0] = 0.1 / 1e-7 = 1e6
|
|
let expected = 0.1 / 1e-7;
|
|
assert!((modpar.dedm1 - expected).abs() < 1e-5);
|
|
}
|
|
|
|
#[test]
|
|
fn test_tdpini_with_zscal() {
|
|
let (mut basnum, mut modpar, mut gffpar, mut curopa) = create_test_data();
|
|
basnum.izscal = 1;
|
|
|
|
// 设置几何深度
|
|
for id in 0..5 {
|
|
modpar.zd[id] = (5 - id) as f64 * 1e5; // 从表面向内递减
|
|
}
|
|
|
|
tdpini(&basnum, &mut modpar, &mut gffpar, &mut curopa);
|
|
|
|
// 检查使用几何深度计算的 DELDMZ
|
|
// DELDMZ[0] = 0.5 * (ZD[0] - ZD[1]) = 0.5 * (5e5 - 4e5) = 5e4
|
|
let expected_z = 0.5 * (5e5 - 4e5);
|
|
assert!((modpar.deldmz[0] - expected_z).abs() < 1e-5);
|
|
}
|
|
}
|