尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CFD不可压缩流算法解析:从SIMPLEC到PISO的选型与调参

CFD不可压缩流算法解析:从SIMPLEC到PISO的选型与调参 做CFD的都知道算不可压缩流的时候最让人头疼的就是压力和速度之间的纠缠关系。动量方程里有压力梯度项但压力本身却没有独立的控制方程只能通过连续性方程来约束速度场。这就导致我们在求解时不能直接一次性得到答案必须走预测-修正的迭代路线。而在这一堆修正算法里PISO和SIMPLEC是我个人用得最多的两个也恰恰是很多新手容易混淆的两个。这篇就从原理到实操把这两兄弟彻底掰开揉碎讲清楚。很多人一开始接触PISO和SIMPLEC都是因为OpenFOAM或者Fluent里的求解器设置选项。但说实话如果不知道它们背后的修正逻辑你连残差曲线都看不懂更别说针对自己的算例去调算法参数了。这篇文章我会先用大白话解释为什么不可压缩流必须要用这类算法再分别拆解SIMPLEC和PISO的修正步骤最后结合我在实际项目中遇到的收敛问题给你一套可以直接用的选型和排错思路。1. 压力-速度耦合为什么SIMPLE家族如此重要1.1 压力没有自己的方程先回忆一下不可压缩Navier-Stokes方程。连续性方程是速度散度等于零动量方程是那个包含压力梯度、对流项和扩散项的偏微分方程。如果直接离散这个方程组你会发现矩阵里压力项出现在动量方程中但是压力本身没有任何时间导数项也没有独立的演化方程。这就意味着压力更像是一个拉格朗日乘子它的作用是在每一步强制速度场满足连续性约束。如果我们把压力项去掉速度场就会变成纯对流扩散问题解出来根本满足不了质量守恒。所以压力场的本质是通过连续性约束反算出来的。这就带来一个麻烦离散后的代数方程是耦合的而且压力矩阵常常是奇异或半正定的直接做联立求解在大多数非结构网格上都非常困难内存和时间开销也大得离谱。因此工程上几乎没有人去做完全的隐式联立求解大家都走分离式求解这条路。分离式求解的核心思想就是先猜一个压力用动量方程算出速度再修正压力让速度满足连续方程。这个猜-算-修的循环就是SIMPLE家族的共同基因。PISO和SIMPLEC的区别不过是在这个循环里多修几步、少修几步、用什么近似来修正而已。1.2 分离式求解的通用框架所有SIMPLE类算法都可以总结成一个大框架用当前的压力场求解动量方程得到一个不满足连续性的预测速度。通过压力修正方程算出一个修正量。用修正量更新压力和速度。判断收敛不收敛就重复。这个框架里最关键的一步是建立速度修正量和压力修正量之间的线性关系。SIMPLE算法在这里做了一个近似把邻居单元的速度修正直接丢掉只保留本单元的修正。这个近似对对角线占优有利但也带来了收敛慢的问题。SIMPLEC和PISO的差异本质上就是对这个近似的处理方式不同一个是从系数上补偿一个是从迭代结构上补偿。1.3 为什么不能多迭代几次就完事有人会问既然都是迭代那我用最简单的SIMPLE算法多迭代几次效果不也一样吗理论上对于稳态问题多迭代确实能收敛到同一结果。但实际问题讲究的是收敛速度和稳定性。SIMPLE算法的这个近似在网格长宽比很大的边界层网格上会让压力修正量算得过猛或过偏导致残差震荡甚至发散。这时候你加再多迭代步数都没用需要从算法层面去改进这也就是SIMPLEC和PISO存在的意义。2. SIMPLEC算法拆解2.1 从SIMPLE到SIMPLEC的一步之遥SIMPLEC的全称是SIMPLE-Consistent意思是一致的SIMPLE。它和SIMPLE的唯一区别就在处理邻居速度修正的时候不再完全丢掉了。SIMPLE算法假设邻居单元的速度修正为零这样压力修正方程的形式很简单但代价是每轮修正量偏小需要多迭代。SIMPLEC的改进思路是既然邻居速度修正不能精确算出来那我就不假设它为零而是把它近似地表达成本单元速度修正的某种比例。具体来说在推导压力修正方程时把邻居修正项移项合并到本单元的系数里这样一来求解出的压力修正量代表了整个单元块的平均修正趋势更接近真实解。虽然压力修正方程的非对角项变复杂了但在很多算例里一次修正就能达到SIMPLE两三次修正的效果。2.2 SIMPLEC的修正方程怎么说这里我用一个简化的二维不可压缩流动来说明。离散后的动量方程可以写成a_P * u_P Σ a_N * u_N - (∂p/∂x)_P * V_P b_P其中a_P是本单元系数a_N是邻居系数u_N是邻居速度b_P是源项。引入压力修正 p 和速度修正 u 之后速度修正满足类似的关系a_P * u_P Σ a_N * u_N - (∂p/∂x)_P * V_PSIMPLE的做法是忽略Σ a_N * u_N这一项于是u_P - (V_P / a_P) * (∂p/∂x)_PSIMPLEC不忽略邻居项而是用一个近似把Σ a_N * u_N表示成 u_P 乘以某种系数加权。这样处理之后速度修正u_P的表达式分母会从 a_P 变成 a_P - Σ a_N这个修正量在数值上比SIMPLE更大修正效果也更直接。如果你去看OpenFOAM的源码会发现SIMPLEC的压力修正方程系数里面确实多了一个求和项就是干这个用的。2.3 SIMPLEC适合哪些情况在我的经验里SIMPLEC在稳态问题里的表现往往比SIMPLE好尤其当网格质量一般、存在大长宽比单元的时候。因为它的修正路径更直接不容易因为邻居速度被忽略而出现修正滞后。对于不可压缩稳态流、传热共轭问题、多孔介质流动这类计算SIMPLEC是很好的默认选择。不过也要注意SIMPLEC对松弛因子的取值比SIMPLE更敏感。因为它修正得比较猛如果压力松弛因子给得太大很容易在迭代初期产生压力场的过冲。我常用的做法是压力松弛因子取0.7到1.0之间速度松弛因子取0.7到0.8之间具体还要看算例的非线性强度。记得先小后大等残差有下降趋势了再逐步提升。3. PISO算法拆解3.1 两步修正的来历PISO的全称是Pressure-Implicit with Splitting of Operators最早是为了模拟非稳态可压缩流提出的后来被广泛用在不可压缩瞬态计算中。PISO和SIMPLECAC最直观的区别是它在每轮迭代里做了两次压力修正而不是一次。PISO的计算流程是这样预测步用当前压力求解动量方程得到预测速度。第一次修正构造并求解压力修正方程更新压力和速度。第二次修正重新计算速度修正与压力修正之间的耦合关系再次求解压力修正方程。这里的第二次修正并不是简单重复而是把第一次修正后仍然存在的速度散度残余再处理一遍。因为第一次修正方程本身也是基于近似得到的所以总会有残差。PISO的第二步修正能把这些残差再压下去一截得到更满足连续性的速度场。3.2 瞬态计算中的时间步优势PISO在瞬态计算里的优势主要体现在它可以配合更大的库朗数Courant number。由于每一步内做了两次修正速度场在每个时间步内更接近满足连续性约束因此即使对流项比较强也不容易因为压力-速度失配而产生震荡。我用它算过圆柱绕流和机翼附近的非定常流动在库朗数接近0.8-1.0的时候PISO依然能维持稳定的残差下降而SIMPLEC如果库朗数超过0.5就有点危险了。当然PISO也不是万能的。它的两次修正会让每一步的计算量比SIMPLEC大一些但这个代价换来了更大的稳定时间步在瞬态问题里往往非常划算。如果你的算例时间依赖性很强比如涡街脱落、颤振这类现象PISO基本是首选。3.3 PISO的边界条件敏感性PISO算法对边界条件的处理比SIMPLEC更敏感尤其是出口边界。因为第二次修正会重新计算压力场和速度场的耦合关系如果出口边界的压力设定不合理很容易出现回流时压力场的振荡。我在实际项目中就遇到过出口设置为固定压力但计算域出口附近有强回流的情况PISO算出来的出口附近压力出现了锯齿状分布后来把出口段加长作为缓冲域才把这个问题压下去。还有一点PISO在面对非正交网格时非正交修正项的处理要格外小心。OpenFOAM里用PISO必须注意nonOrthogonalCorrectors的设置如果网格非正交度高建议把它设为3到5次否则会看到压力残差先降后升怎么都压不下去。这一点在很多新手教程里都没提我踩过坑之后就特别注意了。4. PISO与SIMPLEC的横向对比4.1 修正逻辑的对比SIMPLEC和PISO虽然都是为了克服SIMPLE收敛慢的问题但它们走的是两条完全不同的路SIMPLEC是从修正量计算入手通过保留邻居速度修正项来让每轮修正更准确从而减少迭代轮数PISO是从修正流程入手通过一轮预测加两轮修正让同一预测步内的压力-速度耦合更紧密从而减少时间步内误差。打个通俗的比方SIMPLEC像是一个判断力很强的医生一次诊断就基本找准病灶PISO像是一个严谨的医生看一次不放心复查一次再确认。对于慢性病稳态问题SIMPLEC效率更高对于急性发作瞬态问题PISO的复查机制更保险。4.2 参数与适用场景速查这里我整理了一个在实际选型时经常参考的对比表对比维度SIMPLECPISO修正次数单次修正两次修正主要适用场景稳态问题瞬态问题对大长宽比网格的容忍度高中高对库朗数的承受能力较低建议小于0.5较高可到0.8-1.0每步计算量小中压力松弛因子建议0.7-1.01.0一般不用松弛速度松弛因子建议0.7-0.81.0对出口边界条件敏感性中高需要注意的是现在的商业CFD软件里Fluent对PISO也做了很多细节优化比如自动开启偏斜修正和邻近修正所以它的适用性比教科书里说的更广。但在OpenFOAM这类开源工具里你还是需要手动去配置这些修正项的这时候理解原理就特别重要。4.3 选型决策先问自己三个问题如果你现在要开始一个新的算例不知道怎么选建议先问自己三个问题第一是稳态还是瞬态稳态首选SIMPLEC瞬态首选PISO。第二网格质量如何如果网格长宽比大、非正交度高SIMPLEC更能抗干扰PISO就需要多开非正交修正。第三计算资源紧张吗资源紧张、时间步数多PISO的两次修正虽然每步贵一点但稳定时间步可以放大总体算下来往往更省。我用这套思路处理过很多通风管道、换热器、阀门内部流场的项目大部分情况下都能在第一次试算时就选对算法省去了反复试错的时间。5. 实战在OpenFOAM和Fluent中的设置与调参5.1 OpenFOAM中的算法选择在OpenFOAM里选择算法本质上就是选择用哪个求解器icoFoam和pimpleFoam里你可以通过fvSolution文件中的solver和PISO关键字来控制算法。举个例子对于瞬态不可压缩流动如果要用PISO你会在fvSolution里看到类似这样的配置PISO { nCorrectors 2; nNonOrthogonalCorrectors 2; pRefCell 0; pRefValue 0; }nCorrectors对应的是每一步内压力修正的次数PISO一般设2到3次设太大了收益也不明显。nNonOrthogonalCorrectors对应非正交修正的次数网格越歪这个值越要大但每次非正交修正都要额外求解一次压力泊松方程计算量会增加所以网格质量好的话保持1到2就够。如果你想用SIMPLEC做稳态计算可以用simpleFoam自带的SIMPLE算法也可以手动调整相关参数达到SIMPLEC的效果。simpleFoam里的SIMPLE子字典中有一个consistent选项OpenFOAM早期版本可以通过设置这个参数来启用SIMPLEC模式新版则通过不同的求解类名来实现。如果你用的版本支持直接SIMPLE { nNonOrthogonalCorrectors 0; consistent yes; }5.2 Fluent中的面板配置在Fluent里操作就更图形化了。打开Solver设置面板在Solution Methods页你可以看到Scheme下拉菜单里有SIMPLE、SIMPLEC和PISO三个选项。对于稳态计算我一般在Fluent里选SIMPLEC并把Skewness Correction和Skewness-Neighbor Coupling两个选项打开能显著改善非结构网格上的收敛性。注意面板上有一个Skewness Correction下拉菜单默认可能是0建议根据网格偏斜程度选1或2。对于瞬态计算选PISO后会出现两个子选项Skewness Correction和Neighbor Correction。如果网格质量不错Neighbor Correction保持1就够如果局部网格有畸变Skewness Correction可以开到2或3。我遇到过一个复杂装配体的流动局部四面体网格质量很好但偏斜不小开Skewness Correction 3之后压力残差直接从振荡变为平顺下降。在Fluent里还要注意选定算法后亚松弛因子并不总是在面板上直接暴露。SIMPLEC算法下如果你在Solution Controls里看到Pressure和Momentum的松弛因子建议初始值设为0.7和0.7不要贸然调到1.0。虽然从原理上SIMPLEC可以不用松弛但实际算例里非线性源项的影响还是需要一点过渡的。5.3 离散格式的配合算法选好了离散格式也不能随便配。我的经验是算法与离散格式的匹配优先级是先保证收敛再追求精度。对SIMPLEC动量方程建议先用一阶迎风格式迭代几百步让残差降下来再切到二阶迎风格式继续算。否则一开始就用高阶格式流场还在剧烈调整中很容易在激波或回流区出现振荡。对PISO如果库朗数已经比较高空间格式也尽量用有界格式比如Fluent里的Third-Order MUSCL或OpenFOAM里的linearUpwind能减少数值振荡。压力插值格式也很关键。OpenFOAM里默认的动量插值就是为压力-速度耦合设计的不要随便改成线性插值。Fluent里压力插值一般选Second Order但如果你的算例旋转或强体积力主导可以考虑PRESTO格式。5.4 松弛因子和时间步长的联调最后说说松弛因子和时间步长的关系。稳态算法SIMPLEC没有时间步的概念所以只能靠松弛因子控制收敛速率。瞬态算法PISO有时间步松弛因子一般就保持1.0不能靠降低松弛因子来救场只能缩小时间步。这里有一个我常用的经验公式先估算你物理尺度下的对流时间尺度初始时间步设为它的百分之一比如特征长度0.1米、流速1米每秒对流时间尺度是0.1秒那初始时间步就取0.001秒。算起来之后看库朗数如果最大值超过1.0就把时间步减半。这种保守起步、动态调整的方式能在稳定性和计算效率之间找到很好的平衡。6. 收敛问题排查实录6.1 压力场出现棋盘振荡如果残差曲线一路下降但压力场看起来像跳棋盘一样一格高一格低这大概率是压力-速度失耦问题。这个问题在SIMPLEC算法中更常见尤其是使用同位网格collocated grid的时候。虽然现在的代码都用Rhie-Chow插值来抑制压力振荡但如果插值系数设置不当还是会出现spurious oscillation。排查思路是这样先检查压力松弛因子是不是偏高SIMPLEC下控制在0.7左右再检查动量方程离散格式如果是一阶格式可以切到二阶试试最后检查网格质量那些长宽比特别大的单元往往是振荡的发源地。我在一次管壳式换热器模拟中就是因为局部网格长宽比超过2000压力场总是振荡后来重新切网格把长宽比压到500以下问题才彻底解决。6.2 残差停滞在某个水平降不下去这种情况在SIMPLEC算法里很常见通常表现为残差在前几百步大幅下降然后卡在1e-3就不再动了。我的第一反应是检查通量平衡。在Fluent里看报告里的Net Imbalance如果进出口质量流量差超过千分之一说明问题出在边界条件或网格上而不是算法本身。第二反应是检查有没有回流穿透出口边界。如果出口设置成压力出口但回流区域很大SIMPLEC求解器会在边界上来回调整压力导致残差波动。解决办法是加长出口段或者改用outflow边界条件让流动充分发展后再出域。还有一招对稳态问题可以在迭代过程中切换算法。先用SIMPLEC或PISO先跑几百步把流场大致建立起来再切回SIMPLE继续迭代到收敛。这招对很多强非线性算例有奇效因为PISO和SIMPLEC的前期修正能力更强能更快把流场拖出初始猜测的误区。6.3 PISO瞬态计算中库朗数过大引起发散PISO可以承受更高的库朗数但也不是无上限。如果你发现某个时间步内残差突然翻倍或发散十有八九是局部网格太细导致库朗数局部爆表。PISO虽然做了两次修正但如果库朗数超过2很多情况下也压不住。我的排查经验是先用后处理看一下每个网格单元的库朗数云图找到超标的局部区域。如果只是少数小网格引起最简单的办法是局部加密这些区域的网格把库朗数降下来比全局缩小时间步划算得多。如果整场库朗数都高那就老老实实时间步减半。还有一次我遇到过一种奇怪情况PISO算法在时间推进几千步后压力残差突然上升。最后发现是物性参数在某个温度区间内突变导致密度不可压缩假设失效。这时候选什么算法都没用得先确认你的流动前提是否成立。不可压缩求解器算到接近可压缩的区域必然发散这不是算法的问题是模型选择的问题。6.4 非正交修正次数该怎么调在OpenFOAM里用PISO时nNonOrthogonalCorrectors设置不当是很常见的问题。这个参数设少了非正交网格上的压力梯度计算不准残差会反复跳设多了每一步要多解几次压力方程计算时间明显增加。我的调试方法是先看网格的非正交性报告OpenFOAM运行checkMesh会给出最大非正交角度。如果最大非正交角小于60度设1次就够60到75度设2到3次超过75度建议先修网格不要光靠调算法参数硬扛。因为算法修正只能缓解问题不能根治网格质量问题。如果你发现压力方程迭代次数总是设置次数上限且残差还降不到设定值就要考虑是不是非正交修正次数不够。试着逐步加一次看残差曲线是否有明显改善有改善就继续加没改善就维持现状不要盲目加太多。这类问题排查其实挺考验耐心的但每次通过调参和网格优化把残差曲线从震荡拉到平滑下降我都会对算法本身的特性多一些具体认识。PISO和SIMPLEC这两个算法表面上只是几个字母的差别实际用起来却有完全不一样的脾气。根据我个人经验新手最忌讳的是上来就追求高阶格式和大库朗数那等于把算法的所有缺点都暴露出来了。反而是先用一阶格式、小步长、保守松弛因子把流程跑通再逐步释放参数才能稳扎稳打地把问题收敛到底。希望这篇能帮你少走一些我当年走过的弯路。
返回列表