Files
SpectraRust/src/math/conref.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

963 lines
27 KiB
Rust

//! 对流区温度修正。
//!
//! 重构自 TLUSTY `conref.f`
//!
//! # 功能
//!
//! 对对流区进行温度修正:
//! - 计算各深度点的温度梯度 DELTA
//! - 使用混合长度理论计算对流通量
//! - 迭代修正温度以满足能量守恒
//! - 处理辐射/对流通量分配
use crate::state::constants::{HALF, SIG4P, UN};
// ============================================================================
// 常量
// ============================================================================
/// 2/3 (用于幂次计算)
const TWO_THR: f64 = 0.6666666666666667;
/// 1/3 (用于幂次计算)
const ONE_THR: f64 = 0.3333333333333333;
// ============================================================================
// 配置结构体
// ============================================================================
/// CONREF 配置参数。
#[derive(Debug, Clone)]
pub struct ConrefConfig {
/// 混合长度参数 (HMIX0)
pub hmix0: f64,
/// 对流模式 (ICONV)
pub iconv: i32,
/// 深度标志 (INDL)
pub indl: i32,
/// 对流通量限制 (CRFLIM)
pub crflim: f64,
/// 深对流模式 (IDEEPC)
pub ideepc: i32,
/// 对流区间隙允许 (NDCGAP)
pub ndcgap: i32,
/// 最小对流深度 (IDCONZ)
pub idconz: i32,
/// 对数梯度标志 (ILGDER)
pub ilgder: i32,
/// 盘模式标志 (IDISK)
pub idisk: i32,
/// 不透明度表标志 (IOPTAB)
pub ioptab: i32,
/// Rybicki 标志 (IFRYB)
pub ifryb: i32,
/// 迭代计数 (ITER)
pub iter: i32,
/// IMUCON 迭代阈值
pub imucon: i32,
/// 打印标志 (IPCONF)
pub ipconf: i32,
/// 表面重力 (GRAV)
pub grav: f64,
/// 盘引力参数 (QGRAV)
pub qgrav: f64,
/// 对流常数 A (ACONML)
pub aconml: f64,
/// 对流常数 B (BCONML)
pub bconml: f64,
/// 对流常数 C (CCONML)
pub cconml: f64,
}
impl Default for ConrefConfig {
fn default() -> Self {
Self {
hmix0: 1.0,
iconv: 0,
indl: 0,
crflim: 0.1,
ideepc: 0,
ndcgap: 2,
idconz: 25,
ilgder: 0,
idisk: 0,
ioptab: 0,
ifryb: 0,
iter: 0,
imucon: 9999,
ipconf: 0,
grav: 1e4,
qgrav: 0.0,
aconml: 1.0,
bconml: 1.0,
cconml: 1.0,
}
}
}
// ============================================================================
// 输入/输出结构体
// ============================================================================
/// CONREF 输入参数。
pub struct ConrefParams<'a> {
/// 深度点数 (ND)
pub nd: usize,
/// 有效温度 (TEFF)
pub teff: f64,
/// 配置
pub config: ConrefConfig,
// 深度相关数组 (nd)
/// 温度 (TEMP)
pub temp: &'a mut [f64],
/// 总压力 (PTOTAL)
pub ptotal: &'a [f64],
/// 气压 (PGS)
pub pgs: &'a [f64],
/// 总粒子密度 (DENS)
pub dens: &'a [f64],
/// 湍流速度 (VTURB)
pub vturb: &'a [f64],
/// Rosseland 不透明度 (ABROSD)
pub abrosd: &'a [f64],
/// 辐射通量 (FLRD)
pub flrd: &'a [f64],
/// 对流通量 (FLXC) - 输出
pub flxc: &'a mut [f64],
/// Delta 温度梯度 (DELTA) - 输出
pub delta: &'a mut [f64],
/// 分子质量 (WMM)
pub wmm: &'a [f64],
/// 电子密度 (ELEC)
pub elec: &'a mut [f64],
// 盘模式特定
/// 角速度参数 (THETAV)
pub thetav: &'a [f64],
/// 几何深度 (ZD)
pub zd: &'a [f64],
}
/// CUBCON 通用块数据 (对流计算中间量)。
#[derive(Debug, Clone, Default)]
pub struct CubconData {
/// 对流常数 A
pub a: f64,
/// 对流常数 B (BCNV)
pub b: f64,
/// 有效梯度差
pub del: f64,
/// 绝热梯度 (GRDADB)
pub grdadb: f64,
/// 中间变量
pub delmde: f64,
/// 密度
pub rho: f64,
/// 总通量
pub flxtot: f64,
/// 引力加速度
pub gravd: f64,
}
/// CONREF 输出结果。
#[derive(Debug, Clone)]
pub struct ConrefOutput {
/// 对流区起始深度 (ICBEG, 1-based)
pub icbeg: usize,
/// 对流区结束深度 (ICEND, 1-based)
pub icend: usize,
/// 是否进行了修正
pub modified: bool,
}
// ============================================================================
// 核心计算函数
// ============================================================================
/// 对流区温度修正 (CONREF)。
///
/// # 参数
///
/// * `params` - 输入参数
///
/// # 返回值
///
/// 返回 `ConrefOutput`,包含对流区范围和修正状态。
///
/// # Fortran 原始代码
///
/// ```fortran
/// SUBROUTINE CONREF
/// INCLUDE 'IMPLIC.FOR'
/// INCLUDE 'BASICS.FOR'
/// INCLUDE 'MODELQ.FOR'
/// INCLUDE 'ARRAY1.FOR'
/// COMMON/CUBCON/ACNV,BCNV,DEL,GRDADB,DELMDE,RHO,FLXTOT,GRAVD
/// ...
/// END
/// ```
pub fn conref_pure(params: &mut ConrefParams) -> ConrefOutput {
let nd = params.nd;
let config = &params.config.clone();
// 检查是否需要处理
if config.iconv <= 0 && config.indl == 0 {
return ConrefOutput {
icbeg: 0,
icend: 0,
modified: false,
};
}
// 计算表面总通量
let flxto0 = SIG4P * params.teff.powi(4);
let dltnd = params.delta[nd - 1];
// 临时数组
let mut idcon = vec![0i32; nd];
let mut flxtt = vec![0.0f64; nd];
let mut delta0 = vec![0.0f64; nd];
// 保存初始 delta
for id in 0..nd {
delta0[id] = params.delta[id];
}
// 第一遍:计算对流梯度
let mut icbeg: usize = 0;
let mut icend: usize = 0;
let mut cubcon = CubconData::default();
for id in 1..nd {
let t = params.temp[id];
let p = params.ptotal[id];
let pg = params.pgs[id];
let prad = p - pg - HALF * params.dens[id] * params.vturb[id].powi(2);
let tm = params.temp[id - 1];
let pm = params.ptotal[id - 1];
let pgm = params.pgs[id - 1];
let pradm = pm - pgm - HALF * params.dens[id - 1] * params.vturb[id - 1].powi(2);
// 计算中间点值
let (t0, p0, pg0, pr0, ab0, dlt) = if config.ilgder == 0 {
// 线性平均
let t0 = HALF * (t + tm);
let p0 = HALF * (p + pm);
let pg0 = HALF * (pg + pgm);
let pr0 = HALF * (prad + pradm);
let ab0 = HALF * (params.abrosd[id] + params.abrosd[id - 1]);
let dlt = if (p - pm).abs() > 1e-30 {
(t - tm) / (p - pm) * p0 / t0
} else {
0.0
};
(t0, p0, pg0, pr0, ab0, dlt)
} else {
// 对数平均
let t0 = (t * tm).sqrt();
let p0 = (p * pm).sqrt();
let pg0 = (pg * pgm).sqrt();
let pr0 = (prad * pradm).sqrt();
let ab0 = (params.abrosd[id] * params.abrosd[id - 1]).sqrt();
let dlt = if t > 0.0 && tm > 0.0 && p > 0.0 && pm > 0.0 {
(t / tm).ln() / (p / pm).ln()
} else {
0.0
};
(t0, p0, pg0, pr0, ab0, dlt)
};
params.delta[id] = dlt;
// 计算总通量和引力
if config.idisk == 0 {
cubcon.flxtot = flxto0;
cubcon.gravd = config.grav;
} else {
cubcon.flxtot = flxto0 * (UN - params.thetav[id]);
cubcon.gravd = config.qgrav * params.zd[id];
}
flxtt[id] = cubcon.flxtot;
// 简化的对流计算
let (flxcnv, _, grdadb) = compute_convection_simple(
id + 1, t0, p0, pg0, pr0, ab0, dlt, config, cubcon.flxtot, cubcon.gravd,
);
params.flxc[id] = flxcnv;
cubcon.grdadb = grdadb;
// 标记对流点
idcon[id] = if flxcnv > 0.0 { 1 } else { 0 };
// 检测对流区起始
if icbeg == 0 && params.flxc[id] > 0.0 && params.flxc[id - 1] == 0.0 && id > config.idconz as usize {
icbeg = id + 1; // 1-based
}
if icbeg > 0 && params.flxc[id] > 0.0 {
icend = id + 1; // 1-based
}
}
// 修正算法:处理对流区中的间隙
let mut icbeg0 = icbeg;
if config.ideepc > 0 {
if icend == nd - 1 && config.ideepc == 2 {
icend = nd;
}
// 从 icend 向前搜索对流区起始
let mut icbegd = icend;
for id in ((config.idconz + 1) as usize..=icend).rev() {
let idx = id - 1; // 转换为 0-indexed
if idcon[idx] > 0 {
icbegd = id;
} else {
// 检查是否有间隙
let mut igap = 0;
let start = (idx as i32 - config.ndcgap).max(0) as usize;
for idd in start..idx {
if idcon[idd] > 0 {
igap = 1;
break;
}
}
if igap > 0 {
icbegd = id;
} else {
break;
}
}
}
icbeg0 = icbegd;
}
if config.ideepc == 3 {
icend = nd;
}
// 如果没有对流区,直接返回
if icbeg0 == 0 || icend == 0 {
return ConrefOutput {
icbeg: 0,
icend: 0,
modified: false,
};
}
// 对流区温度修正
let mut modified = false;
// 检查对流区起始点附近的温度振荡
if icbeg0 >= 3 {
let t1 = params.temp[icbeg0 - 2];
let t2 = params.temp[icbeg0 - 1];
let t3 = params.temp[icbeg0];
if t2 < t1 && t2 < t3 {
params.temp[icbeg0 - 1] = HALF * (t1 + t3);
modified = true;
}
}
// 对流区迭代修正
for id in icbeg0..=icend {
let idx = id - 1; // 0-indexed
let t = params.temp[idx];
let p = params.ptotal[idx];
let pg = params.pgs[idx];
let prad = p - pg - HALF * params.dens[idx] * params.vturb[idx].powi(2);
let tm = params.temp[idx - 1];
let pm = params.ptotal[idx - 1];
let pgm = params.pgs[idx - 1];
let pradm = pm - pgm - HALF * params.dens[idx - 1] * params.vturb[idx - 1].powi(2);
// 计算中间点值
let (t0, p0, pg0, pr0, ab0, ppd) = if config.ilgder == 0 {
let t0 = HALF * (t + tm);
let p0 = HALF * (p + pm);
let pg0 = HALF * (pg + pgm);
let pr0 = HALF * (prad + pradm);
let ab0 = HALF * (params.abrosd[idx] + params.abrosd[idx - 1]);
let ppd = (p + pm) / (p - pm);
(t0, p0, pg0, pr0, ab0, ppd)
} else {
let t0 = (t * tm).sqrt();
let p0 = (p * pm).sqrt();
let pg0 = (pg * pgm).sqrt();
let pr0 = (prad * pradm).sqrt();
let ab0 = (params.abrosd[idx] * params.abrosd[idx - 1]).sqrt();
let ppd = 0.0; // 对数模式下不使用
(t0, p0, pg0, pr0, ab0, ppd)
};
// 计算总通量
if config.idisk == 0 {
cubcon.flxtot = flxto0;
cubcon.gravd = config.grav;
} else {
cubcon.flxtot = flxto0 * (UN - params.thetav[idx]);
cubcon.gravd = config.qgrav * params.zd[idx];
}
// 所需对流通量
let mut fcnv = cubcon.flxtot - params.flrd[idx];
if fcnv <= 0.0 {
fcnv = cubcon.flxtot * (UN - params.flrd[idx] / params.flrd[1]);
}
if fcnv < 0.0 {
fcnv = 0.001 * cubcon.flxtot;
}
// 温度迭代
let mut t_iter = t;
let mut dlt = params.delta[idx];
for _iic in 0..10 {
let (t0_iter, dlt_iter) = if config.ilgder == 0 {
let t0_iter = HALF * (t_iter + tm);
let dlt_iter = (t_iter - tm) / (p - pm) * p0 / t0_iter;
(t0_iter, dlt_iter)
} else {
let t0_iter = (t_iter * tm).sqrt();
let dlt_iter = (t_iter / tm).ln() / (p / pm).ln();
(t0_iter, dlt_iter)
};
dlt = dlt_iter;
params.delta[idx] = dlt;
// 如果对流显著,计算修正
if params.flxc[idx] / cubcon.flxtot > config.crflim {
let (_, fc0, grdadb) = compute_convc1_simple(
idx + 1, t0_iter, p0, pg0, pr0, ab0, dlt, config, cubcon.flxtot, cubcon.gravd,
);
cubcon.grdadb = grdadb;
if fc0 > 0.0 {
let deltae = (fcnv / fc0).powf(TWO_THR);
let deltaa = deltae + cubcon.b * deltae.sqrt();
dlt = deltaa + cubcon.grdadb;
}
}
let told = t_iter;
if config.ilgder == 0 {
let dlp = dlt / ppd;
t_iter = tm * (UN + dlp) / (UN - dlp);
} else {
t_iter = tm * (p / pm).powf(dlt);
}
let dtt = (t_iter - told) / told;
if dtt.abs() < 1e-9 {
break;
}
}
if (t_iter - params.temp[idx]).abs() > 1e-10 {
modified = true;
}
params.delta[idx] = dlt;
params.temp[idx] = t_iter;
}
// 高级修正过程 (iter >= imucon)
if config.iter >= config.imucon {
// 新的精细修正
for id in icbeg0..=nd {
let idx = id - 1;
let t = params.temp[idx];
let p = params.ptotal[idx];
let tm = params.temp[idx - 1];
let pm = params.ptotal[idx - 1];
let pg = params.pgs[idx];
let pgm = params.pgs[idx - 1];
let pg0 = (pg * pgm).sqrt();
let prad = p - pg - HALF * params.dens[idx] * params.vturb[idx].powi(2);
let pradm = pm - pgm - HALF * params.dens[idx - 1] * params.vturb[idx - 1].powi(2);
let pr0 = (prad * pradm).sqrt();
let t0 = (t * tm).sqrt();
let p0 = (p * pm).sqrt();
let ab0 = (params.abrosd[idx] * params.abrosd[idx - 1]).sqrt();
let dlt = (t / tm).ln() / (p / pm).ln();
let (_, fc0, grdadb) = compute_convc1_simple(
idx + 1, t0, p0, pg0, pr0, ab0, dlt, config, flxtt[idx], cubcon.gravd,
);
let alp = params.flrd[idx].min(flxtt[idx]) / t0.powi(4) / dlt;
let fcnv = flxtt[idx] - params.flrd[idx];
if fcnv <= 0.0 || fc0 <= 0.0 {
// 辐射主导
if flxtt[idx] < params.flrd[idx] {
let alp_new = flxtt[idx] / params.flrd[idx] * t0.powi(4) * delta0[idx];
let mut t_iter = t;
for _ in 0..20 {
let t1 = UN / t_iter;
let dltp = t1 / (p / pm).ln();
let dele = alp_new - t_iter.powi(4) * dlt;
let delep = -t_iter.powi(4) * dlt * (2.0 * t1 + dltp / dlt);
let dt = -dele / delep * t1;
if dt.abs() < 1e-6 {
break;
}
t_iter = t_iter * (UN + dt);
}
params.temp[idx] = t_iter;
params.delta[idx] = (t_iter / tm).ln() / (p / pm).ln();
modified = true;
}
} else {
// 对流主导
let bet = cubcon.b / t0.powi(3);
let deltae = (fcnv / fc0).powf(TWO_THR);
let deltaa = deltae + cubcon.b * deltae.sqrt();
let mut dlt_new = deltaa + grdadb;
let mut t_iter = tm * (p / pm).powf(dlt_new);
// Newton 迭代
for _ in 0..20 {
let t1 = UN / t_iter;
let t0_new = (t_iter * tm).sqrt();
let dlt_new = (t_iter / tm).ln() / (p / pm).ln();
let dele = (flxtt[idx] - alp * t0_new.powi(4) * dlt_new) / fc0;
let dele3 = dele.powf(ONE_THR);
let dltp = t1 / (p / pm).ln();
let delep = -alp * t0_new.powi(4) * dlt_new / fc0 * (2.0 * t1 + dltp / dlt_new);
let vl = dlt_new - grdadb - dele3 * (dele3 + bet * t0_new.powi(3));
let bb = dltp - TWO_THR * delep / dele3
- bet * t0_new.powi(3) * dele3 * (1.5 * t1 + ONE_THR * delep / dele);
let dt = -vl / bb * t1;
if dt.abs() < 1e-9 {
break;
}
t_iter = t_iter * (UN + dt);
}
params.delta[idx] = (t_iter / tm).ln() / (p / pm).ln();
params.temp[idx] = t_iter;
modified = true;
}
}
}
ConrefOutput {
icbeg: icbeg0,
icend: icend,
modified,
}
}
/// 简化的对流计算 (内部使用)。
///
/// 返回 (flxcnv, vcon, grdadb)
fn compute_convection_simple(
_id: usize,
t0: f64,
pt0: f64,
pg0: f64,
_pr0: f64,
ab0: f64,
dlt: f64,
config: &ConrefConfig,
flxtot: f64,
gravd: f64,
) -> (f64, f64, f64) {
// 如果对流被禁用
if config.hmix0 < 0.0 {
return (0.0, 0.0, 0.0);
}
// 绝热梯度近似 (单原子理想气体 = 0.4)
let grdadb = 0.4;
// 检查对流不稳定性
let ddel = dlt - grdadb;
if ddel < 0.0 {
return (0.0, 0.0, grdadb);
}
// 计算引力
let grav = if config.idisk == 1 { gravd } else { config.grav };
if grav == 0.0 {
return (0.0, 0.0, grdadb);
}
// 粗略估计密度
let rho = if t0 > 0.0 {
pt0 / (t0 * 1.38e-16 * grav)
} else {
1e-7
};
// 混合长度
let hmix = if config.hmix0 == 0.0 { 1.0 } else { config.hmix0 };
// 压力标高
let hscale = pt0 / rho / grav;
// 对流速度
let vco = hmix * (config.aconml * pt0 / rho).abs().sqrt();
// 对流系数
let flco = config.bconml * rho * t0 * hmix / 12.5664;
// 光学厚度
let taue = hmix * ab0 * rho * hscale;
// 辐射耗散因子
let fac = taue / (UN + HALF * taue * taue);
// 参数 B (参考 Mihalas)
let b = 5.67e-5 * t0.powi(3) / (rho * vco) * fac * config.cconml * HALF;
// 参数 D
let d = b * b / 2.0;
let disc = d / 2.0 + ddel;
// 计算有效 DLT
let dlt_eff = if disc >= 0.0 {
let val = d + ddel - b * disc.sqrt();
if val < 0.0 { 0.0 } else { val }
} else {
0.0
};
// 对流速度和通量
let vconv = vco * dlt_eff.sqrt();
let flxcnv = flco * vconv * dlt_eff;
(flxcnv, vconv, grdadb)
}
/// 简化的 CONVC1 计算 (返回 fc0)。
///
/// 返回 (flxcnv, fc0, grdadb)
fn compute_convc1_simple(
_id: usize,
t0: f64,
pt0: f64,
pg0: f64,
_pr0: f64,
ab0: f64,
dlt: f64,
config: &ConrefConfig,
flxtot: f64,
gravd: f64,
) -> (f64, f64, f64) {
// 如果对流被禁用
if config.hmix0 < 0.0 {
return (0.0, 0.0, 0.0);
}
// 绝热梯度近似
let grdadb = 0.4;
// 计算引力
let grav = if config.idisk == 1 { gravd } else { config.grav };
if grav == 0.0 {
return (0.0, 0.0, grdadb);
}
// 估计密度
let rho = if t0 > 0.0 {
pt0 / (t0 * 1.38e-16 * grav)
} else {
1e-7
};
// 混合长度
let hmix = if config.hmix0 == 0.0 { 1.0 } else { config.hmix0 };
// 压力标高
let hscale = pt0 / rho / grav;
// 对流速度
let vco = hmix * (config.aconml * pt0 / rho).abs().sqrt();
// 对流系数
let flco = config.bconml * rho * t0 * hmix / 12.5664;
// FC0 = FLCO * VCO
let fc0 = flco * vco;
// 检查对流不稳定性
let ddel = dlt - grdadb;
if ddel < 0.0 {
return (0.0, fc0, grdadb);
}
// 光学厚度
let taue = hmix * ab0 * rho * hscale;
// 辐射耗散因子
let fac = taue / (UN + HALF * taue * taue);
// 参数 B
let b = 5.67e-5 * t0.powi(3) / (rho * vco) * fac * config.cconml * HALF;
// 参数 D
let d = b * b / 2.0;
let disc = d / 2.0 + ddel;
// 计算有效 DLT
let dlt_eff = if disc >= 0.0 {
let val = d + ddel - b * disc.sqrt();
if val < 0.0 { 0.0 } else { val }
} else {
0.0
};
// 对流速度和通量
let vconv = vco * dlt_eff.sqrt();
let flxcnv = flco * vconv * dlt_eff;
(flxcnv, fc0, grdadb)
}
// ============================================================================
// I/O 函数
// ============================================================================
/// 格式化对流区信息。
pub fn format_convective_refinement(icbeg: usize, icend: usize) -> String {
format!(
"\n convective refinement between depths {:4}{:4}\n",
icbeg, icend
)
}
// ============================================================================
// 测试
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
/// 测试用的参数构建器
struct TestParamsBuilder {
nd: usize,
teff: f64,
config: ConrefConfig,
}
impl TestParamsBuilder {
fn new(nd: usize) -> Self {
Self {
nd,
teff: 35000.0,
config: ConrefConfig::default(),
}
}
fn config(mut self, config: ConrefConfig) -> Self {
self.config = config;
self
}
fn build(self) -> ConrefParams<'static> {
let nd = self.nd;
// 创建拥有所有权的向量
let mut temp = vec![0.0; nd];
let mut ptotal = vec![0.0; nd];
let mut pgs = vec![0.0; nd];
let mut dens = vec![0.0; nd];
let mut vturb = vec![0.0; nd];
let mut abrosd = vec![0.0; nd];
let mut flrd = vec![0.0; nd];
let mut flxc = vec![0.0; nd];
let mut delta = vec![0.0; nd];
let mut wmm = vec![0.0; nd];
let mut elec = vec![0.0; nd];
let mut thetav = vec![0.0; nd];
let mut zd = vec![0.0; nd];
// 填充测试数据
for i in 0..nd {
temp[i] = 10000.0 + i as f64 * 100.0;
ptotal[i] = 1e5 + i as f64 * 1e4;
pgs[i] = ptotal[i] * 0.99;
dens[i] = 1e-7;
vturb[i] = 0.0;
abrosd[i] = 0.1;
flrd[i] = 1e10;
flxc[i] = 0.0;
delta[i] = 0.0;
wmm[i] = 1.0;
elec[i] = 1e12;
thetav[i] = 0.0;
zd[i] = 1e10 * (i + 1) as f64;
}
// 使用 Box::leak 创建 'static 引用
ConrefParams {
nd,
teff: self.teff,
config: self.config,
temp: Box::leak(temp.into_boxed_slice()),
ptotal: Box::leak(ptotal.into_boxed_slice()),
pgs: Box::leak(pgs.into_boxed_slice()),
dens: Box::leak(dens.into_boxed_slice()),
vturb: Box::leak(vturb.into_boxed_slice()),
abrosd: Box::leak(abrosd.into_boxed_slice()),
flrd: Box::leak(flrd.into_boxed_slice()),
flxc: Box::leak(flxc.into_boxed_slice()),
delta: Box::leak(delta.into_boxed_slice()),
wmm: Box::leak(wmm.into_boxed_slice()),
elec: Box::leak(elec.into_boxed_slice()),
thetav: Box::leak(thetav.into_boxed_slice()),
zd: Box::leak(zd.into_boxed_slice()),
}
}
}
#[test]
fn test_conref_no_convection() {
let config = ConrefConfig {
iconv: 0,
indl: 0,
..Default::default()
};
let mut params = TestParamsBuilder::new(50).config(config).build();
let output = conref_pure(&mut params);
// iconv <= 0 且 indl == 0 时应该直接返回
assert_eq!(output.icbeg, 0);
assert_eq!(output.icend, 0);
assert!(!output.modified);
}
#[test]
fn test_conref_disabled_hmix() {
let config = ConrefConfig {
hmix0: -1.0,
iconv: 1,
..Default::default()
};
let mut params = TestParamsBuilder::new(50).config(config).build();
let output = conref_pure(&mut params);
// 对流被禁用时不应该有对流区
assert_eq!(output.icbeg, 0);
}
#[test]
fn test_conref_basic() {
let config = ConrefConfig {
iconv: 1,
hmix0: 1.0,
..Default::default()
};
let mut params = TestParamsBuilder::new(50).config(config).build();
let output = conref_pure(&mut params);
// 验证基本功能
// 由于简化实现,结果可能是没有对流区或有限对流
assert!(output.icbeg <= 50);
assert!(output.icend <= 50);
}
#[test]
fn test_compute_convection_simple_stable() {
let config = ConrefConfig::default();
// dlt = 0.1 < grdadb = 0.4,稳定,无对流
let (flxcnv, vconv, grdadb) = compute_convection_simple(
1, 10000.0, 1e5, 1e5, 0.0, 0.1, 0.1, &config, 1e10, 0.0
);
assert_eq!(flxcnv, 0.0);
assert_eq!(vconv, 0.0);
assert!((grdadb - 0.4).abs() < 1e-10);
}
#[test]
fn test_compute_convection_simple_disabled() {
let config = ConrefConfig {
hmix0: -1.0,
..Default::default()
};
let (flxcnv, vconv, grdadb) = compute_convection_simple(
1, 10000.0, 1e5, 1e5, 0.0, 0.1, 0.5, &config, 1e10, 0.0
);
assert_eq!(flxcnv, 0.0);
assert_eq!(vconv, 0.0);
assert_eq!(grdadb, 0.0);
}
#[test]
fn test_compute_convc1_simple() {
let config = ConrefConfig::default();
let (flxcnv, fc0, grdadb) = compute_convc1_simple(
1, 10000.0, 1e5, 1e5, 0.0, 0.1, 0.1, &config, 1e10, 0.0
);
// fc0 应该被计算
assert!(fc0 >= 0.0);
assert!((grdadb - 0.4).abs() < 1e-10);
}
#[test]
fn test_format_convective_refinement() {
let msg = format_convective_refinement(10, 40);
assert!(msg.contains("10"));
assert!(msg.contains("40"));
}
#[test]
fn test_cubcon_data() {
let data = CubconData::default();
assert_eq!(data.a, 0.0);
assert_eq!(data.b, 0.0);
assert_eq!(data.grdadb, 0.0);
}
#[test]
fn test_conref_disk_mode() {
let config = ConrefConfig {
idisk: 1,
iconv: 1,
hmix0: 1.0,
qgrav: 1e-10,
..Default::default()
};
let mut params = TestParamsBuilder::new(50).config(config).build();
let output = conref_pure(&mut params);
// 盘模式应该正常工作
assert!(output.icbeg <= 50);
}
#[test]
fn test_conref_with_ilgder() {
let config = ConrefConfig {
ilgder: 1,
iconv: 1,
hmix0: 1.0,
..Default::default()
};
let mut params = TestParamsBuilder::new(50).config(config).build();
let output = conref_pure(&mut params);
// 对数平均模式应该正常工作
assert!(output.icbeg <= 50);
}
}