☰
Liutex涡识别方法在Matlab与Tecplot中的实现与可视化
2026/10/14 13:45:38 网站建设 项目流程

简介:这份资源围绕Liutex涡识别方法展开,面向流体力学、湍流研究及CFD后处理方向的学习者与科研人员,帮助理解第三代涡识别方法的数学定义,并借助Matlab与Tecplot完成从计算到可视化的完整流程。压缩包共6个文件,约6.67MB,包含3个m脚本、1个pptx演示文稿、1个eqn公式文件与1个pdf文献,脚本负责Liutex相关量的计算与写出,公式文件便于在文档中复用推导,演示与文献则补充理论背景。资源中提供了Liutex函数实现、旋转量提取与结果输出等核心代码,读者可据此复现涡结构识别过程,并将其接入自有流场数据,配合Tecplot完成涡结构可视化与对比分析。目前已有3576人学习下载,适合希望快速上手Liutex方法、减少重复推导与编码工作的研究者参考使用。

1. 从涡旋识别到可视化落地:Liutex 方法在 Matlab 与 Tecplot 中的实现路径

做湍流或者旋涡分离的朋友大概率都经历过这种场景:算完一个叶轮机械或者钝体绕流的瞬态场,想从速度场里把涡结构拎出来,Q 准则、λ2 准则、Δ 准则轮番上阵,结果要么阈值调得人崩溃,要么涡核边界糊成一团。Liutex 方法这两年被提得越来越多,核心原因就是它给出了一个相对严格的刚体旋转分量定义,不再依赖经验阈值去“猜”涡在哪。这套资源围绕的就是怎么在 Matlab 里把 Liutex 算出来,再顺到 Tecplot 里做场可视化。它适合已经能跑 CFD、手里有速度场数据、但卡在涡识别后处理这一步的从业者,也适合想从 Q 准则迁移到 Liutex 但不知道从哪下手的同学。Matlab 负责矩阵运算和批量处理,Tecplot 负责最终出图和动画,中间的数据接口和坐标系对齐是整条链路里最容易翻车的地方。

2. Liutex 的数学内核:从速度梯度张量到刚体旋转轴

2.1 为什么 Q 准则不够用:局部旋转与剪切的对立

Q 准则的定义是速度梯度张量的第二不变量为正,物理上对应旋转率大于应变率。问题在于,剪切层里 Q 值也可以很大,导致你把剪切误判成涡。λ2 准则稍微好一点,看的是压力张量 Hessian 的次特征值,但它本质上还是在找“压力极小面”,对可压缩或者强旋流的适应性有限。Liutex 的思路不一样,它试图把局部速度梯度分解成一个刚体旋转部分和一个非刚体部分,然后直接给出旋转轴的向量和旋转强度。这个分解不是唯一的,但 Liu 等人给出的定义在数学上满足伽利略不变性,而且旋转强度是量纲一致的。实际用下来,最大的好处是你不用再对着阈值反复试,Liutex 的等值面在涡核附近梯度更陡,边界更干净。

2.2 速度梯度张量的实特征值与复特征值判定

Liutex 的计算起点是速度梯度张量 ∇v,一个 3×3 矩阵。先求它的特征值:如果三个特征值全是实数,说明局部没有旋转,Liutex 为零;如果有一个实特征值和一对共轭复特征值,实特征值对应的特征向量就是旋转轴方向。这一步在 Matlab 里用 eig 就能做,但要注意数据排列顺序。很多 CFD 导出的是扁平化的速度场,需要先 reshape 成 [nx, ny, nz, 3] 再逐点算梯度。梯度计算建议用中心差分,边界用单侧差分,不要直接用 gradient 函数,因为非均匀网格下 gradient 默认假设间距为 1,会引入系统性偏差。

% 假设 u, v, w 是 nx*ny*nz 的速度分量,x, y, z 是对应坐标 [nx, ny, nz] = size(u); % 预分配速度梯度张量 grad_v = zeros(nx, ny, nz, 3, 3); % 中心差分计算梯度,循环维度可改为向量化 for i = 2:nx-1 for j = 2:ny-1 for k = 2:nz-1 dx = x(i+1,j,k) - x(i-1,j,k); dy = y(i,j+1,k) - y(i,j-1,k); dz = z(i,j,k+1) - z(i,j,k-1); grad_v(i,j,k,1,1) = (u(i+1,j,k) - u(i-1,j,k)) / dx; grad_v(i,j,k,1,2) = (u(i,j+1,k) - u(i,j-1,k)) / dy; grad_v(i,j,k,1,3) = (u(i,j,k+1) - u(i,j,k-1)) / dz; grad_v(i,j,k,2,1) = (v(i+1,j,k) - v(i-1,j,k)) / dx; grad_v(i,j,k,2,2) = (v(i,j+1,k) - v(i,j-1,k)) / dy; grad_v(i,j,k,2,3) = (v(i,j,k+1) - v(i,j,k-1)) / dz; grad_v(i,j,k,3,1) = (w(i+1,j,k) - w(i-1,j,k)) / dx; grad_v(i,j,k,3,2) = (w(i,j+1,k) - w(i,j-1,k)) / dy; grad_v(i,j,k,3,3) = (w(i,j,k+1) - w(i,j,k-1)) / dz; end end end

