SpectraRust/src/math/pzevld.rs
2026-03-21 16:23:35 +08:00

247 lines
8.8 KiB
Rust

//! 压力与几何距离评价 - PZEVLD。
//!
//! 重构自 TLUSTY `pzevld.f`
//!
//! 确定总压、气体压以及压力对数梯度;计算从中心平面开始的几何距离 Z。
use crate::math::dmder::DepthDeriv;
use crate::state::arrays::ComputeArrays;
use crate::state::atomic::AtomicData;
use crate::state::config::TlustyConfig;
use crate::state::constants::{BOLK, MDEPTH, HALF, UN};
use crate::state::model::ModelState;
/// 执行压力与几何距离评价。
pub fn pzevld(
config: &mut TlustyConfig,
_atomic: &mut AtomicData,
model: &mut ModelState,
arrays: &mut ComputeArrays,
deriv: &DepthDeriv,
) {
let nd = config.basnum.nd as usize;
let nfreqe = config.basnum.nfreqe as usize;
let ifryb = config.basnum.ifryb;
let ihecor = model.heqaux.ihecor;
let qgrav = config.inppar.qgrav;
let znd = config.centrl.znd;
if ifryb > 0 && model.ifpzpa.ifpzev == 0 {
return;
}
let mut iheitr = 0;
let mut zold = [0.0; MDEPTH];
let mut dpp = [0.0; MDEPTH];
let mut zd1 = [0.0; MDEPTH];
let mut zd2 = [0.0; MDEPTH];
let mut zd3 = [0.0; MDEPTH];
loop {
iheitr += 1;
// 1. 计算几何距离 Z (从中心平面开始)
if ihecor >= 0 {
model.modpar.zd[nd - 1] = znd;
for iid in 1..nd {
let id = nd - 1 - iid;
if iheitr == 1 {
model.modpar.zd[id] = model.modpar.zd[id + 1]
+ HALF
* (model.modpar.dm[id + 1] - model.modpar.dm[id])
* (UN / model.modpar.dens[id + 1] + UN / model.modpar.dens[id]);
zold[id] = model.modpar.zd[id];
}
}
} else {
zd1[0] = -deriv.ddc[0] / deriv.ddb[0];
zd2[0] = -model.modpar.dens1[0] / deriv.ddb[0];
for id in 1..nd - 1 {
let x = UN / (deriv.ddb[id] - deriv.dda[id] * zd1[id - 1]);
zd1[id] = -x * deriv.ddc[id];
zd2[id] = -x * (model.modpar.dens1[id] - deriv.dda[id] * zd2[id - 1]);
}
model.modpar.zd[nd - 1] = znd;
for id in (0..nd - 1).rev() {
model.modpar.zd[id] = zd1[id] * model.modpar.zd[id + 1] + zd2[id];
}
}
// 2. 总压、气体压和声速
for id in 0..nd {
let pturb = HALF * model.modpar.dens[id] * model.turbul.vturb[id] * model.turbul.vturb[id];
let pgsc = (model.modpar.dens[id] / config.inppar.wmm[id] + model.modpar.elec[id])
* BOLK
* model.modpar.temp[id];
model.pressr.pgs[id] = pgsc;
let ptotl0 = model.pressr.pgs[id] + model.pressr.pradt[id] + pturb;
model.pressr.ptotal[id] = ptotl0;
model.prsaux.vsnd2[id] = model.pressr.ptotal[id] / model.modpar.dens[id];
}
// 边界参考
model.prsaux.hg1 = (2.0 * model.pressr.pgs[0] / model.modpar.dens[0] / qgrav).sqrt();
model.prsaux.hr1 = model.heqaux.prd0 / qgrav;
model.prsaux.rr1 = model.prsaux.hr1 / model.prsaux.hg1;
// 3. 重新计算 Z 距离 (辐射驱动力影响)
let mut ij1 = 0;
if config.compti.icompt > 0 && config.compti.icombc > 0 && model.freaux.ijex[0] > 0 {
ij1 = 1;
}
for id in 0..nd {
let mut grp = 0.0;
if nfreqe > 0 || ifryb == 0 {
for ij in ij1..nfreqe {
let rad0 = model.expraf.radex[ij][id];
let abso0 = arrays.exprad.absoex[ij][id];
let ijt = (model.freaux.ijfr[ij] - 1) as usize;
let wd0 = model.frqall.w[ijt];
let fluxw = model.surfac.fh[ijt] * rad0 - model.totrad.hextrd[ijt];
if model.frqall.lskip[id][ijt] == 0 {
if id == 0 {
grp += wd0 * fluxw * abso0;
} else {
let radm = model.expraf.radex[ij][id - 1];
let fkm = model.expraf.fakex[ij][id - 1];
let fk0 = model.expraf.fakex[ij][id];
let frd = fk0 * rad0 - fkm * radm;
grp += wd0 * frd;
}
}
}
model.grdpra.grd[id] = grp + model.totflx.fprd[id];
}
if id > 0 {
let ddm = model.modpar.dm[id] - model.modpar.dm[id - 1];
dpp[id] = (model.pressr.pgs[id] - model.pressr.pgs[id - 1]) / ddm
+ model.grdpra.grd[id] / ddm * 4.19168946e-10;
dpp[id] /= qgrav;
}
}
// 4. 判断是否进入更多迭代
if config.runkey.iter <= config.centrl.ifz0.abs() {
zd1[0] = dpp[1];
zd1[nd - 1] = znd;
for id in 1..nd - 1 {
zd1[id] = (dpp[id] + dpp[id + 1]) * HALF;
}
zd2[nd - 1] = znd;
zd3[nd - 1] = znd;
let mut izdiv = 0;
let mut nzdiv = 0;
for id in (0..nd - 1).rev() {
zd2[id] = 2.0 * dpp[id + 1] - zd2[id + 1];
zd3[id] = dpp[id] * deriv.ddmin[id] + dpp[id + 1] * deriv.ddplu[id];
if zd2[id] <= zd2[id + 1] {
nzdiv += 1;
}
if nzdiv == 1 {
izdiv = id;
}
}
if ihecor >= 0 {
for id in 0..nd {
model.modpar.zd[id] = zd2[id];
if id <= izdiv {
model.modpar.zd[id] = zd1[id];
}
}
} else {
for id in 0..nd {
model.modpar.zd[id] = zd3[id];
}
}
// 重新计算密度 (如果需要)
if ihecor > 0 {
for id in (0..nd - 1).rev() {
let ddm_curr = model.modpar.dm[id + 1] - model.modpar.dm[id];
let x = HALF * ddm_curr;
let xne = model.modpar.elec[id] / model.modpar.dens[id];
model.modpar.dens[id] = x * model.modpar.dens[id + 1]
/ ((model.modpar.zd[id] - model.modpar.zd[id + 1]) * model.modpar.dens[id + 1] - x);
model.modpar.dens1[id] = UN / model.modpar.dens[id];
model.modpar.elec[id] = xne * model.modpar.dens[id];
}
} else if ihecor < -1 {
for id in (0..nd - 1).rev() {
let xne = model.modpar.elec[id] / model.modpar.dens[id];
if id > 0 {
model.modpar.dens1[id] = model.modpar.zd[id - 1] * deriv.dda[id]
- model.modpar.zd[id] * deriv.ddb[id]
- model.modpar.zd[id + 1] * deriv.ddc[id];
} else {
model.modpar.dens1[id] =
-model.modpar.zd[id] * deriv.ddb[id] - model.modpar.zd[id + 1] * deriv.ddc[id];
}
model.modpar.dens[id] = UN / model.modpar.dens1[id];
model.modpar.elec[id] = xne * model.modpar.dens[id];
}
}
let mut dzmx = 0.0;
for id in 0..nd - 1 {
let diff = ((model.modpar.zd[id] - zold[id]) / model.modpar.zd[id]).abs();
if diff > dzmx {
dzmx = diff;
}
zold[id] = model.modpar.zd[id];
}
if iheitr >= 5 || dzmx < 1.0e-3 {
break;
}
} else {
break;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::math::dmder::dmder;
#[test]
fn test_pzevld_basic() {
let mut config = TlustyConfig::default();
let mut atomic = AtomicData::default();
let mut model = ModelState::default();
let mut arrays = ComputeArrays::default();
config.basnum.nd = 10;
config.inppar.qgrav = 1e4;
config.centrl.znd = 1e8;
model.heqaux.ihecor = 0;
// 设置 DM 为均匀网格
for id in 0..10 {
model.modpar.dm[id] = (id + 1) as f64 * 1.0;
model.modpar.dens[id] = 1.0;
model.modpar.temp[id] = 10000.0;
}
let deriv = dmder(&model.modpar.dm, 10);
// 初始运行配置
config.runkey.iter = 10;
config.centrl.ifz0 = 0;
pzevld(&mut config, &mut atomic, &mut model, &mut arrays, &deriv);
// 验证基本压力组件
assert!(model.pressr.pgs[0] > 0.0);
assert!(model.pressr.ptotal[0] >= model.pressr.pgs[0]);
// 验证 ZD 积分结果 (简单情况)
assert!(model.modpar.zd[0] > model.modpar.zd[9]);
}
}