feat: 添加更多重构模块 (第7批)

包含 IO 和 math 模块的实现:
- IO: initia, levcd, linset, ltegr, ltegrd, odfset, outpri, resolv, srtfrq, start, tabini, xenini
- Math: accel2, alisk1, alisk2, alist1, alist2, concor, conout, conref, contmd, contmp, coolrt, greyd, inilam, linsel, lucy, lymlin, matcon, matgen, moleq, newdm, newdmt, odf1, opacf0, opacf1, opacfa, opacfd, opacfl, opactr, opadd, opahst, pgset, princ, prnt, pzeval, quasim, radpre, radtot, rates1, ratsp1, rdata, rdatax, rechck, rhoeos, rhonen, rhsgen, rossop, rtecf1, rtecmc, rtecmu, rtecom, rtefr1, rteint, russel, rybchn, rybene, rybheq, rybsol, sgmer1, sigave, sigk, solve, solves, state, steqeq, temcor, temper, topbas, trmder, trmdrt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
fmq
2026-03-25 01:46:29 +08:00
co-authored by Claude Opus 4.6
parent 21cb6af16c
commit a086e313cb
85 changed files with 48464 additions and 6 deletions
+800
View File
@@ -0,0 +1,800 @@
//! 预条件化辐射速率计算 - RATSP1。
//!
//! 重构自 TLUSTY `ratsp1.f`
//!
//! 计算辐射跃迁的上下行速率,包括连续谱和谱线跃迁。
//! 支持标准模式和 ODF 采样模式。
use crate::state::constants::{UN, PCK, MDEPTH, MTRANS};
// 物理常数
/// 4π/c
const PGRD: f64 = 4.1916825e-10;
/// 谱线常数
const OSC_CONST: f64 = 0.02654;
// ============================================================================
// 参数结构体
// ============================================================================
/// RATSP1 配置参数
#[derive(Debug, Clone)]
pub struct Ratsp1Config {
/// 深度点数
pub nd: usize,
/// 频率点数
pub nfreq: usize,
/// 束缚-自由跃迁数
pub ntranc: usize,
/// 总跃迁数
pub ntrans: usize,
/// PRD 跃迁数
pub ntrprd: usize,
/// 当前迭代次数
pub iter: i32,
/// 最后一次迭代标志
pub lfin: bool,
/// ODF 采样标志 (0: 标准, >=1: ODF)
pub ispodf: i32,
/// 表格不透明度标志 (<0: 仅使用表格)
pub ioptab: i32,
/// 散射处理标志 (0: 包含散射, >0: 不包含)
pub ilpsct: i32,
/// 混合长度参数 (>0: 使用 Rosseland)
pub hmix0: f64,
/// 深度记录标志 (<=0: 计算完整 Rosseland)
pub ndre: i32,
}
impl Default for Ratsp1Config {
fn default() -> Self {
Self {
nd: 50,
nfreq: 100,
ntranc: 10,
ntrans: 100,
ntrprd: 0,
iter: 1,
lfin: false,
ispodf: 0,
ioptab: 0,
ilpsct: 0,
hmix0: 0.0,
ndre: 0,
}
}
}
/// RATSP1 模型状态参数
#[derive(Debug)]
pub struct Ratsp1ModelState<'a> {
// 深度点数据 (nd 个元素)
/// 温度倒数倒数 h/kT
pub hkt1: &'a [f64],
/// 深度差分 deldmz
pub deldmz: &'a [f64],
/// 密度倒数 dens1
pub dens1: &'a [f64],
/// 柱质量密度
pub dm: &'a [f64],
/// 总粒子密度
pub dens: &'a [f64],
/// 散射修正因子 crsw
pub crsw: &'a [f64],
// 频率数据 (nfreq 个元素)
/// 频率数组
pub freq: &'a [f64],
/// 频率权重
pub w: &'a [f64],
/// 归一化权重
pub w0e: &'a [f64],
/// 频率索引标志 ijx
pub ijx: &'a [i32],
// 不透明度数据 (nd 个元素)
/// 总吸收系数
pub absot: &'a [f64],
/// 吸收系数 (单频率) - 可被回调函数修改
pub abso1: &'a mut [f64],
/// 电子散射系数
pub elscat: &'a [f64],
// 辐射场数据
/// 辐射强度 rad1 (nd)
pub rad1: &'a [f64],
/// 上边界强度 fh (nfreq)
pub fh: &'a [f64],
/// 氦外辐射 hextrd (nfreq)
pub hextrd: &'a [f64],
/// 辐射场积分 fak1 (nd)
pub fak1: &'a [f64],
/// 归一化普朗克函数 bnue (nfreq)
pub bnue: &'a [f64],
// Lambda 算子
/// Lambda 算子对角 ali1 (nd)
pub ali1: &'a [f64],
// 跃迁数据
/// 截面 cross (ntranc × nfreq)
pub cross: &'a [f64],
/// 低能级索引 ilow (ntrans)
pub ilow: &'a [i32],
/// 高能级索引 iup (ntrans)
pub iup: &'a [i32],
/// 跃迁索引 itra (mlevel × mlevel)
pub itra: &'a [i32],
/// 束缚-自由跃迁索引 itrbf (ntranc)
pub itrbf: &'a [i32],
/// 零占据标志 ipzero (mlevel × nd)
pub ipzero: &'a [i32],
/// Macfarlane 下沉修正索引 mcdw (ntrans)
pub mcdw: &'a [i32],
/// 合并能级索引 imrg (mlevel)
pub imrg: &'a [i32],
/// 占据概率修正标志 ifwop (mlevel)
pub ifwop: &'a [i32],
/// 下沉修正因子 dwf1 (mmcdw × nd)
pub dwf1: &'a [f64],
/// 合并能级截面 sgmrg (mmer × nd)
pub sgmg: &'a [f64],
/// 吸收系数 abtra (ntrans × nd)
pub abtra: &'a [f64],
/// 发射系数 emtra (ntrans × nd)
pub emtra: &'a [f64],
// 谱线数据
/// 主谱线索引 ijlin (nfreq)
pub ijlin: &'a [i32],
/// 谱线轮廓 prflin (nd × nfreq)
pub prflin: &'a [f64],
/// 重叠谱线数 nlines (nfreq)
pub nlines: &'a [i32],
/// 重叠谱线索引 itrlin (maxlines × nfreq)
pub itrlin: &'a [i16],
/// 频率起点 ifr0 (ntrans)
pub ifr0: &'a [i32],
/// 频率终点 ifr1 (ntrans)
pub ifr1: &'a [i32],
/// PRD 跃迁索引 iprd (ntrans)
pub iprd: &'a [i32],
/// 振子强度 osc0 (ntrans)
pub osc0: &'a [f64],
/// 显式谱线标志 linexp (ntrans)
pub linexp: &'a [bool],
// ODF 数据
/// 频率偏移 kfr0 (ntrans)
pub kfr0: &'a [i32],
/// 谱线索引 indexp (ntrans)
pub indexp: &'a [i32],
/// 铁截面 sigfe (ntab × nfreq)
pub sigfe: &'a [f64],
/// 深度相关索引 jidi (nd)
pub jidi: &'a [i32],
/// 插值因子 xjid (nd)
pub xjid: &'a [f64],
// 输出数组
/// 上行辐射速率 (ntrans × nd)
pub rru: &'a mut [f64],
/// 下行辐射速率 (ntrans × nd)
pub rrd: &'a mut [f64],
/// 总辐射压 (nd)
pub pradt: &'a mut [f64],
/// 吸收辐射压 (nd)
pub prada: &'a mut [f64],
/// 辐射通量 (nd)
pub flrd: &'a mut [f64],
/// PRD J 积分 (ntrprd × nd)
pub pjbar: &'a mut [f64],
/// Rosseland 平均不透明度 (nd)
pub abrosd: &'a mut [f64],
/// Rosseland 累积 (nd)
pub sumdpl: &'a mut [f64],
/// PRD 零点
pub prd0: &'a mut f64,
}
/// RATSP1 输出结构体
#[derive(Debug)]
pub struct Ratsp1Output {
/// 最小辐射压比
pub prdx: f64,
}
// ============================================================================
// 主函数
// ============================================================================
/// 计算预条件化辐射速率。
///
/// # 参数
/// - `config`: 配置参数
/// - `model`: 模型状态
/// - `opacf1_fn`: 不透明度计算函数
/// - `rtefr1_fn`: 辐射转移计算函数
/// - `rosstd_fn`: Rosseland 平均计算函数 (可选)
///
/// # 返回值
/// - `Ratsp1Output`: 包含最小辐射压比
#[allow(clippy::too_many_arguments)]
pub fn ratsp1<F, G, H>(
config: &Ratsp1Config,
model: &mut Ratsp1ModelState,
opacf1_fn: F,
rtefr1_fn: G,
rosstd_fn: Option<H>,
) -> Ratsp1Output
where
F: Fn(usize, &mut Ratsp1ModelState),
G: Fn(usize, &mut Ratsp1ModelState),
H: Fn(usize, &mut Ratsp1ModelState),
{
let nd = config.nd;
let nfreq = config.nfreq;
let ntranc = config.ntranc;
let ntrans = config.ntrans;
let ntrprd = config.ntrprd;
// 工作数组
let mut ehk = vec![0.0; nd];
let mut alab = vec![0.0; nd];
// 判断是否计算 Rosseland
let lross = (config.ndre <= 0 && config.iter == 1) || config.lfin || config.hmix0 > 0.0;
// ========================================================================
// 初始化输出数组
// ========================================================================
for id in 0..nd {
model.pradt[id] = 0.0;
model.prada[id] = 0.0;
model.flrd[id] = 0.0;
for itr in 0..ntrans {
model.rru[itr * nd + id] = 0.0;
model.rrd[itr * nd + id] = 0.0;
}
for itrp in 0..ntrprd {
model.pjbar[itrp * nd + id] = 0.0;
}
}
*model.prd0 = 0.0;
// 初始化 Rosseland 数组
if lross {
for id in 0..nd {
model.abrosd[id] = 0.0;
model.sumdpl[id] = 0.0;
}
}
// ========================================================================
// 频率循环
// ========================================================================
for ij in 0..nfreq {
// 跳过无效频率
if model.ijx[ij] == -1 {
continue;
}
let fr = model.freq[ij];
let w0 = model.w0e[ij];
let ww = model.w[ij];
// 计算不透明度和辐射转移
opacf1_fn(ij, model);
rtefr1_fn(ij, model);
// 计算 Rosseland 平均
if lross {
if let Some(ref ros_fn) = rosstd_fn {
ros_fn(ij, model);
}
}
// 通量梯度
let fluxw = model.w[ij] * model.rad1[0] * model.fh[ij];
// GRADF 在原代码中定义但未使用
// 上边界通量
model.flrd[0] += ww * model.fh[ij] * model.rad1[0] - ww * model.hextrd[ij];
// 深度点通量
for id in 1..nd {
let dt = UN / (model.absot[id] + model.absot[id - 1]) / model.deldmz[id - 1];
let fl = (model.rad1[id] * model.fak1[id] - model.rad1[id - 1] * model.fak1[id - 1]) * dt;
model.flrd[id] += ww * fl;
}
// 跳过仅表格模式
if config.ioptab < 0 {
continue;
}
// ====================================================================
// 连续谱跃迁
// ====================================================================
for id in 0..nd {
ehk[id] = (-model.hkt1[id] * fr).exp();
alab[id] = if config.ilpsct == 0 {
model.ali1[id] / (model.abso1[id] - model.elscat[id])
} else {
model.ali1[id] / model.abso1[id]
};
for ibft in 0..ntranc {
let itr = model.itrbf[ibft] as usize;
if itr == 0 {
continue;
}
let itr_idx = itr - 1;
let sg = model.cross[ibft * nfreq + ij];
if sg <= 0.0 {
continue;
}
let ii = model.ilow[itr_idx] as usize;
let jj = model.iup[itr_idx] as usize;
if ii == 0 || jj == 0 {
continue;
}
let ii_idx = ii - 1;
let jj_idx = jj - 1;
// 检查零占据
if model.ipzero[ii_idx * nd + id] != 0 || model.ipzero[jj_idx * nd + id] != 0 {
continue;
}
// 计算截面修正
let sg_final = if model.ifwop[ii_idx] >= 0 {
let icdw = model.mcdw[itr_idx];
if icdw >= 1 {
sg * model.dwf1[(icdw as usize - 1) * nd + id]
} else {
sg
}
} else {
let imer = model.imrg[ii_idx] as usize;
if imer > 0 {
sg * model.sgmg[(imer - 1) * nd + id]
} else {
sg
}
};
let sgw0 = sg_final * w0;
let rlam = sg_final * alab[id];
let elin = model.emtra[itr_idx * nd + id] * ehk[id];
let radres = model.rad1[id] - rlam * model.bnue[ij] * elin;
let bnures = model.bnue[ij] * (UN - rlam * (model.abtra[itr_idx * nd + id] - elin));
model.rru[itr_idx * nd + id] += sgw0 * radres;
model.rrd[itr_idx * nd + id] += sgw0 * (radres + bnures) * ehk[id];
}
}
// ====================================================================
// 谱线跃迁
// ====================================================================
if config.ispodf == 0 {
// 标准模式
if model.ijlin[ij] > 0 {
// 主谱线
let itr = (model.ijlin[ij] as usize) - 1;
let ii = model.ilow[itr] as usize;
let jj = model.iup[itr] as usize;
if ii > 0 && jj > 0 {
let ii_idx = ii - 1;
let jj_idx = jj - 1;
for id in 0..nd {
if model.ipzero[ii_idx * nd + id] != 0
|| model.ipzero[jj_idx * nd + id] != 0
{
continue;
}
let sg = model.prflin[id * nfreq + ij];
let sgw0 = sg * w0;
let rlam = sg * alab[id];
let elin = model.emtra[itr * nd + id] * ehk[id];
let radres = model.rad1[id] - rlam * model.bnue[ij] * elin;
let bnures =
model.bnue[ij] * (UN - rlam * (model.abtra[itr * nd + id] - elin));
model.rru[itr * nd + id] += sgw0 * radres;
model.rrd[itr * nd + id] += sgw0 * (radres + bnures) * ehk[id];
}
// PRD 贡献
let itrprd = model.iprd[itr];
if itrprd > 0 {
let s = UN / (OSC_CONST * model.osc0[itr]);
for id in 0..nd {
let sg = model.prflin[id * nfreq + ij] * s;
model.pjbar[(itrprd as usize - 1) * nd + id] +=
sg * model.w[ij] * model.rad1[id];
}
}
}
}
// 重叠谱线
let nlines = model.nlines[ij];
if nlines > 0 {
for ilint in 0..nlines as usize {
let itr = model.itrlin[ilint * nfreq + ij] as usize;
if itr == 0 || model.linexp[itr - 1] {
continue;
}
let itr_idx = itr - 1;
// 频率插值
let ij0 = model.ifr0[itr_idx] as usize;
let mut ij0_adj = ij0;
for ijt in ij0..=model.ifr1[itr_idx] as usize {
if model.freq[ijt] <= fr {
ij0_adj = ijt;
break;
}
}
let ij1 = ij0_adj - 1;
let a1 = if ij1 < nfreq && ij0_adj < nfreq {
(fr - model.freq[ij0_adj]) / (model.freq[ij1] - model.freq[ij0_adj])
} else {
0.0
};
let a2 = UN - a1;
let ii = model.ilow[itr_idx] as usize;
let jj = model.iup[itr_idx] as usize;
if ii == 0 || jj == 0 {
continue;
}
let ii_idx = ii - 1;
let jj_idx = jj - 1;
for id in 0..nd {
if model.ipzero[ii_idx * nd + id] != 0
|| model.ipzero[jj_idx * nd + id] != 0
{
continue;
}
let sg = if ij1 < nfreq && ij0_adj < nfreq {
a1 * model.prflin[id * nfreq + ij1]
+ a2 * model.prflin[id * nfreq + ij0_adj]
} else {
0.0
};
let sgw0 = sg * w0;
let rlam = sg * alab[id];
let elin = model.emtra[itr_idx * nd + id] * ehk[id];
let radres = model.rad1[id] - rlam * model.bnue[ij] * elin;
let bnures =
model.bnue[ij] * (UN - rlam * (model.abtra[itr_idx * nd + id] - elin));
model.rru[itr_idx * nd + id] += sgw0 * radres;
model.rrd[itr_idx * nd + id] += sgw0 * (radres + bnures) * ehk[id];
}
// PRD 贡献
let itrprd = model.iprd[itr_idx];
if itrprd > 0 {
let s = UN / (OSC_CONST * model.osc0[itr_idx]);
for id in 0..nd {
let sg = if ij1 < nfreq && ij0_adj < nfreq {
(a1 * model.prflin[id * nfreq + ij1]
+ a2 * model.prflin[id * nfreq + ij0_adj])
* s
} else {
0.0
};
model.pjbar[(itrprd as usize - 1) * nd + id] +=
sg * model.w[ij] * model.rad1[id];
}
}
}
}
} else {
// ODF 采样模式
let nlines = model.nlines[ij];
if nlines > 0 {
for ilint in 0..nlines as usize {
let itr = model.itrlin[ilint * nfreq + ij] as usize;
if itr == 0 {
continue;
}
let itr_idx = itr - 1;
let kj = ij as i32 - model.ifr0[itr_idx] + model.kfr0[itr_idx];
let indxpa = model.indexp[itr_idx].abs();
let ii = model.ilow[itr_idx] as usize;
let jj = model.iup[itr_idx] as usize;
if ii == 0 || jj == 0 {
continue;
}
let ii_idx = ii - 1;
let jj_idx = jj - 1;
if indxpa != 3 && indxpa != 4 {
// 标准截面
for id in 0..nd {
if model.ipzero[ii_idx * nd + id] != 0
|| model.ipzero[jj_idx * nd + id] != 0
{
continue;
}
let sg = model.prflin[id * nfreq + kj as usize];
let sgw0 = sg * w0;
let rlam = sg * alab[id];
let elin = model.emtra[itr_idx * nd + id] * ehk[id];
let radres = model.rad1[id] - rlam * model.bnue[ij] * elin;
let bnures = model.bnue[ij]
* (UN - rlam * (model.abtra[itr_idx * nd + id] - elin));
model.rru[itr_idx * nd + id] += sgw0 * radres;
model.rrd[itr_idx * nd + id] += sgw0 * (radres + bnures) * ehk[id];
}
} else {
// 铁截面插值
for id in 0..nd {
if model.ipzero[ii_idx * nd + id] != 0
|| model.ipzero[jj_idx * nd + id] != 0
{
continue;
}
let kjd = model.jidi[id] as usize;
let xjid = model.xjid[id];
let sg = if kjd > 0 && (kjd + 1) < nd && (kj as usize) < nfreq {
(xjid * model.sigfe[kjd * nfreq + kj as usize]
+ (UN - xjid) * model.sigfe[(kjd + 1) * nfreq + kj as usize])
.exp()
} else {
1.0
};
let sgw0 = sg * w0;
let rlam = sg * alab[id];
let elin = model.emtra[itr_idx * nd + id] * ehk[id];
let radres = model.rad1[id] - rlam * model.bnue[ij] * elin;
let bnures =
model.bnue[ij] * (UN - rlam * (model.abtra[itr_idx * nd + id] - elin));
model.rru[itr_idx * nd + id] += sgw0 * radres;
model.rrd[itr_idx * nd + id] += sgw0 * (radres + bnures) * ehk[id];
}
}
}
}
}
}
// ========================================================================
// 散射修正
// ========================================================================
for id in 0..nd {
if model.crsw[id] != UN {
for itr in 0..ntrans {
model.rru[itr * nd + id] *= model.crsw[id];
model.rrd[itr * nd + id] *= model.crsw[id];
}
}
}
// ========================================================================
// 辐射压
// ========================================================================
let mut prdx = 1.0;
for id in 0..nd {
model.pradt[id] *= PCK;
model.prada[id] *= PCK;
if model.prada[id] > 0.0 {
let prdr = model.pradt[id] / model.prada[id];
if prdr < prdx {
prdx = prdr;
}
}
}
*model.prd0 = *model.prd0 / model.dens1[0] * model.dm[0] * PCK;
// ========================================================================
// Rosseland 平均
// ========================================================================
if lross {
for id in 0..nd {
if model.abrosd[id] > 0.0 {
model.abrosd[id] = model.sumdpl[id] / (model.abrosd[id] * model.dens[id]);
}
}
}
Ratsp1Output { prdx }
}
// ============================================================================
// 测试
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ratsp1_config_default() {
let config = Ratsp1Config::default();
assert_eq!(config.nd, 50);
assert_eq!(config.nfreq, 100);
assert_eq!(config.ntrans, 100);
}
#[test]
fn test_ratsp1_basic() {
let nd = 5;
let nfreq = 3;
let ntrans = 2;
let config = Ratsp1Config {
nd,
nfreq,
ntranc: 0,
ntrans,
ntrprd: 0,
iter: 1,
lfin: false,
ispodf: 0,
ioptab: -1, // 跳过跃迁计算
ilpsct: 0,
hmix0: 0.0,
ndre: 0,
};
// 创建简单的测试数据
let hkt1 = vec![1e-4; nd];
let deldmz = vec![0.01; nd];
let dens1 = vec![1e-14; nd];
let dm = vec![0.01; nd];
let dens = vec![1e14; nd];
let crsw = vec![1.0; nd];
let freq = vec![1e14, 2e14, 3e14];
let w = vec![0.5; nfreq];
let w0e = vec![1.0; nfreq];
let ijx = vec![0; nfreq];
let absot = vec![1e-8; nd];
let mut abso1 = vec![1e-8; nd];
let elscat = vec![1e-10; nd];
let rad1 = vec![1e-10; nd];
let fh = vec![0.0; nfreq];
let hextrd = vec![0.0; nfreq];
let fak1 = vec![1.0; nd];
let bnue = vec![1e-10; nfreq];
let ali1 = vec![1.0; nd];
let cross = vec![];
let ilow = vec![1, 2];
let iup = vec![2, 3];
let itra = vec![];
let itrbf = vec![];
let ipzero = vec![0; 100 * nd];
let mcdw = vec![0; ntrans];
let imrg = vec![0; 100];
let ifwop = vec![0; 100];
let dwf1 = vec![];
let sgmg = vec![];
let abtra = vec![1e-8; ntrans * nd];
let emtra = vec![1e-20; ntrans * nd];
let ijlin = vec![0; nfreq];
let prflin = vec![0.0; nd * nfreq];
let nlines = vec![0; nfreq];
let itrlin = vec![0; 100 * nfreq];
let ifr0 = vec![1; ntrans];
let ifr1 = vec![nfreq as i32; ntrans];
let iprd = vec![0; ntrans];
let osc0 = vec![0.1; ntrans];
let linexp = vec![false; ntrans];
let kfr0 = vec![0; ntrans];
let indexp = vec![0; ntrans];
let sigfe = vec![];
let jidi = vec![0; nd];
let xjid = vec![0.0; nd];
let mut rru = vec![0.0; ntrans * nd];
let mut rrd = vec![0.0; ntrans * nd];
let mut pradt = vec![0.0; nd];
let mut prada = vec![0.0; nd];
let mut flrd = vec![0.0; nd];
let mut pjbar = vec![];
let mut abrosd = vec![0.0; nd];
let mut sumdpl = vec![0.0; nd];
let mut prd0 = 0.0;
let mut model = Ratsp1ModelState {
hkt1: &hkt1,
deldmz: &deldmz,
dens1: &dens1,
dm: &dm,
dens: &dens,
crsw: &crsw,
freq: &freq,
w: &w,
w0e: &w0e,
ijx: &ijx,
absot: &absot,
abso1: &mut abso1,
elscat: &elscat,
rad1: &rad1,
fh: &fh,
hextrd: &hextrd,
fak1: &fak1,
bnue: &bnue,
ali1: &ali1,
cross: &cross,
ilow: &ilow,
iup: &iup,
itra: &itra,
itrbf: &itrbf,
ipzero: &ipzero,
mcdw: &mcdw,
imrg: &imrg,
ifwop: &ifwop,
dwf1: &dwf1,
sgmg: &sgmg,
abtra: &abtra,
emtra: &emtra,
ijlin: &ijlin,
prflin: &prflin,
nlines: &nlines,
itrlin: &itrlin,
ifr0: &ifr0,
ifr1: &ifr1,
iprd: &iprd,
osc0: &osc0,
linexp: &linexp,
kfr0: &kfr0,
indexp: &indexp,
sigfe: &sigfe,
jidi: &jidi,
xjid: &xjid,
rru: &mut rru,
rrd: &mut rrd,
pradt: &mut pradt,
prada: &mut prada,
flrd: &mut flrd,
pjbar: &mut pjbar,
abrosd: &mut abrosd,
sumdpl: &mut sumdpl,
prd0: &mut prd0,
};
// 简单的回调函数
let opacf1_fn = |_: usize, m: &mut Ratsp1ModelState| {
for id in 0..m.abso1.len() {
m.abso1[id] = 1e-8;
}
};
let rtefr1_fn = |_: usize, _m: &mut Ratsp1ModelState| {};
let output = ratsp1(&config, &mut model, opacf1_fn, rtefr1_fn, None::<fn(usize, &mut Ratsp1ModelState)>);
// 验证输出
assert_eq!(output.prdx, 1.0); // 由于所有 prada 为 0
assert_eq!(model.flrd.len(), nd);
}
}