这段代码的逻辑很直接:对每个内部网格点,用相邻两点的速度差除以坐标差得到偏导数。参数说明上,dx、dy、dz 是局部网格间距,非均匀网格必须逐点算,不能用一个全局平均值代替。边界点单独处理,通常用前向或后向差分。如果网格量级在百万以上,三重循环会非常慢,建议用 permute 和 diff 做向量化,或者干脆写 mex。我一般会先把梯度张量存成稀疏格式,因为大部分点的 Liutex 值接近零,稠密存储浪费内存。

2.3 复特征值对应的旋转轴提取

拿到 ∇v 之后,逐点求特征值。Matlab 的 eig 对 3×3 矩阵返回一个 3×1 复向量。判断是否有复特征值:如果任意两个特征值的虚部绝对值大于某个小量(比如 1e-12),就认为存在旋转。实特征值对应的特征向量就是旋转轴。注意,eig 返回的特征向量可能符号相反,需要统一方向,否则 Tecplot 里画出来的涡轴会跳变。常见做法是让旋转轴与当地涡量方向点积为正,如果为负就取反。

liutex_mag = zeros(nx, ny, nz); liutex_axis = zeros(nx, ny, nz, 3); for i = 1:nx for j = 1:ny for k = 1:nz A = squeeze(grad_v(i,j,k,:,:)); [V, D] = eig(A); eig_vals = diag(D); % 判断是否存在复特征值 if any(abs(imag(eig_vals)) > 1e-12) % 找实特征值对应的特征向量 [~, idx] = min(abs(imag(eig_vals))); axis_vec = real(V(:, idx)); axis_vec = axis_vec / norm(axis_vec); % 与涡量对齐 vort = [grad_v(i,j,k,3,2)-grad_v(i,j,k,2,3), ... grad_v(i,j,k,1,3)-grad_v(i,j,k,3,1), ... grad_v(i,j,k,2,1)-grad_v(i,j,k,1,2)]; if dot(axis_vec, vort) < 0 axis_vec = -axis_vec; end liutex_axis(i,j,k,:) = axis_vec; % Liutex 强度计算,这里用简化形式 liutex_mag(i,j,k) = abs(imag(eig_vals(idx))); end end end end

这里 liutex_mag 只是取了虚部的绝对值作为强度的一个代理,严格定义下 Liutex 强度是旋转轴方向上的速度梯度分量减去其转置分量。实际写的时候建议按原始文献的公式来,我这里为了展示流程做了简化。参数上,1e-12 这个容差要根据数据精度调,双精度一般够用,单精度数据要放大到 1e-6 左右。liutex_axis 存成四维数组,后面导出 Tecplot 的时候直接对应三个分量。

3. Matlab 到 Tecplot 的数据接口:格式选择与坐标系对齐

3.1 Tecplot 能吃的几种格式:PLT、DAT 与 CGNS

Tecplot 支持的原生格式里,二进制 PLT 读写最快,但 Matlab 没有内置写 PLT 的函数,得靠第三方 mex 或者自己拼二进制头。DAT 是 ASCII 格式,写起来简单,但文件体积大,百万网格点轻松上 G。CGNS 是 CFD 通用格式,Tecplot 和大部分 CFD 软件都认,但 Matlab 写 CGNS 需要额外工具箱。我一般用 DAT 做小规模调试,正式出图用 PLT。如果你们组有 Tecplot 的 Chorus 或者 360 版本,也可以走 Python 的 pytecplot 接口,但那就绕开 Matlab 了。这里只讲纯 Matlab 写 DAT 的路子,因为最可控。

3.2 用 Matlab 拼 Tecplot ASCII 数据文件

Tecplot 的 DAT 文件结构分三块:标题区、变量列表、数据区。变量列表里要声明所有你要画的量,比如 X、Y、Z、U、V、W、Liutex、Axis_X、Axis_Y、Axis_Z。数据区按变量顺序逐点排列。对于结构网格,可以用 I、J、K 声明维度,然后按 i 最快、j 次之、k 最慢的顺序写。下面是一个写 DAT 的示例。

