//! 压力与几何距离评价 - 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]); } }