ParaView 可复现后处理:结果诊断与可信度验证

把一次可视化固化为可复现脚本:用 pvpython 锁定相机、颜色范围与等值面阈值,给出 Q 判据与 lambda2 判据的定义和阈值量级估算,并用图像差分做回归。

OpenFOAM结果诊断与可信度验证ParaView 可复现后处理pvpython专题

ParaView 可复现后处理:结果诊断与可信度验证

ParaView 的手工操作不可复现,而状态文件与 Python 脚本可以。本文给出把一次可视化固化为脚本的最小闭环:状态导出、pvpython 批处理、颜色与相机的显式锁定,以及 Q 判据与 lambda2 判据的定义和阈值量级估算。

状态文件与 Python 脚本的取舍

.pvsm 保存过滤器栈、相机、颜色映射与不透明度传递函数,加载后完全复现界面状态;缺点是版本敏感,跨大版本可能丢失过滤器参数。pvpython 脚本可版本控制、可 diff,适合进入 CI。实践做法是用 .pvsm 固化交互探索,用 Python 脚本固化最终出图。

from paraview.simple import *
case = OpenFOAMReader(FileName='case.foam')
case.MeshRegions = ['internalMesh']
case.CellArrays = ['U', 'p']
case.UpdatePipeline()

sl = Slice(Input=case)
sl.SliceType = 'Plane'
sl.SliceType.Origin = [0.5, 0.0, 0.0]
sl.SliceType.Normal = [1.0, 0.0, 0.0]

lut = GetColorTransferFunction('U')
lut.RescaleTransferFunction(0.0, 25.0)
lut.ApplyPreset('Cool to Warm', True)

cam = GetActiveCamera()
cam.SetPosition(2.5, 0.0, 0.5)
cam.SetFocalPoint(0.5, 0.0, 0.0)
cam.SetViewUp(0.0, 0.0, 1.0)
Render()
SaveScreenshot('slice_x05.png', ImageResolution=[1920, 1080])

颜色范围必须显式锁定

自动范围随时刻变化,动画里会出现"同一颜色代表不同速度"的假象。把 UU 的范围锁定在 [0,25] m/s[0, 25]\ \mathrm{m/s},则第 1 帧与第 100 帧的红色都对应 25 m/s。若真实最大值为 28.4 m/s28.4\ \mathrm{m/s},超出部分会被截断成饱和色,因此锁定前应先用统计过滤器确认全域极值。

涡识别判据的定义与阈值

Q=12(∥Ω∥2−∥S∥2),S=12(∇U+∇UT),Ω=12(∇U−∇UT)Q = \tfrac12\left(\|\Omega\|^2 - \|S\|^2\right), \qquad S = \tfrac12(\nabla\mathbf{U} + \nabla\mathbf{U}^T), \quad \Omega = \tfrac12(\nabla\mathbf{U} - \nabla\mathbf{U}^T)

Q>0Q > 0 的等值面显示旋转主导的区域。某圆柱尾流算例取 Q=500 s−2Q = 500\ \mathrm{s^{-2}} 得到清晰的涡街结构,取 Q=100 s−2Q = 100\ \mathrm{s^{-2}} 时剪切层也被卷入,结构变模糊。阈值必须与 ∥∇U∥\|\nabla\mathbf{U}\| 的量级对照:∥∇U∥∼U∞/D=20/0.1=200 s−1\|\nabla\mathbf{U}\| \sim U_\infty/D = 20/0.1 = 200\ \mathrm{s^{-1}},故 QQ 的自然尺度为 2002=4×104 s−2200^2 = 4\times10^4\ \mathrm{s^{-2}},取 500 相当于该尺度的 1.25%。

λ2 ⁣(S2+Ω2)<0\lambda_2\!\left(S^2 + \Omega^2\right) < 0

即取张量 S2+Ω2S^2 + \Omega^2 的三个特征值 λ1≥λ2≥λ3\lambda_1 \ge \lambda_2 \ge \lambda_3 中 λ2<0\lambda_2 < 0 的区域。它比 QQ 对剪切层更不敏感,适合分离流与射流剪切层并存的算例。

用脚本做回归比对

把所有会引入随机性的量显式写出:相机位置、颜色范围、等值面阈值、时间索引、图像分辨率。缺一项就不可复现。

pvpython render_slice.py --time 100 --umin 0 --umax 25
python -c "from PIL import Image, ImageChops; import sys; \
d = ImageChops.difference(Image.open(sys.argv[1]), Image.open(sys.argv[2])); \
print('diff bbox:', d.getbbox())" a.png b.png

失败模式

现象 根因 判定试验
动画颜色随帧变化 颜色范围用自动模式 用 RescaleTransferFunction 锁定并比对首末帧
脚本在不同版本报错 过滤器属性名随版本改变 用 GetPropertyValue 打印属性名做兼容分支
出图与手工操作不一致 相机未显式设置 在脚本里 SetPosition/SetFocalPoint/SetViewUp
Q 等值面糊成一片 阈值远低于 ∣∇U∣2|\nabla\mathbf{U}|^2 尺度 按 Q∼(U/D)2Q \sim (U/D)^2 取 1% 量级重试
截图分辨率与报告不符 未设 ImageResolution 显式指定 1920×1080

参考文献

  1. Kitware Inc., ParaView User’s Guide, 2023.
  2. J. C. R. Hunt, A. A. Wray, P. Moin, “Eddies, streams, and convergence zones in turbulent flows”, Proceedings of the Summer Program, Center for Turbulence Research, 1988.
  3. J. Jeong, F. Hussain, “On the identification of a vortex”, Journal of Fluid Mechanics, 285, 1995.
  4. C. R. Johnson, C. D. Hansen (eds.), The Visualization Handbook, Elsevier, 2005.
  5. M. Jiang, R. Machiraju, D. Thompson, “Detection and visualization of vortices”, in The Visualization Handbook, Elsevier, 2005.