Files
SpectraRust/src/math/ratsp1.rs
T
fmqandClaude Opus 4.6 a086e313cb 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>
2026-03-25 01:46:29 +08:00

801 lines
26 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.
//! 预条件化辐射速率计算 - 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);
}
}