fid = fopen('liutex_output.dat', 'w'); fprintf(fid, 'TITLE = "Liutex Field"\n'); fprintf(fid, 'VARIABLES = "X" "Y" "Z" "U" "V" "W" "Liutex" "Ax" "Ay" "Az"\n'); fprintf(fid, 'ZONE T="FlowField", I=%d, J=%d, K=%d, DATAPACKING=POINT\n', nx, ny, nz); for k = 1:nz for j = 1:ny for i = 1:nx fprintf(fid, '%e %e %e %e %e %e %e %e %e %e\n', ... x(i,j,k), y(i,j,k), z(i,j,k), ... u(i,j,k), v(i,j,k), w(i,j,k), ... liutex_mag(i,j,k), ... liutex_axis(i,j,k,1), liutex_axis(i,j,k,2), liutex_axis(i,j,k,3)); end end end fclose(fid);

逻辑说明:先写标题和变量名,Tecplot 对变量名大小写不敏感,但建议统一。ZONE 行里的 I、J、K 告诉 Tecplot 这是结构网格,DATAPACKING=POINT 表示按点写。循环顺序必须是 k 外层、j 中层、i 内层,因为 Tecplot 默认 i 变化最快。参数上,%e 是科学计数法,精度够用,如果数据范围跨好几个量级可以改用 %g。文件写完后用 Tecplot 打开,如果报“数据点数量不匹配”,九成是循环顺序反了。

3.3 非结构网格的导出策略

如果你的网格是非结构的,比如四面体或者多面体,DAT 文件里就不能用 I、J、K 了,得改成 ZONE 里声明 NODES 和 ELEMENTS,然后先写节点坐标和变量值,再写单元连接关系。Matlab 里通常有网格的节点坐标和单元索引矩阵,直接按格式拼就行。注意 Tecplot 的单元索引是从 1 开始的,Matlab 也是从 1 开始,这点不用转换。但如果你中间用过其他工具转过格式,要确认索引基准没变。非结构网格的 Liutex 轴可视化建议用切片或者流线,不要直接画等值面,因为单元形状不规则,等值面容易破。

4. Tecplot 里的 Liutex 可视化:等值面、涡轴与动画

4.1 用 Liutex 幅值做等值面:阈值怎么选

数据导入 Tecplot 后,第一件事是画 Liutex 的等值面。在 Contour 里选 Liutex 变量,然后切到 Isosurface 模式。阈值选取有个经验:先看 Liutex 的体渲染或者切片云图,找到涡核区域的典型值,然后取该值的 30% 到 50% 作为等值面阈值。Liutex 的好处是涡核内部值高、外部衰减快,所以阈值窗口比 Q 准则窄,不用反复试。如果等值面出现碎片,说明阈值偏低,把剪切区的噪声也包进来了;如果涡结构断成几截,说明阈值偏高,把涡核弱连接处切掉了。我一般会同时开两个等值面,一个高阈值看涡核,一个低阈值看涡的包裹范围。

4.2 涡轴向量场的显示:用 Vector 还是 Streamtrace

Liutex 轴是单位向量,直接画 Vector 图会密密麻麻,而且箭头长度没有物理意义。更好的做法是用 Streamtrace 沿着涡轴方向积分,或者用 Tecplot 的 Vortex Core 功能线。具体操作:在 Plot 里选 Vector,变量选 Ax、Ay、Az,然后调整箭头间距和长度。如果涡轴方向跳变严重,检查 Matlab 里有没有做方向对齐。另一个技巧是用 Volume 渲染把 Liutex 幅值映射成透明度,涡轴用 Line 画,这样既有强度信息又有方向信息。Tecplot 的 Volume 渲染对显卡有要求,如果卡顿就改用切片。

4.3 瞬态动画的帧序列导出

瞬态数据通常是一个时间序列一个文件,Tecplot 可以用 Time 菜单里的 Animate 做帧切换。前提是每个 DAT 文件里的变量名和网格维度完全一致,否则 Tecplot 会认为是不同数据集。导出动画时选 AVI 或者 GIF,帧率一般 10 到 15 帧每秒就够了。如果文件太多,可以用 Tecplot 的宏命令批量加载和导出。宏文件里用 $!ReadDataSet 读文件,$!Export 导出图片,循环变量用 $!Loop。注意宏里的路径要用双反斜杠或者正斜杠,Windows 下单反斜杠会被当转义符。

5. 避坑与排查:Liutex 计算和可视化里的五个血泪教训

5.1 现象:Liutex 全场为零,但流场明明有涡

原因:速度梯度张量的特征值全是实数,说明局部没有复特征值。常见于涡核被数值耗散抹平,或者网格分辨率不够,涡的旋转特征在离散尺度上退化了。解决:先检查网格在涡核附近的尺寸,如果当地网格尺度大于涡核半径,Liutex 必然算不出来。加密网格或者用高阶插值重构速度场。另一个可能是速度数据本身有问题,比如从 CFD 导出时做了太多平滑。

