20_SIMPLE
Important
访问 https://aerosand.cn 以获取最近更新。
0. 前言
我们回忆计算流体力学的基本控制方程 https://aerosand.cc/docs/cfd/cfdb/05_general-conservation/
- 质量方程
- 动量方程
- 能量方程
总结有通用形式基本方程
本文主要讨论
- 压力速度耦合方程
- SIMPLE 算法
- SIMPLE 代码框架
1. NS 方程
1.1. 无重力稳态不可压
考虑无重力稳态不可压缩流动的 NS 方程
连续方程(质量方程)
描述了粘性力的动量方程
在 OpenFOAM 的不可压缩求解器中,压力 实际上是动压头,隐含的已经除以了密度,即实际上
其中, 是物理压力,此时的 的单位为
类似的,在 OpenFOAM 不可压缩求解器中,粘性力项也默认除以了密度,用运动粘度 nu 代替了动力粘度 mu ,即
此时,我们知道在 OpenFOAM 中使用的控制方程为
连续方程(质量方程)
动量方程为
对于此控制方程,在求解中面临两个问题:
- 的非线性
- 压力和速度的耦合
我们需要一定的算法来求解此方程组。
1.2. 非线性
回忆之前的对流项,物理量 由质量通量 的影响而产生对流。而这里相当于是自己输运自己(速度“输运”速度)。
现在的对流项,作体积积分后离散
对于其中的非线性部分 ,实践中更倾向于线性处理,也就是令其中一个速度使用上一时间步的值作为已知值。当然,这样会导致计算过程中,非线性项存在一个延迟。不过这对于稳态计算来说并不重要。
对于瞬态计算来说,仍然可以忽略非线性延迟而作一个线性化处理,也可以单独对非线性项作迭代进行处理。但是,单独作迭代会增加计算消耗。
当时间步很小的时候,连续解之间的差别就会很小,此时非线性延迟也就不再显著。
实践中,一般使用 PISO 压力-速度耦合算法来计算瞬态流动计算,使用 SIMPLE 压力-速度耦合算法来计算稳态流动计算。
1.3. 压力速度耦合
动量方程的形式可以简化为
可以想见场的系数矩阵 是一个对角占优的稀疏方阵(或者说我们希望它能够对角占优), 矩阵的对角线都是离散方程中的本元素,同一行上,对角线前后(在该行也许不紧挨)的元素都是和该单元相邻的单元。
最基本的思路是,我们最开始假设一个初始压力场,根据动量方程求出速度场。直接从动量方程求出来的速度场,再去考虑满足质量方程的约束。
那,怎么从动量方程求出速度场呢?
我们先处理系数矩阵 。
从 矩阵中分解出对角矩阵 (不是求解线性代数系统 中的 ),对角矩阵 可以很容易求出逆矩阵。
OpenFOAM 中的对角矩阵以及求解方法已经高度抽象化,也更易读,如下所示
// 对角矩阵的倒数
volScalarField rAU(1.0/UEqn.A());动量方程的左侧抽离对角矩阵,可以写成
相应的非对角矩阵为
OpenFOAM 中也提供可以直接调用的成员方法 UEqn.H() 。
作为比较,注意以下处理是错误的。
分解后的动量方程为
两边同时乘以 的逆矩阵
可以得到【预测速度方程】
上面求出的速度场并不是最终结果,我们称之为预测速度。预测速度场还需要满足连续方程。
预测速度带入连续方程
即有
进一步整理得到【压力修正方程】
OpenFOAM 中对应的代码在 pEqn.H 中
Note
摘取自早期版本 OpenFOAM-2.2,方便理解和阅读。
// OpenFOAM
volScalarField rAU(1.0/UEqn().A());
volVectorField HbyA("HbyA", U);
HbyA = rAU*UEqn().H();
surfaceScalarField phiHbyA("phiHbyA", fvc::interpolate(HbyA) & mesh.Sf());
fvScalarMatrix pEqn
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
);
pEqn.solve();求解压力修正方程后,可以得到新的压力场。
Warning
在代码中,实际参与方程计算的为什么是是 ,而不是 ?
暂且记下,后续会继续讨论。
2. SIMPLE
在 OpenFOAM 中,SIMPLE(Semi-Implicit Method for Pressure Linked Equations)算法用于求解稳态问题。
2.1. 理论
第一步
基于上一步的压力场和速度场(非线性的一部分)(启动步使用初始压力场和初始速度场),进行 momentum predictor
求解方程,可得预测速度。
第二步
求解连续方程,也即求解压力修正方程
先更新 H 矩阵
再求解压力
第三步
以新的压力场,修正速度场
第四步(外循环)
基于新的压力和新的速度作为已知量,回到第一步,再次求解动量方程,再次求得速度场,形成循环迭代。
Tip
这个过程也被称为 outer loop
2.2. 实现
我们对比 OpenFOAM 原生 simpleFoam 求解器,看看 SIMPLE 算法的代码实现应该是什么样子的。
终端输入命令,参看当前版本的 simpleFoam 求解器
sol
code incompressible/simpleFoam避免被复杂代码迷惑,我们参考历史版本的 OpenFOAM 代码,链接如下
代码对应分析如下
第一步
动量预测,即求解动量方程,得到预测速度,也就是 UEqn.H 中的 momentum predictor 部分。
为了方便理解,我们摘抄主要代码如下
| |
Warning
注意湍流粘性力项在左边,而且是正号,为什么不是负号呢? 暂且记下,以后会讨论。
第二步
压力修正,即求解连续方程,得到修正后的压力,也就是 pEqn.H 中的 pressure corrector loop 部分。
第三步
速度修正,即基于修正后的压力修正速度,也就是 pEqn.H 中的 momentum corrector 部分。
为了方便理解,我们摘抄主要代码如下
| |
第四步
循环迭代,即使用修正后的压力和速度,重新回到第一步,再次求得速度场,形成迭代,也就是 simple.loop() 部分。
为了方便理解,我们摘抄主要代码如下
| |
3. 小结
本文介绍了压力速度耦合方程的求解问题,并讨论了 SIMPLE 算法的理论和实现。
通过讨论,我们明白了 SIMPLE 算法的主要思路,不过我们还是有一些问题未解答
- 为什么使用 而不是 ?
- 为什么湍流粘性扩散项在代码中的符号是正号?
这些问题会在以后再次讨论,无需担心。读者也可先行探索思考。
本文完成讨论
- 压力速度耦合方程
- SIMPLE 算法
- SIMPLE 代码框架
支持我们
Tip
希望这里的分享可以对坚持、热爱又勇敢的您有所帮助。
如果这里的分享对您有帮助,您的评论、转发和赞助将对本系列以及后续其他系列的更新、勘误、迭代和完善都有很大的意义,这些行动也会为后来的新同学的学习有很大的助益。
赞助打赏时的信息和留言将用于展示和感谢。
