2026/10/18 11:41:17

Matlab与Tecplot实现Liutex涡识别全流程详解

Matlab与Tecplot实现Liutex涡识别全流程详解 简介该资源为Liutex涡定义与第三代涡识别方法的入门与实现资料包面向流体力学、涡动力学方向的研究人员及工程技术人员帮助读者理解Liutex理论并快速上手Matlab与Tecplot的可视化实现。压缩包共6个文件包括3个Matlab脚本如getR.m、writeLiutex.m等用于计算与输出Liutex场、1份PDF文献介绍、1份PPTX讲解材料及1个公式文件整体大小6.67MB内容精简但覆盖从原理到编码的关键环节。已有3582人浏览学习较为适合具有一定流体力学基础、希望掌握新代涡识别方法的读者。资料由作者针对网上盗卖行为重新免费上传无需积分即可下载。通过阅读PDF与PPT可系统了解Liutex定义与优势借助Matlab脚本可对照实现核心算法并进一步结合Tecplot完成结果可视化从而在科研或工程项目中直接应用这一较前沿的涡识别工具。1. Liutex 不是玄学为什么我用 Matlab 算、用 Tecplot 看做 CFD 后处理的人大多会遇到同一种尴尬算完流场用 Q 准则或 λ2 准则挑涡结构结果射流剪切层、壁面边界层、甚至纯剪切缝隙里都飘着一大片“涡”可这些区域根本没有旋转核心云图出来后完全没法跟实验流动显示对上。Liutex 方法就是来补这个空子的它把速度梯度张量拆成刚性旋转和变形两类贡献只保留真正的刚性旋转强度 R再输出矢量。这条路我用 Matlab 做逐点计算、Tecplot 做后处理出图脚本全流程跑通不依赖商业 CFD 求解器内部函数。适合手上只有速度场结果、想快速验证涡结构的仿真工程师和研究生。2. Liutex 的数学原理与计算路线从速度梯度到旋转轴2.1 为什么不再依赖 Q 准则和 λ2 判据传统判据的通病在于它们都建立在“涡量大于变形就等于有涡”这个近似上。考察速度梯度张量∇u的对称部分 S 和反对称部分 ΩQ 准则计算0.5*(||Ω||² - ||S||²)λ2 准则看的是 S²Ω² 的第二特征值。这两个判据在纯剪切层里的响应非常糟糕纯剪切场的涡量和变形量可以同时很大Q 值照样偏高于是把一大片剪切区误报成涡。我最早用 Q 准则时判断“哪里是涡”基本靠猜后来才意识到这是剪切污染。Liutex 的计算思路完全不同。它不比较涡量与变形的相对大小而是先问一个问题这个局部区域是否存在一条旋转轴能让流体质点绕它做刚性旋转判断依据是速度梯度张量的特征值结构。只要存在一对共轭复特征值和一条唯一的实特征值对应的旋转轴再满足强旋转判别式就认为该点是涡。这个门槛把剪切、拉伸这类非旋转变形滤掉了所以它输出的等值面通常比 Q 准则小两三圈正好对应流体绕某条轴转动的核心。2.2 特征值分解与 Liutex 强度的计算完整算法分五步。第一步计算每一点的速度梯度张量∇u第二步求∇u的三个特征值判断是否存在一个实特征值和一对共轭复特征值如果三个特征值都是实数该点直接置零第三步取实特征值对应的特征向量单位化后作为旋转轴方向 r第四步计算涡量 ω 在 r 上的投影ω_r ω·r并取复特征值的实部 λ_cr第五步求刚性旋转强度 R。公式是R sign(ω_r) * sqrt( max(ω_r² - 4*λ_cr², 0) )Liutex 向量就是R·r。公式里的4*λ_cr²项就是把速度梯度张量中由拉伸/剪切带来的变形贡献扣除剩下才是绕 r 轴的刚性旋转分量。这套计算在 Matlab 里可以做成一个独立函数方便后续逐点调用。function [Rvec, Rmag] liutex_grad(D, omega) % D : 3x3 速度梯度张量 % omega : 1x3 涡量向量 % 返回 Liutex 向量 Rvec 与标量强度 Rmag tol 1e-8 * max(1, sqrt(sum(D(:).^2))); [V, Deig] eig(D); lam diag(Deig); n_real sum(abs(imag(lam)) tol); Rvec [0 0 0]; Rmag 0; if n_real ~ 1 return; % 三个实根或退化情况不产生刚性旋转 end idx_real find(abs(imag(lam)) tol, 1); r real(V(:, idx_real)); r r / norm(r); if dot(r, omega) 0 r -r; % 统一旋转轴方向避免相邻点符号跳变 end idx_cplx find(abs(imag(lam)) tol, 1); lam_cr real(lam(idx_cplx)); wr dot(omega, r); disc wr * wr - 4 * lam_cr * lam_cr; Rmag sign(wr) * sqrt(max(disc, 0)); Rvec Rmag * r; end逻辑说明每个网格点单独调用这个函数返回零向量说明该点不是涡。n_real用容差判断而不是imag(lam) 0因为浮点计算里纯实数根的虚部也可能出现 1e-16 量级的残留严格相等会把好点全部漏掉。旋转轴方向统一那一步不是可选项特征向量只有方向没有正负同一物理涡在相邻网格点可能一个取正一个取负不做对齐则输出 R 向量会连续倒向。参数说明tol取张量 F 范数的 1e-8 倍比固定阈值如 1e-10 更抗量纲影响压气机流场速度量级大、梯度张量数值大固定阈值很容易把所有特征值都判成实根lam_cr取第一个虚部超过容差的特征值的实部一对共轭复特征值实部相同取哪一个结果一样。R 和 λ_cr 的单位都是 1/s与涡量一致所以后处理时可以直接和涡量场对比量级。2.3 旋转轴方向统一关键数值细节特征向量作为旋转轴方向时存在一个天然歧义r和-r是同一个方向。如果不在代码里做统一输出 R 向量会在相邻网格点之间出现随机反向。我一般用dot(r, omega) 0来判断让 r 与局部涡量方向的点积非负。这样旋转轴方向在空间上连续R 向量在流场中的指向才有物理意义。极少数退化点上涡量接近零或 r 与 ω 接近垂直点积接近零符号判定会抖动。这类点本身 R 也趋于零对涡核等值面影响可以忽略。不要在代码里把这类点特殊处理成 NaNTecplot 显示时会留下空洞反而干扰后续处理。3. Matlab 实现从 CFD 速度场到 Liutex 矢量的完整流程3.1 读入结构化网格速度数据假设已经有计算出的结构化网格速度场无论是自己写的求解器还是从商业软件导出的 Tecplot ASCII 文件这一步都先把数据读到 Matlab 四维数组中。Tecplot ASCII 的 FPOINT 格式比较简单数据按 I 方向最快、J 方向其次、K 方向最慢排列每个点按顺序写 X、Y、Z、U、V、W。我习惯先扫描到 ZONE 关键字再开始读数避免不同软件导出的表头行数不一致。function [x,y,z,u,v,w] read_tecplot_ascii(fname, ni, nj, nk) % 读取 Tecplot ASCII 点序数据 % 变量顺序固定为 X Y Z U V W fid fopen(fname, r); offset 0; while ~feof(fid) line fgetl(fid); offset offset 1; if contains(upper(line), ZONE) break; end end raw textscan(fid, %f); fclose(fid); data raw{1}; npts ni * nj * nk; data reshape(data(1:npts*6), 6, []); x reshape(data(:,1), ni, nj, nk); y reshape(data(:,2), ni, nj, nk); z reshape(data(:,3), ni, nj, nk); u reshape(data(:,4), ni, nj, nk); v reshape(data(:,5), ni, nj, nk); w reshape(data(:,6), ni, nj, nk); end逻辑说明先用fgetl逐行找含 ZONE 的行找到后文件指针已经停在数据起点textscan从下一行开始读取所有浮点数。reshape成 6 列是为了把每个点的分量拆开再用reshape还原成三维数组时第一维对应 I 方向和 Tecplot 的 FPOINT 写入顺序一致。参数说明ni、nj、nk必须与 Tecplot ZONE 行里的 I、J、K 一致否则 reshape 会报错或静默错位。读取后建议先对 x、y、z 做一次单调性检查diff(x(:,1,1))出现变号说明数据顺序理解反了。3.2 核心函数逐点计算 Liutex 向量读入速度分量后用 Matlab 自带的gradient函数计算九个梯度分量再组装成速度梯度张量 D调用上一章写好的liutex_grad。注意gradient的三参数版本要求网格等间距结构网格且 dx、dy、dz 为常数时可以直接用。dx x(2,1,1) - x(1,1,1); dy y(1,2,1) - y(1,1,1); dz z(1,1,2) - z(1,1,1); [dudx, dudy, dudz] gradient(u, dx, dy, dz); [dvdx, dvdy, dvdz] gradient(v, dx, dy, dz); [dwdx, dwdy, dwdz] gradient(w, dx, dy, dz); wx dwdy - dvdz; wy dudz - dwdx; wz dvdx - dudy; Rx zeros(size(u)); Ry Rx; Rz Rx; Rmag Rx; for k 1:nk for j 1:nj for i 1:ni D [dudx(i,j,k), dudy(i,j,k), dudz(i,j,k); dvdx(i,j,k), dvdy(i,j,k), dvdz(i,j,k); dwdx(i,j,k), dwdy(i,j,k), dwdz(i,j,k)]; omega [wx(i,j,k), wy(i,j,k), wz(i,j,k)]; [Rvec, Rm] liutex_grad(D, omega); Rx(i,j,k) Rvec(1); Ry(i,j,k) Rvec(2); Rz(i,j,k) Rvec(3); Rmag(i,j,k) Rm; end end end逻辑说明速度梯度张量 D 的三行分别是 u、v、w 的三个方向导数组装顺序要和liutex_grad里的eig(D)对应。涡量用旋度公式直接算符号约定是右手系如果数据来自左手坐标系R 会整体反向需要在读入阶段先检查坐标系。参数说明gradient在边界上用单侧差分边界层第一层网格的梯度和 R 会偏大这是后处理时最需要注意的误差来源后面避坑章节会展开。三重循环在五百万网格点上大概要跑几分钟到十几分钟主要开销在eig如果网格过亿可以把外层循环改成parfor但liutex_grad内部不要共享变量。3.3 导出 Tecplot 可直接打开的数据文件计算完成后把速度原始场和 Liutex 场一起写入新的 Tecplot ASCII 文件。这样导入 Tecplot 后既可以同时显示原始速度云图和 Liutex 涡核又能在同一份数据里做截面和向量图不用来回切换文件。fidw fopen(liutex_field.dat, w); fprintf(fidw, TITLE Liutex field\n); fprintf(fidw, VARIABLES X,Y,Z,U,V,W,Rx,Ry,Rz,Rmag\n); fprintf(fidw, ZONE TLiutex, I%d, J%d, K%d, FPOINT\n, ni, nj, nk); for n 1:numel(x) fprintf(fidw, %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n, ... x(n), y(n), z(n), u(n), v(n), w(n), Rx(n), Ry(n), Rz(n), Rmag(n)); end fclose(fidw);逻辑说明numel(x)线性索引顺序与 Tecplot 的 FPOINT 顺序一致因为数据写入时 I 方向最快。变量列表里 Rx、Ry、Rz 是 Liutex 向量三个分量Rmag 是标量强度Tecplot 里既能用 Rmag 做等值面也能用 Rx/Ry/Rz 画旋转轴向量。参数说明%.6e足够后处理绘图精度不建议用%f因为速度量级跨度大固定小数位会丢失小量信息。老版本 Tecplot 打开时报 zone 类型错误可以在 ZONE 行加ZONETYPEORDERED。写完文件后用load(liutex_field.dat)读回来检查第一列是否单调递增这是最廉价的验证方式。4. Liutex 实现的常见坑现象、原因与排查4.1 旋转轴符号跳变导致 R 向量方向混乱现象输出的 R 向量在相邻网格点之间突然完全反向Tecplot 里向量图呈锯齿状等值面边界出现随机毛刺。原因特征值分解给出的特征向量方向不确定r和-r是同一根轴逐点计算时不同网格点可能落到不同符号分支上。解决在liutex_grad里强制dot(r, omega) 0时取反。如果做完这步还有个别点跳变检查这些点的涡量是否接近零接近零的区域 R 也接近零不影响涡核判断不用处理。4.2 特征值虚部判断失误把剪切错认成旋涡现象层流库埃特流这种纯剪切场Rmag 仍然和真实涡核同量级等值面密密麻麻。原因代码里用了imag(lam) 0判断实根浮点误差让纯实数根的虚部出现 1e-16 量级残留被误判成复数特征值于是走进了旋转分支。解决用相对容差tol 1e-8 * norm(D, fro)并且只要n_real ~ 1就返回零向量。更保守的做法是同时要求disc 0才给非零 R根号内非正的区域一律按非涡处理。4.3 sqrt 内判别式出现负值现象个别网格点 Rmag 突然出现 NaNTecplot 等值面在这些点附近断开。原因ω_r² - 4*λ_cr²理论上是非负的但速度场经过插值或数据格式转换后局部梯度会引入噪声导致根号内出现 -1e-10 量级的负数另一种可能是该点本身是强变形主导两个共轭复特征值的实部过大不满足强旋转条件。解决用max(disc, 0)保护同时在脚本里统计disc 0的点数。如果负值点占比小于总点数的 0.1%可以直接忽略如果超过 1%说明输入速度场没有经过良好插值或者网格变换时梯度算错了不要靠改公式掩盖。4.4 Tecplot 打开数据错位变量数与 FPOINT 不匹配现象导入 liutex_field.dat 后坐标云图出现条纹或者某个变量显示出来的数值明显不对。原因fprintf 的占位符数量与 VARIABLES 声明的变量数不一致常见的是少写一个分量或多写一个分量Tecplot 会按固定列宽读取错位后整个场都乱掉。解决检查 VARIABLES 字符串里有几个变量名fprintf 里每行就写几个%e。我一般写完后立刻用textscan读回来对比 Rmag 总量是否与计算时一致。另一个隐蔽问题是文件被 Excel 打开后另存换行符和空格都会被改Tecplot 可能读不出正确的点数所以别让编辑器碰 .dat 文件。4.5 边界差分误差让 R 值虚高现象壁面附近出现一层条带状伪涡Rmag 在贴近边界的第一层网格上突然增大向内却迅速下降。原因gradient在边界上只能用单侧差分一阶精度比内部中心差分低一到两个数量级速度梯度过大导致特征值误判R 在边界被显著放大。解决先分清是物理边界还是人为截断边界。物理壁面处建议把计算域收缩一个网格跳过最外层两点再统计数据量足够时也可以在计算前对速度场沿壁面法向做一次五点平滑但要注意不要过度平滑导致真实涡核消失。边界层的 R 虚高是所有特征值类涡判据的共性问题Q 准则同样存在不是 Liutex 特有的。5. 验证脚本正确性的三个解析场与 Tecplot 出图技巧5.1 用解析速度场做量级验证拿到新数据直接出图之前花十分钟用三个解析速度场把脚本跑一遍能避免大量后期返工。表格是三个验证用例用例速度场定义预期 Liutex 标量 R刚体旋转u-Ωy, vΩxR2Ω纯剪切uεy, v0R0刚体旋转拉伸u-Ωyεx, vΩx-εyR2√(Ω²-ε²)刚体旋转用来验证主量级是否正确纯剪切用来验证是否会被误判成涡旋转加拉伸用来验证变形贡献是否被正确剥离。第三组要求 |ε| |Ω|否则没有刚性旋转主导区R 应当返回零。nx 50; ny 50; x linspace(-1, 1, nx); y linspace(-1, 1, ny); [X,Y] meshgrid(x, y); Z zeros(size(X)); Omega 1.0; Epsilon 0.5; u -Omega*Y Epsilon*X; v Omega*X - Epsilon*Y; w 0*Z; % 后续复用 3.2 节的梯度与循环代码 % 取中心点 (nx/2, ny/2) 的 Rmag 与 2*sqrt(Omega^2-Epsilon^2) 对比逻辑说明网格中心点远离边界差分误差最小适合做定量对比期望值与数值解误差应小于 1e-8。如果误差很大优先检查组装 D 时梯度分量放的行列位置是否反了这个错误会把旋转方向算错但不影响特征值实部非常隐蔽。参数说明Ω 取 1.0 是为了让量级便于检查刚体旋转的涡量是 2Ω所以 Rmag 期望值是 2.0不需要额外换算。5.2 Tecplot 里画涡核等值面和旋转轴向量数据导入 Tecplot 后我一般先做一个 Rmag 的等值面阈值取全场最大值的一半快速看涡核空间位置再用 Rx、Ry、Rz 画 Vector确认旋转轴方向与涡量方向大致一致。等值面不要直接拖 Contour 默认值先看 Rmag 分布直方图找到有明显拐点的阈值避免被边界伪涡拉高最大值后等值面什么都显示不出来。一个实用的步骤是在 Tecplot 里创建两个切片一个垂直于旋转轴看截面涡核一个沿旋转轴看延展长度。如果涡核在切片上呈对称圆形说明旋转轴估计正确如果被拉成椭圆形说明该区域存在较强拉伸需要回到 Liutex 向量而不是只盯着 Rmag。有一次我图省事拿到新的模拟数据直接跑脚本出等值面结果壁面全是伪涡结构。排查了半天才发现是特征值判断没加容差把剪切区的实数根误判成了复共轭根。从那以后我每次换网格格式、换求解器都强制先用这三个解析场把脚本过一遍再上真实数据。希望帮到你。本文还有配套的精品资源点击获取