5.2 现象:Tecplot 打开 DAT 文件报“变量数量不匹配”

原因:VARIABLES 行声明的变量个数和实际每行写的数据个数不一致。常见于变量列表里多写了一个空格或者少写了一个引号。解决:用文本编辑器打开 DAT 文件,数一下 VARIABLES 行里引号对的数量,再数数据行里数值的个数。Tecplot 对格式很敏感,多一个逗号都可能报错。建议在 Matlab 里用 fprintf 拼字符串时,把变量名和格式串分开维护,改一个地方就同步改另一个。

5.3 现象:涡轴方向在相邻点之间来回翻转

原因:eig 返回的特征向量符号是任意的,Matlab 不保证连续性。解决:在计算每个点的轴向量后,与上一个点的轴向量做点积,如果为负就取反。更稳健的做法是与当地涡量方向对齐,因为涡量方向在涡核附近是连续的。如果涡量本身也跳变,那就用全局参考方向,比如来流方向,但只适用于涡轴大致一致的场景。

5.4 现象:Tecplot 里等值面出现大量碎片,像噪声

原因:Liutex 在剪切层里虽然比 Q 准则干净,但仍有小值残留。如果阈值取得太低,这些残留就被包进来了。解决:先对 Liutex 场做一次空间平滑,用 3×3×3 的均值滤波,但注意平滑会削弱涡核峰值。另一个办法是在 Matlab 里设一个下限,低于某个值的 Liutex 直接置零,这个下限取全场最大值的 1% 到 5%。置零后等值面会干净很多。

5.5 现象:瞬态动画里涡结构闪烁,不连续

原因:每帧的 Liutex 阈值是独立选的,或者每帧的坐标轴范围变了。解决:在 Tecplot 里锁定等值面阈值和视图范围,所有帧用同一套参数。如果数据本身有时间步之间的数值振荡,可以在 Matlab 里对时间序列做低通滤波。另外,瞬态数据的 DAT 文件命名要有规律,比如 liutex_0001.dat、liutex_0002.dat,Tecplot 的 Time 菜单才能自动识别序列。

6. 进阶技巧:用 Matlab 批量算 Liutex 并直接驱动 Tecplot 宏

当你需要处理几十个工况或者几百个时间步的时候,手动在 Tecplot 里点来点去就不现实了。我一般会在 Matlab 里写一个主脚本,循环读速度场、算 Liutex、写 DAT,然后调用 Tecplot 的宏做批量出图。Tecplot 宏可以用命令行调用,Windows 下是 tecplot.exe -b -p macro.mcr,Linux 下类似。宏文件里用 $!ReadDataSet 读 DAT,$!RedrawAll 刷新,$!Export 导出图片。下面是一个宏模板。

# Tecplot 宏模板:批量导出 Liutex 等值面图片 $!ReadDataSet "liutex_output.dat" $!CreateContourGroup [1] $!ContourGroup [1] ContourType = Isosurface $!ContourGroup [1] ContourVar = 7 $!ContourGroup [1] IsosurfaceValue = 0.35 $!RedrawAll $!ExportSetup ExportFormat = PNG $!ExportSetup ImageWidth = 1920 $!ExportSetup ImageHeight = 1080 $!Export "liutex_iso.png"

这个宏的逻辑是:读数据,建等值面组,指定变量索引为 7(对应 Liutex),设等值面值为 0.35,刷新后导出 PNG。参数上,ContourVar 的索引要和 VARIABLES 行里的顺序一致,从 1 开始数。IsosurfaceValue 根据你的数据范围调,可以先跑一个工况看云图再定。ExportSetup 里的分辨率按期刊要求设,一般 300 dpi 对应 1920 宽就够。如果要做动画,把 ReadDataSet 和 Export 放进 $!Loop 里,循环变量用文件名后缀。

还有一个技巧是直接在 Matlab 里生成 Tecplot 的布局文件(.lay),这样连宏都不用写。布局文件是 XML 格式,里面定义了帧、等值面、切片、流线等所有可视化元素。Matlab 可以用 xmlwrite 或者直接 fprintf 拼。好处是一次生成,以后每次只换数据文件就行。缺点是布局文件的 schema 在不同 Tecplot 版本之间有差异,换版本可能要微调。我一般会在目标版本上手动存一个模板,然后用 Matlab 做字符串替换,把数据文件名和阈值换掉。

从那以后我每次算完 Liutex 都强制走一遍检查清单:梯度计算用中心差分且边界单独处理、特征值容差按数据精度设、涡轴方向与涡量对齐、DAT 文件先小规模测试再批量写、Tecplot 宏先在单帧上验证再循环。这套流程跑顺了,从速度场到涡结构出图基本可以做到半自动。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询