
刚接触多相流仿真的时候我跟你一样坐到 Fluent 面前第一件事就是对着 Multiphase Model 面板发愣——VOF、Mixture、Eulerian 三个选项摆在那里每个看起来都挺像选错了又不会立刻报错结果算完一后处理才发现流场完全不合物理直觉。这种亏我吃过不少后来才慢慢摸出规律多相流模型的选择不是看哪个“高级”或“流行”而是看你关心的物理过程本质是什么。这篇内容我从实战使用的角度把 Fluent 里的多相流模型整套拆开讲清楚包括三种主流模型的适用边界、关键参数设置、初始化与收敛排查、边界条件参数化以及 UDF 扩展尽量把你在项目里真正会碰到的决策点一次性说透。Fluent 中多相流模型全面解析1. 到底该怎么选三种多相流模型的适用边界1.1 多相流模型的公共框架体积分数不是什么神秘概念Fluent 里的多相流模型本质都是基于“相体积分数”的概念建立的。所谓相可以是气、液、固中任意两种或三种的组合每一相在网格单元里占据的体积比例就是体积分数 α。一个单元里如果液体占了 70%那气相体积分数就是 0.3液相就是 0.7所有相的体积分数之和永远等于 1。这个看似简单的体积分数却是整个多相流模拟体系的基石。无论是 VOF 还是 Eulerian求解器都是先把每一相的连续性方程或体积分数输运方程算出来再根据同一网格单元内多相共存的情况去分配动量、能量和组分。换句话说多相流和单相流最大的差异不是多了一个方程而是同一个控制体积里不再只有一个速度场和物性场相与相之间可能存在滑移可能存在质量交换还可能存在非常尖锐的相界面。理解了这点再去看 Fluent 里的三个模型你就会发现它们其实是在“相界面处理方式”和“相间作用力描述程度”这两条轴上做了不同取舍。没有哪个模型是万能的选型的关键是搞清楚你的工程问题里相界面对结果的影响有多大、相间滑移要不要显式考虑、以及你手里的计算资源允许多大的网格规模。1.2 选型判断四问我个人的习惯是拿到一个多相流问题后先问自己四个问题答案清晰了模型基本就定了一半。第一相与相之间是否存在清晰的界面比如明渠水流、波浪、液滴在空气中的运动、油箱晃动这些场景里气液界面非常明显我们关心的就是界面位置和形态变化那就直接走 VOF。反过来如果气泡或颗粒非常细小、数量巨大宏观上你根本不在乎某一个气泡长什么样只关心气含率分布或压降规律那 VOF 就吃力不讨好了。第二相间滑移速度可不可以忽略像气泡在液体中上升气液两相之间存在明显的速度差这就是滑移。如果两相速度几乎一致比如微细颗粒在水流中随流输运Mixture 模型的简化假设就够用了。滑移显著且对精度要求高的时候优先考虑 Eulerian 模型。第三是否涉及颗粒相、流化床、气力输送这类离散颗粒动力学主导的过程这类问题一般需要 Eulerian 模型配合颗粒动力学理论因为要计算颗粒之间的碰撞摩擦产生的颗粒压力、颗粒黏度等属性。Mixture 模型虽然也能算一部分颗粒问题但物理机制上做了太多简化工程上做定量分析不太推荐。第四计算资源有多少这个问题很现实。同样一个搅拌槽Eulerian 双流体模型需要的方程数量和内存开销都要明显高于 Mixture而 VOF 如果要做精细的自由液面捕捉网格量通常又比 Mixture 大得多。所以资源有限的时候常常需要接受 Mixture 模型的简化精度。1.3 三种模型对比与典型应用场景模型界面捕捉能力相间滑移相间作用力典型场景计算开销VOF强支持几何重构不显式计算共享速度场仅表面张力自由液面、波浪、液滴、晃荡中高依赖网格Mixture弱相界面模糊通过代数滑移速度近似简化的曳力和空化源项含气率分布、空化、沉降低Eulerian弱界面非真实捕捉完整求解多速度场曳力、升力、虚拟质量力、碰撞力等流化床、气泡柱、颗粒输运高这里要特别提醒一点VOF 和 Eulerian 不是替代关系而是物理视角完全不同。VOF 默认全场只有一个速度场相之间没有滑移也就是所谓“均匀流”假设Eulerian 则允许每一相有独立的速度场。选 VOF 去算气泡柱界面算出来是漂亮了但气泡和液体的相对运动被抹掉了这是原则性错误。选 Eulerian 去算水面晃动又会因为界面数值扩散导致相界面被抹得模模糊糊同样不是好结果。2. VOF 模型实测精讲从相界面设置到库朗数控制的完整链路2.1 VOF 的核心机制体积分数输运与几何重构VOF 模型的核心是求解体积分数的输运方程方程本身不复杂真正影响计算质量的是“界面重构”这一步。Fluent 里最常用的界面重构方法是 Geo-Reconstruct它利用每个单元内体积分数的分布重新构造一个分段线性的界面然后再计算通过单元面的对流通量。换句话说它是用几何方法“画”出界面而不是靠单纯数值格式把界面抹开。使用 Geo-Reconstruct 有两个前提条件需要特别留意。第一个是必须使用显式体积分数格式因为隐式格式在时间上做了更多平均化处理界面会被显著钝化无法保证几何重构的锐利效果。第二个是网格最好以六面体或高质量多面体为主三角形或四面体网格虽然支持但在界面处更容易出现伪速度也就是所谓的寄生电流现象数值上表现为液面附近出现成对的微涡结构。表面张力模型一般选择 CSF 连续表面力模型给定表面张力系数和接触角即可。如果计算的是水气两相这么大尺度的流动表面张力常常可以忽略但如果是微流控里的液滴生成表面张力就成了主导因素这时建议同时打开 Wall Adhesion 选项并正确设置接触角否则液滴在壁面上的铺展行为会和实验对不上。2.2 主相与次相的选择逻辑VOF 参数设置里有一个经常被忽略的决策点哪种介质设为 Primary Phase哪种设为 Secondary Phase。我见过不少人在这一步随手点结果后面 patch、后处理全都乱了。Fluent 里主相的选择原则其实很简单——把不可压缩的连续相或体积占优的相作为主相计算上会更稳定。比如模拟水箱里的水和大气的自由液面大气包在四周水在底下通常更建议把空气设为主相水设置为次相。这样在计算域初始全是空气的时候次相水的体积分数为 0patch 起来非常自然。反过来也不是不行但要注意 patch 时体积分数的绝对数值是基于次相来定义的主相体积分数永远等于 1 减去次相体积分数容易把自己绕晕。这里就涉及 patch 操作。VOF 初始化之后直接用标准初始化通常是不行的因为初始时刻整个计算域要么全是水要么全是空气真实的初始场需要你把一部分区域指定为某种相。常见做法是用 Adapt Region 功能把目标区域选中再通过 Patching 把水的体积分数在该区域内设置为 1。实际操作中我建议 patch 水区之前先把水的初始速度、压力都准备好一次性 patch 完整避免多次 patch 导致某些边界上的体积分数状态不一致。2.3 库朗数控制时间步长一个必须刻在脑子里的公式VOF 显式格式对时间步长有一个硬性约束那就是库朗数。Fluent 中 VOF 的全局 Courant Number 默认允许最大值是 0.5 到 1 之间但实际工程中我建议保持在 0.5 以下尤其是液面附近流动速度较快的时候取值越大界面越容易出现数值波动。库朗数公式长这样Courant v × Δt / Δx其中 v 是局部流速Δt 是时间步长Δx 是局部网格尺寸。这意味着时间步长的选取不能只看计算稳定性还要看网格尺寸和流速。举一个我实际调过的例子一个二维水槽入口流速 1 m/s液面附近最小网格 2 mm如果要保证库朗数 0.5那么 Δt 0.5 × 0.002 / 1 0.001 秒也就是毫秒量级。很多人一开始不管网格尺寸直接把时间步长设成 0.05 秒算到几十步就开始发散本质问题就在这里。对于速度本身就在变化的瞬态过程你也可以开启自适应时间步长让 Fluent 根据局部库朗数自动调整 Δt。这个方法我强烈推荐给做波浪或晃荡模拟的朋友省下来的调参时间非常可观。2.4 界面模糊与伪速度的实战排查经验VOF 算出来最常见的两个异常一个是界面“糊”了一个是界面附近出现假涡。界面糊掉的直接原因通常是数值扩散。虽然 Geo-Reconstruct 对界面的锐利度已经处理得很好但如果计算中使用了过大的时间步长导致库朗数多次超过上限界面还是会被抹开。另外如果模型设置时选择了隐式体积分数格式也要有界面变模糊的心理准备。隐式格式适合做稳态或弱瞬态问题自由液面动态捕捉场景下不推荐。伪速度则复杂一些它和界面处的表面张力计算、网格正交性都有关系。改进手段一般从三个方面入手检查网格质量保证界面附近网格的歪斜率低于 0.7降低全局库朗数让表面张力项在时间推进中更平滑对于水气密度比极大的情况可以考虑在初始化阶段给压力场一个合理的静水压力分布而不是让求解器从零压力场开始硬算。3. Mixture 模型和 Eulerian 模型滑移、曳力与颗粒相的处理细节3.1 Mixture 模型代数滑移速度与空化模拟Mixture 模型可以理解为简化版的 Eulerian 模型它求解混合物的动量方程然后通过一个代数滑移关系来描述相与相之间的相对速度。这样做的好处是方程数量少收敛相对容易坏处是滑移速度的表达是近似公式复杂流动下精度有限。Mixture 模型最成功的工程应用场景我认为是空化模拟。空化本身涉及液相蒸发和气相凝结相间质量交换非常快相又会经历从微气泡到蒸汽腔的剧烈形态变化用 VOF 去捕捉蒸汽腔不是不行但计算量极大。Mixture 模型配合空化模型使用 Schnerr-Sauer 或 Zwart-Gerber-Belamri 模型在泵、阀门、水翼这类问题上被验证过大量案例效率非常高。使用 Mixture 做空化模拟时有一个关键操作需要特别留意饱和蒸汽压 Pv 的设定。这个参数直接影响蒸发凝结的驱动压差不同温度下差异很大。20 度水的饱和蒸汽压大约 2340 Pa但如果你算的是高温工况比如 80 度水饱和蒸汽压会升高到接近 47 kPa继续用默认值就会导致空化区域计算严重失真。每次建模前先查好工况温度对应的物性这步省不得。3.2 Eulerian 模型的相间作用力模型选择Eulerian 多相流模型把每一相都当作完全独立的连续介质来处理每相都有自己的连续性方程和动量方程相与相之间通过作用力源项耦合。这个框架最严谨但也最容易“调不动”因为耦合作用力项的存在让方程组非线性程度变得非常高。相间作用力里面最重要的一项是曳力。Fluent 里常见的曳力模型包括 Schiller-Naumann、Morsi-Alexander、Symmetric 等。对于气泡或者液滴在液体中运动的情况Schiller-Naumann 模型在低相对雷诺数下表现稳健是许多工程计算的默认选择。Morsi-Alexander 模型适用范围更宽因为它基于实验数据拟合了一个多段关系式但数值稳定性稍差容易在气液两相密度比大的时候出现振荡。另一个容易被忽略的是虚拟质量力。当气泡在液体中加速运动时周围液体会被带动这部分的惯性效应就通过虚拟质量力体现。稳态计算里这个力可以忽略但瞬态计算尤其是气泡柱启动阶段虚拟质量力的影响还是比较明显的。建议至少开启一次测试它对结果的影响再决定是否保留。升力同样值得关注它在剪切流场中会把气泡推向壁面或中心。流化床和气泡柱的径向气含率分布很大程度上就是由升力决定的。Fluent 中升力系数默认值一般取 0.1 到 0.5 之间具体数值随手册和文献调整。3.3 颗粒流道颗粒动力学理论与收敛性调节Eulerian 模型处理气固两相流时需要开启颗粒动力学理论也就是 Granular 选项。这时固相除了遵循连续介质方程外还要额外求解颗粒温度方程用来描述颗粒随机运动引起的颗粒压力、颗粒剪切黏度和颗粒体积黏度。这些参数本质上来自分子动力学类比但对应的是宏观颗粒群。调节颗粒相时最常遇到的问题是固相体积分数接近堆积极限时求解发散。这时看残差曲线你会发现压力残差掉不下去速度残差在某个水平震荡。我的处理套路是把固相动量方程的欠松弛因子从默认的 0.2 调到 0.1 以下压力松弛因子保留在默认值附近先把计算稳定下来再逐步提高松弛因子加速收敛。同时检查颗粒体积分数上限也就是 Packing Limit流化床一般取 0.63 附近。对多相流搅拌、流化床这类强非线性问题一个非常实用的技巧是先用较简单的 Mixture 模型或者单相流算出一个收敛的初场然后切换到 Eulerian 模型继续算。这招可以显著降低 Eulerian 模型从头开始迭代时的发散概率我自己在用这个技巧时成功率很高。4. 边界条件参数化与流量正负判定的实操逻辑4.1 入口边界条件参数化把速度、流量变成可扫掠的变量很多人在做多工况分析时习惯一次次手动改入口速度、再重新初始化效率低而且容易出错。Fluent 从较新的版本开始已经支持直接把边界条件数值参数化。操作路径是在图形区右键点击入口边界名称选择 Create Parameter 选项然后选中你要参数化的速度或温度值Fluent 会自动在参数面板里生成对应的输入参数。更流畅的做法是在 Workbench 里建立参数化流程。在 Fluent 里把入口速度参数化之后回到 Workbench 的 Project Schematic把该参数提升为 Parameter Set然后在 Design Points 表格里填多组工况值Workbench 会自动依次调用 Fluent 完成计算。这套流程配合并行计算非常适合批量研究入口流速对混合效果或压降的影响。参数化过程中有个小坑需要提醒如果入口边界条件还用到了 Profile 文件或 UDF参数化面板里不会直接显示 Profile 中的数值这时需要把 UDF 里的关键常数也做成可参数化的变量。做法是在 UDF 中用 RP_Get_Real 读取以 Parameter 名义传入的变量这部分稍微有点绕但在参数化扫掠时真的省事。4.2 出口入口流量正负判定别再被符号绕晕经常有朋友来问为什么 Fluent 的 Flux Report 里入口流量是负值我明明记得入口是朝里流的这还有个小知识点Fluent 默认约定流出为正、流入为负。也就是说一个正常的入口边界质量流率报告出来后大概率是负值出口是正值。判断正负的核心是看面法向向量与速度向量的点积点积为正就是流出为负就是流入。实际操作时我建议别依赖记忆直接在 Report 面板里看每个边界的名称把入口、出口列出来检查它们的绝对值之和是否相等。如果入口加出口的质量净流量不等于零而且差值明显大于 0.1% 量级那说明计算域内存在质量不守恒要么是边界条件没给对要么是存在泄漏。另外还要留意压力出口在多相流中的行为。压力出口会允许流体双向流动当计算域内部压力波动导致流体反向进入时出口边界的流量符号可能瞬时反转。这时候监测流量绝对值变化比盯着正负号更直观也可以给出口设置一个回流条件让回流流体的相组成更容易收敛。4.3 流量平衡检查与残差曲线配合使用多相流计算里只看残差曲线是一个很危险的判断方式。残差下降得再漂亮如果进出口质量流量不平衡、整体相体积分数不守恒结果仍然不能信。我每次计算收尾前都会做三个检查第一Setup 里设置 Report Definitions 来监测进出口质量流率和任意截面上的平均体积分数随时间变化第二在残差收敛后查看 Flux Report确认总质量不平衡量在 0.01% 量级以下第三用体积积分命令统计整个计算域的相体积分数确保没有莫名其妙的相消失或生成。这三个检查里第二个最容易被人忽略但它恰恰能揪出很多边界条件设置错误。比如我曾经在计算中把某个壁面误设成了压力出口残差照样收敛但流量平衡死活对不上最后靠 Flux Report 才发现问题。记住残差是用来判断代数方程组求解精度的物理守恒则要自己去验证。5. 初始化方法与收敛容差求解之前必须要搞清楚的几件事5.1 标准初始化与混合初始化到底差在哪熟悉 Fluent 2020 以上版本的朋友应该都见过每次初始化时弹出的选择框一边是 Standard Initialization一边是 Hybrid Initialization。很多做多相流的人习惯默认选 Standard殊不知在多相流场景下 Hybrid 往往是省心的那个。标准初始化的逻辑很简单用你在面板里填的初始值均匀铺满整个计算域然后从边界条件往内部推进。这种方式干净利落但多相流里最大的问题是初始场可能非物理。比如你设置一个气液两相系统入口是水但初始全场都是气标准初始化可能会在入口处造成一个巨大的体积分数突变迭代初期残差直接飙上去。混合初始化则是 Fluent 自动构造初始场的一套算法会求解拉普拉斯方程来生成一个平滑速度场和压力场同时对多相流还会自动安排相的分布。它最大的好处是减少初始场的突变让计算在早期更稳定。对于多相流问题尤其是没有明确初始相分区的时候我会优先用 Hybrid然后再根据需要对特定区域重新 patch。但 Hybrid 也不是没有弊端。它对网格质量的要求比较高如果网格里存在严重歪斜的单元Hybrid 初始化可能在初始化阶段就报错或速度场发散。另外它自动生成的相分布不一定符合你的物理预期所以初始化完成之后一定要先看一眼体积分数云图再开始迭代。5.2 初始化未达到收敛容差的提醒怎么判断能不能继续算有朋友遇到 Fluent 提示 “Initialization did not converge” 或者类似的收敛容差告警问我是不是模型废了。其实这个提示要分情况。如果你用的是 Hybrid Initialization它内部会进行若干步迭代来构造初始场如果代数迭代没有达到默认容差Fluent 会给出这个警告。出现这个警告首先要排查的是网格质量因为网格歪斜率大时拉普拉斯方程求解本身就难收敛。其次检查计算域是否存在封闭性问题比如是否有面没有配对、有小的缝隙导致求解器无法给完整计算域建立内部关联。如果网格和几何都没问题这个警告未必会中断计算。我的建议是忽略警告继续算几步观察残差和流场是否正常发展。如果残差从一开始就在高位震荡再回头处理初始化问题。要知道初始化只负责给你一个合理的起点真正决定结果品质的是后续迭代只要起点不疯狂后续求解大概率能自己校正过来。5.3 多相流计算的收敛判据不要只盯残差单相流计算里残差降到 1e-4 经常被当作收敛标准多相流里这个习惯要改一改。由于相与相之间存在强耦合多相流残差经常在某个水平上震荡着下不去比如 1e-3 就到头了。这时候强行追求更低的残差不仅浪费时间还可能让松弛因子被调得很低导致计算停滞。我自己的判断标准是三层结合第一层是残差要求至少下降三个数量级且不再持续上升第二层是全局变量监测进出口流量差、平均相体积分数、监测点压力这几条曲线都要基本平稳第三层是物理合理性液相体积分数云图、速度矢量图没有异常突变监测点的变量变化趋势符合工程直觉。三层都通过了哪怕残差还停在 1e-3我一样会认为这个多相流计算已经收敛。这个经验在流化床和气泡柱这类难收敛问题上特别有用。6. UDF 与外部数据导入复杂工况下的多相流增强手段6.1 UDF 在边界条件和源项中的典型用法当标准边界条件不够用时就该 UDF 上场了。多相流中最常见的 UDF 场景有三个入口速度随时间或空间变化、自定义初始相分布、以及自定义相间质量源项。以入口速度随时间变化为例一个最简单的 DEFINE_PROFILE 宏长这样#include udf.h DEFINE_PROFILE(inlet_velocity_time, thread, position) { face_t f; real t CURRENT_TIME; begin_f_loop(f, thread) { F_PROFILE(f, thread, position) 2.0 * sin(2.0 * M_PI * 0.5 * t); } end_f_loop(f, thread) }这段代码的含义是让入口速度以 2 m/s 的幅值、0.5 Hz 的频率做正弦变化。使用前需要把入口边界的速度类型改为 UDF并在编译完成后在边界条件面板里选中这个 profile。多相流里用 DEFINE_SOURCE 自定义相间质量源项也很常见比如模拟蒸发冷凝时你可以在能量方程和相方程中分别加入对应的质量源项。这时需要特别注意单位一致性Fluent 中源项的单位是 kg/(m³·s)不少人在这里把量纲搞错导致质量凭空多出来一块。6.2 把外部实验数据作为输入Profile 文件与临时数据导入有时候边界条件不是简单的公式而是来自实验测得的离散数据这时用 Profile 文件是最直接的办法。Fluent 的 Profile 文件是纯文本格式用于瞬态数据的基本结构如下((velocity-inlet transient) (time 0 0.5 1.0 1.5) (vz 0 1.2 1.5 1.8))这个文件定义了一个名为 velocity-inlet 的瞬态 Profile在 0 时刻速度是 00.5 秒是 1.2 m/s以此类推。在 Fluent 中通过 File → Read → Profile 导入后进入速度边界条件面板选择 velocity-inlet 作为速度 Profile求解器会在时间推进时自动插值。对于空间分布的数据则需要在 Profile 文件中同时给出坐标点格式比瞬态 Profile 复杂一些需要把所有网格点坐标和对应的速度都列出来。考虑到手动整理这个文件很痛苦建议提前准备好脚本从实验数据导出时就直接生成 Fluent 可识别的 Profile 文本。如果数据量特别大或者 Profile 文件格式怎么调都报错还有一个备选方案把数据写入二维数组通过 UDF 里的 DEFINE_PROFILE 循环读取。但这个方法对内存占用比较高只适合中等规模数据数据量几十万行以上的时候Profile 文件仍然是首选。6.3 UDF 编译环境配置与并行计算的注意事项最后聊聊 UDF 编译环境。每次在不同电脑上装 Fluent 之后都要重新折腾一遍编译这里有几个坑值得记一下。首先要保证 Fluent 版本和 Visual Studio 版本匹配新版 ANSYS Fluent 2024 R1 对 VS2022 有官方支持。如果 VS 安装在非默认路径需要手动配置 udf.bat确保其中的 VS 路径指向正确。很多人编译报错“无法打开头文件 udf.h”百分之八十是环境路径没配对。其次是并行计算时加载 UDF 需要额外小心。在单机上用共享内存并行UDF 编译后应该能直接加载但如果用分布式并行需要确保各节点能访问到 UDF 库文件否则会出现计算开始后 UDF 无法初始化的问题。多相流 UDF 如果涉及到相间作用力强烈建议先用单相流或简化模型验证 UDF 逻辑正确再切换到目标多相流模型否则出了 bug 你根本不知道是 UDF 的问题还是多相流本身不收敛的问题。还有一个容易被忽视的点就是 UDF 中的密度、黏度等物性参数读取。多相流里 C_R(c, thread) 必须在正确的相线程下调用否则取到的是主相的物性而不是你期望的次相。这个错误十分隐蔽因为不报错、只出偏差排查起来非常费劲。每次把多相流案例做完回头看我都会想Fluent 里的多相流模型虽然多但工程应用的核心从来不是模型本身的技术细节而是你对物理过程的理解程度。界面怎么处理、滑移要不要算、曳力用什么模型、初始场怎么给这些问题都源于你对自己要模拟的那个现象的直觉判断。所以如果你想长期做多相流模拟我建议你花点时间把 VOF 的库朗数控制、Eulerian 的相间作用力模型这些基本功打扎实再用一批小案例反复练习真正把这些参数背后的物理意义变成自己的肌肉记忆。这样以后遇到再复杂的多相流工程问题你也能在建模第一步就做出大概率正确的选择。