学习自F. Moukalled, L. Mangani, M. Darwish所著The Finite Volume Method in Computational Fluid Dynamics - An Advanced Introduction with OpenFOAM and Matlab
Chapter 15 Fluid Flow Computation: Incompressible Flows
前面几章讲解的关于变量 ϕ \phi ϕ的一般输运方程的离散和求解流程,均是建立在事先已知速度场的前提下。但是一般情况下,速度场是未知的,且需要通过求解Navier-Stokes方程组来获取。对于不可压缩流动而言,该项工作尤为复杂,因为压力和速度是强烈耦合在一起的,而且压力并不以主变量的形式出现在动量或是连续方程中。本章的重点在于展示解决上述两个问题的方法,以及不可压缩流动问题的流场计算方法。先讲解一维交错网格,然后是一维同位网格,最后是同位三维非结构网格。除了阐明SIMPLE、SIMPLEC、PRIME和PISO算法的来龙去脉,还清晰阐明了Rhie-Chow插值方法,以及将其扩展到瞬态、松弛和体积力项的方法。最后,展现了一些常见边界条件的添加细节。
由于本章内容繁杂,篇幅较长,故分成了四部分来讲解,各部分主要内容分别为:交错网格、同位网格、边界条件、SIMPLE家族算法。
这里是第四部分,主要讲解在SIMPLE算法基础上衍生出的其他SIMPLE家族算法、最佳欠松弛因子、Rhie-Chow插值对不同项的处理、代码讲解。
7 SIMPLE家族算法
在SIMPLE算法中,速度和压力是用分离式(顺序式)方式来处理的,压力场是通过压力修正方程算出的,而压力修正方程的推导则是利用离散的动量方程,将连续方程中的速度场替换成压力项来得到的(即,从离散动量方程推导出速度和压力的关系,然后把该关系代入到连续方程中,得到用压力项而非速度项表示的连续方程,即压力修正方程)。在推导过程中,速度修正项, H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′],是被忽略掉了的,因为如果保留它的话会使得方程难以处理。
抛掉该项并不会影响到最终的解,因为该项在收敛的时候值为零。只是,这么做影响了收敛的过程,因为在最初的迭代过程中该项的值是相当大的。这个很大的值可能会导致发散或是减缓收敛速度,因为高估了压力修正场。为了平衡该作用,在SIMPLE算法中,压力要做欠松弛处理,即 p = p ∗ + λ p p ′ p=p^*+\lambda^p p' p=p∗+λpp′,其中 λ p \lambda^p λp是压力欠松弛因子。为了获得最佳收敛效果, λ p \lambda^p λp通常取成( 1 − λ v 1-\lambda^\bold v 1−λv),其中 λ v \lambda^\bold v λv为动量欠松弛因子,这个后面会详细探讨。
尽管使用了欠松弛处理,SIMPLE算法的收敛速率仍然依据问题的不同而不同,因此学者们寻求各种替代方法来做更好的改进。他们的努力最终发展了一系列SIMPLE类型的家族算法,例如SIMPLEC、SIMPLER、PISO、SIMPLEX、PRIME、SIMPLEM和SIMPLEST。Moukalled和Darwish统一了针对不可压缩和可压缩流动的这些算法的公式,而Darwish等人和Jang等人则评估了它们的性能。这里并不打算给出这些算法的完整描述,而是,聚焦在两种最常用的算法上,它们是Van Doormal和Raithby的SIMPLEC(SIMPLE Consistent)算法,以及Issa的PISO(Pressure-Implicit Split Operator)算法。这两种算法展示了对于 H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′]项的两种不同的处理方法。在SIMPLEC算法中,主网格节点的速度修正近似为 邻近位置处速度修正的加权平均,将 H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′]项转变为修正项, H f ~ [ v ′ ] \widetilde{\bold H_f} [\bold v'] Hf [v′],其幅值更小(比 H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′]更小),可以忽略。在PISO算法中, H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′]项将作为分裂算子方法中的一部分来考虑。在其它算法中,SIMPLE算法中直接忽略掉的 H f ‾ [ v ′ ] \overline{\bold H_f} [\bold v'] Hf[v′]项将进行修改并引入到动量方程或算子 D v \bold D^\bold v Dv中。因为PISO算法等效于一步SIMPLE算法和一步或多步PRIME算法的结合,所以PRIME算法也将进行介绍。
在PRIME算法中,动量方程是显式求解的。对动量方程的该显式处理是合适的,因为其对整体流场的收敛贡献很小。另一方面,找寻压力场的正确解则是影响整场收敛的重要因素。
在SIMPLEST算法中,动量方程的系数分成对流部分和扩散部分,对流部分显式处理,扩散部分隐式处理,这样影响着 D v \bold D^\bold v Dv和 H \bold H H。对流部分显式处理的正当性是基于,在纯对流情况下扰动的传播是以幅值不变的有限速度进行的,与,显式迭代方法的单次迭代中从某个特定点到邻近网格点的误差的传播,是相似的。而扩散部分的隐式处理的证明则源自于,在纯扩散情况下扰动的传播是同时向着各个方向进行的且幅值是快速衰减的,与,隐式求解方法中的单次迭代步内误差是在整个计算域上衰减的,是相似的。
在SIMPLEM(SIMPLE-Modified)算法中,压力修正方程是先于动量方程求解的,表明压力场是使用旧的速度场求解的。这样会比速度修正产生更好的压力修正,相较于SIMPLE算法,两者的优点和缺点是互换的。
在SIMPLER(SIMPLE-Revised)算法中,提出了一个额外的方程,从中可直接解出压力,而类似SIMPLE的压力修正方程则用于更新速度场。采用分离的压力方程的原因是,一旦速度场使用预测压力修正场更新后,其不再满足动量方程。因此,压力需要从另一个满足速度的方程来求解,这样可同时满足动量方程。
SIMPLEX算法的发展目的是确保收敛速度不会随着网格的加密而衰减,其与SIMPLE算法的不同是 D v \bold D^{\bold v} Dv场是要计算的。这是使用额外的方程组来求解的,其发展和求解所基于的假设是,压力差值的空间分布的影响随着网格的加密变化很小。因此,如果压力差值的影响限制在一个单元上,那么做出下面的假设是合适的,通过外插,主网格节点的压力差值足够代表单元面的压力差值。
尽管所有上述算法最初是用于交错网格的,然而他们在同位网格框架下依然适用。
7.1 SIMPLEC算法
SIMPLEC(SIMPLE-Consistent)算法是SIMPLE算法的修改变型,其改动在于,简单地假设在点
C
C
C处的速度修正是邻近网格节点的修正值的加权平均。数学上表示为
v
C
′
≈
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
∑
F
∼
N
B
(
C
)
a
F
v
⇒
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
≈
v
C
′
∑
F
∼
N
B
(
C
)
a
F
v
\bold v'_C\approx\frac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v} \Rightarrow \displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F \approx \bold v'_C \displaystyle\sum_{F\sim NB(C)}a_F^\bold v
vC′≈F∼NB(C)∑aFvF∼NB(C)∑aFvvF′⇒F∼NB(C)∑aFvvF′≈vC′F∼NB(C)∑aFv
使用
H
\bold H
H算子,上式可写为
∑
F
∼
N
B
(
C
)
a
F
v
a
C
v
v
F
′
≈
v
C
′
∑
F
∼
N
B
(
C
)
a
F
v
a
C
v
⇒
H
C
[
v
′
]
≈
v
C
′
H
C
[
1
]
\sum_{F\sim NB(C)}\frac{a_F^\bold v}{a_C^\bold v} \bold v'_F \approx \bold v'_C \sum_{F\sim NB(C)}\frac{a_F^\bold v}{a_C^\bold v} \Rightarrow \bold H_C[\bold v'] \approx \bold v'_C \bold H_C[1]
F∼NB(C)∑aCvaFvvF′≈vC′F∼NB(C)∑aCvaFv⇒HC[v′]≈vC′HC[1]
因此,并非像在SIMPLE中那样忽略掉
H
C
[
v
′
]
‾
\overline{\bold H_C[\bold v']}
HC[v′]项,把它用上式的近似值来代替。这样,速度修正方程
v
C
′
+
H
C
[
v
′
]
=
−
D
C
v
(
∇
p
′
)
C
\bold v_C'+\bold H_C[\bold v'] = -\bold D_C^{\bold v}(\nabla p')_C
vC′+HC[v′]=−DCv(∇p′)C变为了
(
1
+
H
C
[
1
]
)
v
C
′
=
−
D
C
v
(
∇
p
′
)
C
⇒
v
C
′
=
−
D
C
v
~
(
∇
p
′
)
C
(1+\bold H_C[1])\bold v'_C=-\bold D_C^\bold v(\nabla p')_C \Rightarrow \bold v'_C=-\widetilde{\bold D_C^\bold v}(\nabla p')_C
(1+HC[1])vC′=−DCv(∇p′)C⇒vC′=−DCv
(∇p′)C
接下来,可用上式推导出压力修正方程。
通过在动量方程中添加和减去
∑
F
∼
N
B
(
C
)
a
F
v
v
C
\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v_C
F∼NB(C)∑aFvvC项,也可获得同样的结果,即
(
a
C
v
+
∑
F
∼
N
B
(
C
)
a
F
v
)
v
C
+
∑
F
∼
N
B
(
C
)
a
F
v
(
v
F
+
v
C
)
=
−
v
C
(
∇
p
)
C
+
b
^
C
v
\left(a_C^\bold v+\sum_{F\sim NB(C)}a_F^\bold v \right)\bold v_C+ \sum_{F\sim NB(C)}a_F^\bold v(\bold v_F+\bold v_C)= -\bold v_C(\nabla p)_C+\hat{\bold b}_C^\bold v
⎝⎛aCv+F∼NB(C)∑aFv⎠⎞vC+F∼NB(C)∑aFv(vF+vC)=−vC(∇p)C+b^Cv
可以写成
v
C
+
H
C
~
[
v
−
v
C
]
=
−
D
C
v
~
(
∇
p
)
C
+
B
^
C
v
\bold v_C + \widetilde{\bold H_C}[\bold v - \bold v_C]=-\widetilde{\bold D_C^\bold v}(\nabla p)_C+\hat{\bold B}_C^\bold v
vC+HC
[v−vC]=−DCv
(∇p)C+B^Cv
根据上式,速度修正方程变为
v
C
′
=
−
H
C
~
[
v
′
−
v
C
′
]
−
D
C
v
~
(
∇
p
′
)
C
\bold v'_C = -\widetilde{\bold H_C}[\bold v' - \bold v'_C]-\widetilde{\bold D_C^\bold v}(\nabla p')_C
vC′=−HC
[v′−vC′]−DCv
(∇p′)C
忽略掉
H
C
~
[
v
′
−
v
C
′
]
\widetilde{\bold H_C}[\bold v' - \bold v'_C]
HC
[v′−vC′]项,就和前面推导的近似形式一样了,同样用这个修正速度可推导出压力修正方程。
在SIMPLEC算法中,得益于更好的近似估算(即,忽略的项更小),与SIMPLE算法相比,压力的松弛处理不再需要了,所得速度也更加符合动量方程。于是乎,可得到更快的收敛速度。如此看来,忽略掉 H C ~ [ v ′ − v C ′ ] \widetilde{\bold H_C}[\bold v' - \bold v'_C] HC [v′−vC′]项,而非 H C [ v ′ ] \bold H_C[\bold v'] HC[v′]项,并且把 D C v \bold D_C^\bold v DCv替换成 D C v ~ \widetilde{\bold D_C^\bold v} DCv ,SIMPLEC算法中的步骤和SIMPLE中的步骤是相似的。
7.2 PRIME算法
在PRIME(Pressure Implicit Momentum Explicit)算法中,动量方程是显式求解的,该显式处理是恰当的,因为在迭代求解过程中动量方程对于整体流场的收敛贡献较小,而另一方面,压力场的正确解则对整体收敛的贡献至关重要。基于该认知,将PRIME算法汇总如下:
动量方程显式求解,获得新的速度场
v
∗
\bold v^*
v∗
v
C
∗
=
−
H
C
[
v
(
n
)
]
−
D
C
v
(
∇
p
(
n
)
)
C
+
B
C
v
\bold v_C^*=-\bold H_C[\bold v^{(n)}]-\bold D_C^\bold v(\nabla p^{(n)})_C+\bold B_C^\bold v
vC∗=−HC[v(n)]−DCv(∇p(n))C+BCv
该速度场将用于推导压力修正方程。定义修正场如下
v
C
∗
∗
=
v
C
∗
+
v
C
′
p
C
∗
=
p
C
(
n
)
+
p
C
′
\bold v_C^{**}=\bold v_C^* + \bold v_C' \quad\quad p_C^*=p_C^{(n)}+p_C'
vC∗∗=vC∗+vC′pC∗=pC(n)+pC′
修正场应满足
v
C
∗
∗
=
−
H
C
[
v
∗
∗
]
−
D
C
v
(
∇
p
∗
)
C
+
B
C
v
=
−
H
C
[
v
∗
+
v
′
]
−
D
C
v
[
∇
(
p
(
n
)
+
p
′
)
]
C
+
B
C
v
\begin{aligned} \bold v_C^{**} &= -\bold H_C[\bold v^{**}]-\bold D_C^\bold v(\nabla p^{*})_C+\bold B_C^\bold v \\ &= -\bold H_C[\bold v^* + \bold v']-\bold D_C^\bold v[\nabla (p^{(n)}+p')]_C+\bold B_C^\bold v \end{aligned}
vC∗∗=−HC[v∗∗]−DCv(∇p∗)C+BCv=−HC[v∗+v′]−DCv[∇(p(n)+p′)]C+BCv
上式减去上上上式,可得到如下的速度和压力关系
v
C
′
=
−
(
H
C
[
v
∗
−
v
(
n
)
]
+
H
C
[
v
′
]
)
‾
−
D
C
v
∇
p
C
′
\bold v_C'=\underline{-\left(\bold H_C[\bold v^*- \bold v^{(n)}]+ \bold H_C[\bold v']\right)} -\bold D_C^\bold v\nabla p'_C
vC′=−(HC[v∗−v(n)]+HC[v′])−DCv∇pC′
上式再代入到连续方程,得
−
∑
f
∼
n
b
(
C
)
ρ
f
D
f
‾
∇
p
f
′
⋅
S
f
=
−
∑
f
∼
n
b
(
C
)
m
˙
f
∗
+
∑
f
∼
n
b
(
C
)
[
ρ
f
(
H
f
‾
[
v
∗
−
v
(
n
)
]
+
H
f
‾
[
v
′
]
)
⋅
S
f
]
‾
-\sum_{f\sim nb(C)}\rho_f\overline{\bold D_f}\nabla p_f'\cdot\bold S_f= -\sum_{f\sim nb(C)}\dot m_f^*+\underline{\sum_{f\sim nb(C)}\left[ \rho_f\left(\overline{\bold H_f}\left[\bold v^* - \bold v^{(n)}\right]+\overline{\bold H_f}[\bold v']\right)\cdot \bold S_f\right]}
−f∼nb(C)∑ρfDf∇pf′⋅Sf=−f∼nb(C)∑m˙f∗+f∼nb(C)∑[ρf(Hf[v∗−v(n)]+Hf[v′])⋅Sf]
其中的下划线项可以忽略。
如果 H C [ v ′ ] \bold H_C[\bold v'] HC[v′]与 H C [ v ∗ − v ( n ) ] \bold H_C[\bold v^*- \bold v^{(n)}] HC[v∗−v(n)]两项符号相反的话,那么在PRIME算法中忽略的项 H C [ v ∗ − v ( n ) ] + H C [ v ′ ] \bold H_C[\bold v^*- \bold v^{(n)}]+ \bold H_C[\bold v'] HC[v∗−v(n)]+HC[v′]是比SIMPLE算法中忽略的项 H C [ v ′ ] \bold H_C[\bold v'] HC[v′]要来的小的。注意到 H C [ v ′ ] = H C [ v C ∗ ∗ − v C ∗ ] \bold H_C[\bold v']=\bold H_C[\bold v_C^{**}-\bold v_C^{*}] HC[v′]=HC[vC∗∗−vC∗]是为了满足连续方程而带来的修正,而 H C [ v ∗ − v ( n ) ] \bold H_C[\bold v^*- \bold v^{(n)}] HC[v∗−v(n)]是为了满足动量方程而带来的修正,通常加到动量方程中的修正与加到连续方程中的修正是符号相反的,因此,PRIME算法中忽略掉的项 H C [ v ∗ − v ( n ) ] + H C [ v ′ ] \bold H_C[\bold v^*- \bold v^{(n)}]+ \bold H_C[\bold v'] HC[v∗−v(n)]+HC[v′]是较小的。此外,由于动量方程是显示求解的,所以不需要欠松弛处理,这样带来的好处是增加了算法的稳定性。
7.3 PISO算法
在PISO算法中,修正过程由两步或者更多的步骤构成,而
H
C
[
v
′
]
\bold H_C[\bold v']
HC[v′]项则在修正过程的部分步骤中考虑。第一步与SIMPLE算法类似,其中
v
′
\bold v'
v′是用忽略掉
H
C
[
v
′
]
\bold H_C[\bold v']
HC[v′]的方法算出的。满足连续方程的速度
v
∗
∗
\bold v^{**}
v∗∗和压力
p
∗
p^*
p∗场将用于重新计算动量方程的系数,并显式求解该方程。新的速度场
v
∗
∗
∗
\bold v^{***}
v∗∗∗将用于计算单元面处的质量流量场
m
˙
∗
∗
∗
\dot m^{***}
m˙∗∗∗,使用Rhie-Chow插值。然后,
H
C
[
v
′
]
\bold H_C[\bold v']
HC[v′]在第二个修正步中将做部分恢复,其中速度修正写为
v
C
∗
∗
∗
∗
=
v
C
∗
∗
∗
+
v
C
′
′
=
−
H
C
∗
∗
[
v
∗
∗
]
−
(
D
C
v
)
∗
∗
(
∇
p
∗
)
C
+
v
C
′
′
=
−
H
C
∗
∗
[
v
∗
+
v
′
]
−
(
D
C
v
)
∗
∗
(
∇
p
∗
)
C
+
v
C
′
′
=
−
H
C
∗
∗
[
v
∗
]
−
H
C
∗
∗
[
v
′
]
−
(
D
C
v
)
∗
∗
(
∇
p
∗
)
C
+
v
C
′
′
=
−
H
C
∗
∗
[
v
∗
]
−
(
D
C
v
)
∗
∗
(
∇
p
∗
)
C
⏟
≈
v
C
∗
∗
−
H
C
∗
∗
[
−
D
C
v
(
∇
p
′
)
C
]
+
v
C
′
′
≈
v
C
∗
∗
+
v
C
′
′
−
H
C
∗
∗
[
−
D
C
v
(
∇
p
′
)
C
]
‾
\begin{aligned} \bold v_C^{****} &= \bold v_C^{***} + \bold v''_C \\ &= -\bold H_C^{**}[\bold v^{**}]-(\bold D_C^\bold v)^{**}(\nabla p^{*})_C+\bold v''_C \\ &= -\bold H_C^{**}[\bold v^{*}+\bold v']-(\bold D_C^\bold v)^{**}(\nabla p^{*})_C+\bold v''_C \\ &= -\bold H_C^{**}[\bold v^{*}]-\bold H_C^{**}[\bold v'] -(\bold D_C^\bold v)^{**}(\nabla p^{*})_C+\bold v''_C \\ &= \underbrace{-\bold H_C^{**}[\bold v^{*}]-(\bold D_C^\bold v)^{**}(\nabla p^{*})_C}_{\approx\bold v_C^{**}} -\bold H_C^{**}[-\bold D_C^\bold v(\nabla p')_C]+\bold v''_C \\ &\approx \bold v_C^{**}+\underline{\bold v''_C -\bold H_C^{**}[-\bold D_C^\bold v(\nabla p')_C]} \end{aligned}
vC∗∗∗∗=vC∗∗∗+vC′′=−HC∗∗[v∗∗]−(DCv)∗∗(∇p∗)C+vC′′=−HC∗∗[v∗+v′]−(DCv)∗∗(∇p∗)C+vC′′=−HC∗∗[v∗]−HC∗∗[v′]−(DCv)∗∗(∇p∗)C+vC′′=≈vC∗∗
−HC∗∗[v∗]−(DCv)∗∗(∇p∗)C−HC∗∗[−DCv(∇p′)C]+vC′′≈vC∗∗+vC′′−HC∗∗[−DCv(∇p′)C]
上式中的下划线部分代表着
H
C
[
v
′
]
\bold H_C[\bold v']
HC[v′]的部分,其在第二个修正步中有所恢复。第二个速度修正满足
v
C
′
′
=
−
H
C
∗
∗
[
v
′
′
]
‾
−
(
D
C
v
)
∗
∗
(
∇
p
′
′
)
C
\bold v_C''=-\underline{\bold H_C^{**}[\bold v'']}-(\bold D_C^\bold v)^{**}(\nabla p'')_C
vC′′=−HC∗∗[v′′]−(DCv)∗∗(∇p′′)C
使用上上式,以及
C
C
C和
F
F
F节点之间的Rhie-Chow插值,可得到新的压力修正方程
−
∑
f
∼
n
b
(
C
)
ρ
f
D
f
‾
∇
p
f
′
′
⋅
S
f
=
−
∑
f
∼
n
b
(
C
)
m
˙
f
∗
+
∑
f
∼
n
b
(
C
)
(
ρ
f
H
f
‾
[
v
′
′
]
⋅
S
f
)
‾
-\sum_{f\sim nb(C)}\rho_f\overline{\bold D_f}\nabla p''_f\cdot \bold S_f = -\sum_{f\sim nb(C)}\dot m_f^* + \underline{\sum_{f\sim nb(C)}\left(\rho_f\overline{\bold H_f}[\bold v'']\cdot \bold S_f\right)}
−f∼nb(C)∑ρfDf∇pf′′⋅Sf=−f∼nb(C)∑m˙f∗+f∼nb(C)∑(ρfHf[v′′]⋅Sf)
其中下划线项可以忽略,该修正步可以想重复多少次就重复多少次,每次恢复
H
C
[
v
′
]
\bold H_C[\bold v']
HC[v′]新的部分。
通过对该流程的分析,不难发现,PISO可以视为一个SIMPLE步和一个或多个PRIME步的结合,因此结合了SIMPLE算法的隐式特性和PRIME算法的稳定性。同位网格上的PISO算法的流程可汇总如下:
- 为计算时刻 t + Δ t t+\Delta t t+Δt的解,用时刻 t t t的压力、速度和质量流量场 p C t p_C^{t} pCt、 v C t \bold v_C^{t} vCt、 m ˙ f t \dot m_f^{t} m˙ft作为初始猜测值 p C ( n ) p_C^{(n)} pC(n)、 v C ( n ) \bold v_C^{(n)} vC(n)、 m ˙ f ( n ) \dot m_f^{(n)} m˙f(n);
SIMPLE 一步
- 隐式求解动量方程获得新速度场
v
C
∗
\bold v_C^*
vC∗;
v C ∗ + H C [ v ∗ ] = − D C v ( ∇ p ( n ) ) C + B C v \bold v_C^*+\bold H_C[\bold v^*] = -\bold D_C^{\bold v}(\nabla p^{(n)})_C + \bold B_C^{\bold v} vC∗+HC[v∗]=−DCv(∇p(n))C+BCv - 更新单元面处的质量流量,使用Rhie-Chow差值技术获得满足动量方程的质量流量场
m
˙
f
∗
\dot m_f^*
m˙f∗;
m ˙ f ∗ = ρ f v f ∗ ⋅ S f = ρ f v f ∗ ‾ ⋅ S f − ρ f D f v ‾ ( ∇ p f ( n ) − ∇ p f ( n ) ‾ ) ⋅ S f \dot m_f^* = \rho_f \bold v_f^* \cdot \bold S_f = \rho_f \overline{\bold v_f^*} \cdot \bold S_f - \rho_f\overline{\bold D_f^{\bold v}}\left( \nabla p_f^{(n)}-\overline{\nabla p_f^{(n)}} \right) \cdot \bold S_f m˙f∗=ρfvf∗⋅Sf=ρfvf∗⋅Sf−ρfDfv(∇pf(n)−∇pf(n))⋅Sf - 使用新的质量流量
m
˙
f
∗
\dot m_f^*
m˙f∗组装压力修正方程,并求解该方程以获得压力修正场
p
C
′
p_C'
pC′;
a C p ′ p C ′ + ∑ F ∼ N B ( C ) a F p ′ p F ′ = b C p ′ a_C^{p'}p'_C+\sum_{F\sim NB(C)}a_F^{p'}p'_F=b_C^{p'} aCp′pC′+F∼NB(C)∑aFp′pF′=bCp′
其中
a F p ′ = F l u x F f = − ρ f D f a C p ′ = − ∑ f ∼ n b ( c ) F l u x F f = − ∑ F ∼ N B ( C ) a F p ′ b C p ′ = − ∑ f ∼ n b ( C ) F l u x V f + ∑ f ∼ n b ( C ) ( ρ f H f ‾ [ v ′ ] ⋅ S f ) ‾ = − ∑ f ∼ n b ( C ) m ˙ f ∗ + ∑ f ∼ n b ( C ) ( ρ f H f ‾ [ v ′ ] ⋅ S f ) ‾ \begin{aligned} a_F^{p'} &= FluxF_f = -\rho_f \mathcal D_f \\ a_C^{p'} &= -\sum_{f\sim nb(c)}FluxF_f=-\sum_{F\sim NB(C)}a_F^{p'} \\ b_C^{p'} &= -\sum_{f\sim nb(C)} FluxV_f+\underline{\sum_{f\sim nb(C)}\left(\rho_f \overline{\bold H_f}[\bold v'] \cdot \bold S_f\right) } \\ &= -\sum_{f\sim nb(C)} \dot m_f^*+\underline{\sum_{f\sim nb(C)}\left(\rho_f \overline{\bold H_f}[\bold v'] \cdot \bold S_f\right) } \end{aligned} aFp′aCp′bCp′=FluxFf=−ρfDf=−f∼nb(c)∑FluxFf=−F∼NB(C)∑aFp′=−f∼nb(C)∑FluxVf+f∼nb(C)∑(ρfHf[v′]⋅Sf)=−f∼nb(C)∑m˙f∗+f∼nb(C)∑(ρfHf[v′]⋅Sf) - 基于压力修正场,更新单元形心处的压力和速度场,以及单元面处的质量流量场,以获得满足连续方程的场,这些场分别用
p
C
∗
p_C^*
pC∗、
v
C
∗
∗
\bold v_C^{**}
vC∗∗、
m
˙
f
∗
∗
\dot m_f^{**}
m˙f∗∗表示;
v C ∗ ∗ = v C ∗ + v C ′ v C ′ = − D C v ( ∇ p ′ ) C m ˙ f ∗ ∗ = m ˙ f ∗ + m ˙ f ′ m ˙ f ′ = − ρ f D f v ‾ ∇ p f ′ ⋅ S f p C ∗ = p C ( n ) + λ p p C ′ \begin{aligned} \bold v_C^{**} &= \bold v_C^* + \bold v'_C & \bold v'_C &= -\bold D_C^{\bold v}(\nabla p')_C \\ \dot m_f^{**} &= \dot m_f^* + \dot m'_f & \dot m'_f &= -\rho_f \overline{\bold D_f^{\bold v}}\nabla p'_f \cdot \bold S_f \\ p_C^* &= p_C^{(n)}+\lambda^p p'_C \end{aligned} vC∗∗m˙f∗∗pC∗=vC∗+vC′=m˙f∗+m˙f′=pC(n)+λppC′vC′m˙f′=−DCv(∇p′)C=−ρfDfv∇pf′⋅Sf
PRIME一步或多步
- 使用最新可用的速度和压力场,计算动量方程的系数并显式求解该方程;
- 使用Rhie-Chow差值技术,更新单元面处的质量流量;
- 使用新的质量流量,组装压力修正方程,并求解以获得压力修正场;
− ∑ f ∼ n b ( C ) ρ f D f ‾ ∇ p f ′ ′ ⋅ S f = − ∑ f ∼ n b ( C ) m ˙ f ∗ + ∑ f ∼ n b ( C ) ( ρ f H f ‾ [ v ′ ′ ] ⋅ S f ) ‾ -\sum_{f\sim nb(C)}\rho_f\overline{\bold D_f}\nabla p''_f\cdot \bold S_f = -\sum_{f\sim nb(C)}\dot m_f^* + \underline{\sum_{f\sim nb(C)}\left(\rho_f\overline{\bold H_f}[\bold v'']\cdot \bold S_f\right)} −f∼nb(C)∑ρfDf∇pf′′⋅Sf=−f∼nb(C)∑m˙f∗+f∼nb(C)∑(ρfHf[v′′]⋅Sf) - 更新压力、速度、质量流量场;
- 返回第6步,依据想要的修正步数,多次重复该流程;
- 将最新的速度、压力、质量流量值作为初值猜测值;
- 返回第2步,并重复该流程直到收敛;
- 将收敛值设为 t + Δ t t+\Delta t t+Δt时刻的解;
- 推进到下一时刻, t ← t + Δ t t\leftarrow t+\Delta t t←t+Δt;
- 返回第1步并重复该流程直至到达最后时间步。
PISO算法的流程图如下图所示
8 v \bold v v和 p ′ p' p′的最佳欠松弛因子
为推动SIMPLE算法的收敛,动量和连续方程要做欠松弛处理,分别使用欠松弛因子
λ
v
\lambda^\bold v
λv和
λ
p
\lambda^p
λp,那么找寻能获得最佳收敛速度的欠松弛因子值就变得很有必要了,回想一下,不含欠松弛处理的速度修正是这样子的
v
C
′
=
−
D
C
(
∇
p
′
)
C
\bold v'_C=-\bold D_C(\nabla p')_C
vC′=−DC(∇p′)C
此外,在计算压力场时,压力修正要做欠松弛处理,以便让速度修正场满族精确的速度修正方程
v
C
′
=
−
H
C
[
v
′
]
−
λ
p
D
C
(
∇
p
′
)
C
\bold v'_C=-\bold H_C[\bold v']-\lambda^p\bold D_C(\nabla p')_C
vC′=−HC[v′]−λpDC(∇p′)C
结合上式和上上式,可得
λ
p
\lambda^p
λp的表达式
−
D
C
(
∇
p
′
)
C
=
−
H
C
[
v
′
]
−
λ
p
D
C
(
∇
p
′
)
C
⇒
λ
p
=
1
+
H
C
[
v
′
]
v
C
′
=
1
+
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
a
C
v
v
C
′
\begin{aligned} & -\bold D_C(\nabla p')_C=-\bold H_C[\bold v']-\lambda^p\bold D_C(\nabla p')_C \\ \Rightarrow & \lambda^p=1+\frac{\bold H_C[\bold v']}{\bold v'_C}= 1+\frac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{a_C^\bold v \bold v'_C} \end{aligned}
⇒−DC(∇p′)C=−HC[v′]−λpDC(∇p′)Cλp=1+vC′HC[v′]=1+aCvvC′F∼NB(C)∑aFvvF′
SIMPLEC算法无需对压力修正做欠松弛处理,其有着最佳的加速速度。因此,使用SIMPLEC算法中引入的近似,点
C
C
C处的速度修正可以写成邻近网格节点速度修正的加权平均,即
v
C
′
≈
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
∑
F
∼
N
B
(
C
)
a
F
v
\bold v_C'\approx \frac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v }
vC′≈F∼NB(C)∑aFvF∼NB(C)∑aFvvF′
在前面的推导中,系数
a
C
v
a_C^\bold v
aCv可展开为
a
C
v
=
1
λ
v
(
a
C
v
−
∑
F
∼
N
B
(
C
)
a
F
v
+
∑
f
∼
n
b
(
C
)
m
˙
f
)
a_C^\bold v=\frac{1}{\lambda^\bold v}\left( a_C^\bold v- \sum_{F\sim NB(C)}a_F^\bold v + \sum_{f\sim nb(C)}\dot m_f\right)
aCv=λv1⎝⎛aCv−F∼NB(C)∑aFv+f∼nb(C)∑m˙f⎠⎞
其在稳态解的限制下,简化为
a
C
v
=
−
1
λ
v
∑
F
∼
N
B
(
C
)
a
F
v
a_C^\bold v=-\frac{1}{\lambda^\bold v}\sum_{F\sim NB(C)}a_F^\bold v
aCv=−λv1F∼NB(C)∑aFv
上式代入到上上上式,速度修正可近似为
v
C
′
≈
−
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
λ
v
a
C
v
⇒
a
C
v
v
C
′
≈
−
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
λ
v
\bold v_C'\approx -\frac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{\lambda^\bold v a_C^\bold v} \Rightarrow a_C^\bold v\bold v_C'\approx -\frac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{\lambda^\bold v }
vC′≈−λvaCvF∼NB(C)∑aFvvF′⇒aCvvC′≈−λvF∼NB(C)∑aFvvF′
结合前面的式子
λ
p
=
1
+
∑
F
∼
N
B
(
C
)
a
F
v
v
F
′
a
C
v
v
C
′
\lambda^p=1+\dfrac{\displaystyle\sum_{F\sim NB(C)}a_F^\bold v \bold v'_F}{a_C^\bold v \bold v'_C}
λp=1+aCvvC′F∼NB(C)∑aFvvF′,得
λ
p
≈
1
−
λ
v
\lambda^p\approx 1-\lambda^\bold v
λp≈1−λv
经验表明使用满足上式的欠松弛因子的SIMPLE算法的性能,与SIMPLEC算法,是相似的。
9 Rhie-Chow插值对各种项的处理
9.1 欠松弛项的处理
基于Rhie-Chow插值,使用同位网格所得到的解是依赖于动量方程中的欠松弛因子的。为了消除该依赖性,需要对Rhie-Chow插值做修改,欠松弛动量方程为
1
λ
v
a
C
v
v
C
=
−
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
−
V
C
∇
p
C
+
(
1
−
λ
v
λ
v
)
a
C
v
v
C
(
n
)
\frac{1}{\lambda^\bold v}a_C^\bold v \bold v_C = -\sum_{F\sim NB(C)}a_F^\bold v \bold v_F + \bold b_C^\bold v-V_C\nabla p_C+\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)a_C^\bold v\bold v_C^{(n)}
λv1aCvvC=−F∼NB(C)∑aFvvF+bCv−VC∇pC+(λv1−λv)aCvvC(n)
其中
b
C
v
\bold b_C^\bold v
bCv是动量方程中的源项,从中可提取出压力和欠松弛源项,
v
C
(
n
)
\bold v_C^{(n)}
vC(n)是单元形心
C
C
C处速度的前次迭代值。对应的欠松弛动量方程,使用交错网格形式,为
1
λ
v
a
f
v
v
f
=
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
−
V
f
∇
p
f
+
(
1
−
λ
v
λ
v
)
a
f
v
v
f
(
n
)
\frac{1}{\lambda^\bold v}a_f^\bold v \bold v_f = -\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v-V_f\nabla p_f+\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)a_f^\bold v\bold v_f^{(n)}
λv1afvvf=−nb∼NB(C)∑anbvvnb+bfv−Vf∇pf+(λv1−λv)afvvf(n)
通过构建单元面上的伪动量方程,Rhie-Chow插值方法模仿了交错网格方程。正是由于该特性,Rhie-Chow才能成功应用。因此作为指导准则,对Rhie-Chow插值的任何改动的衡量标准应该是,改动方程是否和交错网格方程形式类似。因此,使用Rhie-Chow插值的欠松弛方程的形式应该是
1
λ
v
a
f
v
‾
v
f
=
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
−
V
f
‾
∇
p
f
+
(
1
−
λ
v
λ
v
)
a
f
v
‾
v
f
(
n
)
\frac{1}{\lambda^\bold v}\overline{a_f^\bold v} \bold v_f = -\overline{\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v}-\overline{V_f}\nabla p_f+\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)\overline{a_f^\bold v}\bold v_f^{(n)}
λv1afvvf=−nb∼NB(C)∑anbvvnb+bfv−Vf∇pf+(λv1−λv)afvvf(n)
右端项的第一项平均的获取方法为
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
=
−
g
C
(
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
)
−
g
F
(
∑
N
∼
N
B
(
C
)
a
N
v
v
N
+
b
F
v
)
=
g
C
[
1
λ
v
a
C
v
v
C
+
V
C
∇
p
C
−
(
1
−
λ
v
λ
v
)
a
C
v
v
C
(
n
)
]
+
g
F
[
1
λ
v
a
F
v
v
F
+
V
F
∇
p
F
−
(
1
−
λ
v
λ
v
)
a
F
v
v
F
(
n
)
]
=
1
λ
v
a
f
v
v
f
‾
+
V
f
∇
p
f
‾
−
(
1
−
λ
v
λ
v
)
a
f
v
v
f
(
n
)
‾
\begin{aligned} -\overline{\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v} =& -g_C\left(\sum_{F\sim NB(C)}a_{F}^\bold v \bold v_{F} + \bold b_C^\bold v\right) -g_F\left(\sum_{N\sim NB(C)}a_{N}^\bold v \bold v_{N} + \bold b_F^\bold v\right) \\ =&g_C\left[\frac{1}{\lambda^\bold v}a_C^\bold v \bold v_C +V_C\nabla p_C-\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)a_C^\bold v\bold v_C^{(n)}\right] + \\ &g_F\left[\frac{1}{\lambda^\bold v}a_F^\bold v \bold v_F +V_F\nabla p_F-\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)a_F^\bold v\bold v_F^{(n)}\right] \\ =&\frac{1}{\lambda^\bold v}\overline{a_f^\bold v \bold v_f} +\overline{V_f\nabla p_f}-\left(\frac{1-\lambda^\bold v}{\lambda^\bold v}\right)\overline{a_f^\bold v\bold v_f^{(n)}} \end{aligned}
−nb∼NB(C)∑anbvvnb+bfv===−gC⎝⎛F∼NB(C)∑aFvvF+bCv⎠⎞−gF⎝⎛N∼NB(C)∑aNvvN+bFv⎠⎞gC[λv1aCvvC+VC∇pC−(λv1−λv)aCvvC(n)]+gF[λv1aFvvF+VF∇pF−(λv1−λv)aFvvF(n)]λv1afvvf+Vf∇pf−(λv1−λv)afvvf(n)
上式代入到上上式中,可得单元面速度
v
f
\bold v_f
vf的扩展Rhie-Chow插值
v
f
=
v
f
‾
−
D
f
v
‾
(
∇
p
f
−
∇
p
f
‾
)
+
(
1
−
λ
v
)
(
v
f
(
n
)
−
v
f
(
n
)
‾
)
\bold v_f=\overline{\bold v_f}-\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f})+ (1-\lambda^\bold v)(\bold v_f^{(n)}-\overline{\bold v_f^{(n)}})
vf=vf−Dfv(∇pf−∇pf)+(1−λv)(vf(n)−vf(n))
没有计及欠松弛效应对面速度的影响,所导致的解对欠松弛因子的依赖性。
9.2 瞬态项的处理
当使用后向Euler瞬态格式求解瞬态问题时,离散动量方程为
a
C
v
v
C
=
−
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
−
V
C
∇
p
C
+
a
C
∘
v
C
∘
a_C^\bold v \bold v_C = -\sum_{F\sim NB(C)}a_F^\bold v \bold v_F + \bold b_C^\bold v-V_C\nabla p_C+a_C^\circ\bold v_C^\circ
aCvvC=−F∼NB(C)∑aFvvF+bCv−VC∇pC+aC∘vC∘
其中
b
C
v
\bold b_C^\bold v
bCv是动量方程中的源项,从中可提取出压力和瞬态源项。交错网格变量构架下的等效方程形式如下
a
f
v
v
f
=
−
∑
n
b
∼
N
B
(
f
)
a
n
b
v
v
n
b
+
b
f
v
−
V
f
∇
p
f
+
a
f
∘
v
f
∘
a_f^\bold v \bold v_f = -\sum_{nb\sim NB(f)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v-V_f\nabla p_f+a_f^\circ\bold v_f^\circ
afvvf=−nb∼NB(f)∑anbvvnb+bfv−Vf∇pf+af∘vf∘
使用Rhie-Chow插值方法,伪单元面方程构建为
a
f
v
‾
v
f
=
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
−
V
f
‾
∇
p
f
+
a
f
∘
‾
v
f
∘
\overline{a_f^\bold v} \bold v_f = -\overline{\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v}-\overline{V_f}\nabla p_f+\overline{a_f^\circ}\bold v_f^\circ
afvvf=−nb∼NB(C)∑anbvvnb+bfv−Vf∇pf+af∘vf∘
右端项的第一项平均的获取方法为
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
=
−
g
C
(
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
)
−
g
F
(
∑
N
∼
N
B
(
C
)
a
N
v
v
N
+
b
F
v
)
=
g
C
[
a
C
v
v
C
+
V
C
∇
p
C
−
a
C
∘
v
C
∘
]
+
g
F
[
a
F
v
v
F
+
V
F
∇
p
F
−
a
F
∘
v
F
∘
]
=
a
f
v
v
f
‾
+
V
f
∇
p
f
‾
−
a
f
∘
v
f
∘
‾
\begin{aligned} -\overline{\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v} =& -g_C\left(\sum_{F\sim NB(C)}a_{F}^\bold v \bold v_{F} + \bold b_C^\bold v\right) -g_F\left(\sum_{N\sim NB(C)}a_{N}^\bold v \bold v_{N} + \bold b_F^\bold v\right) \\ =&g_C\left[a_C^\bold v \bold v_C +V_C\nabla p_C-a_C^\circ\bold v_C^\circ\right] + \\ &g_F\left[a_F^\bold v \bold v_F +V_F\nabla p_F-a_F^\circ\bold v_F^\circ\right] \\ =&\overline{a_f^\bold v \bold v_f} +\overline{V_f\nabla p_f}-\overline{a_f^\circ\bold v_f^\circ} \end{aligned}
−nb∼NB(C)∑anbvvnb+bfv===−gC⎝⎛F∼NB(C)∑aFvvF+bCv⎠⎞−gF⎝⎛N∼NB(C)∑aNvvN+bFv⎠⎞gC[aCvvC+VC∇pC−aC∘vC∘]+gF[aFvvF+VF∇pF−aF∘vF∘]afvvf+Vf∇pf−af∘vf∘
可得单元面速度
v
f
\bold v_f
vf的扩展Rhie-Chow插值
v
f
=
v
f
‾
−
D
f
v
‾
(
∇
p
f
−
∇
p
f
‾
)
+
a
f
∘
D
f
∘
‾
V
f
(
v
f
∘
−
v
f
∘
‾
)
\bold v_f=\overline{\bold v_f}-\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f})+ \frac{\overline{a_f^\circ\bold D_f^\circ}}{V_f}(\bold v_f^{\circ}-\overline{\bold v_f^{\circ}})
vf=vf−Dfv(∇pf−∇pf)+Vfaf∘Df∘(vf∘−vf∘)
没有计及非定常项对面速度的影响,所导致的解对时间步的依赖性,以及小时间步的振荡特性。该修正仅对一阶Euler离散格式有效,对于更加精确的时间离散格式,可遵循同样的原则推导类似的修正。
9.3 体积力项的处理
当在交错网格上处理体积力的时候,体积力项的架构和压力梯度项的架构是一样的。在同位网格情况下,体积力、速度、动量变量是在相同位置上计算的。这样,为了让体积力的离散保持和压力同样的架构,需要把体积力做重新分配。离散动量方程为
a
C
v
v
C
=
−
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
−
V
C
∇
p
C
+
V
C
B
C
v
‾
‾
a_C^\bold v \bold v_C = -\sum_{F\sim NB(C)}a_F^\bold v \bold v_F + \bold b_C^\bold v-V_C\nabla p_C+V_C\overline{\overline{\bold B_C^\bold v}}
aCvvC=−F∼NB(C)∑aFvvF+bCv−VC∇pC+VCBCv
其中双上划线表明两个平均步骤,第一个平均步骤是计算在单元面处的
B
C
v
‾
\overline{\bold B_C^\bold v}
BCv
B
f
v
‾
=
g
C
B
C
v
+
(
1
−
g
C
)
B
F
v
\overline{\bold B_f^\bold v}=g_C\bold B_C^\bold v+(1-g_C)\bold B_F^\bold v
Bfv=gCBCv+(1−gC)BFv
如下图所示
第二步是对这些面值进行平均,算得单元形心值,如下图所示
单元形心的平均值的推导,最好是通过考虑如下图所示的一维问题来实现。
对于静止流体,压力梯度应该和体积力平衡,推出
0
=
−
∇
p
f
+
B
f
v
0=-\nabla p_f+\bold B_f^\bold v
0=−∇pf+Bfv
展开上述方程,可得在点
C
C
C和
F
F
F压力间的关系
p
C
=
p
F
+
B
f
δ
y
p_C=p_F+B_f\delta y
pC=pF+Bfδy
或者更加通有的形式
p
C
=
p
F
+
B
f
⋅
d
C
F
p_C=p_F+\bold B_f\cdot \bold d_{CF}
pC=pF+Bf⋅dCF
其中
B
f
B_f
Bf是
B
f
\bold B_f
Bf的幅值,比如重力加速度情况下是
B
f
=
ρ
f
g
B_f=\rho_f g
Bf=ρfg
对于不可压缩流动,体积力中密度随温度的变化是用Boussinesq假设来近似的。
再次对于单元
C
C
C,压力梯度应该等于体积力,即
0
=
−
∇
p
C
+
B
C
v
⇒
∇
p
C
=
B
C
v
0=-\nabla p_C+\bold B_C^\bold v \Rightarrow \nabla p_C=\bold B_C^\bold v
0=−∇pC+BCv⇒∇pC=BCv
然而单元
C
C
C的压力梯度是这样算得的
∇
p
C
=
∑
f
p
f
S
f
V
C
=
∑
f
(
g
C
p
C
+
(
1
−
g
C
)
p
F
)
S
f
V
C
\begin{aligned} \nabla p_C &= \frac{\displaystyle\sum_f p_f \bold S_f}{V_C} \\ &= \frac{\displaystyle\sum_f (g_Cp_C+(1-g_C)p_F) \bold S_f}{V_C} \end{aligned}
∇pC=VCf∑pfSf=VCf∑(gCpC+(1−gC)pF)Sf
把
p
C
=
p
F
+
B
f
⋅
d
C
F
p_C=p_F+\bold B_f\cdot \bold d_{CF}
pC=pF+Bf⋅dCF代入,有
∇
p
C
=
∑
f
(
g
C
(
p
F
+
B
f
v
‾
⋅
d
C
F
)
+
(
1
−
g
C
)
p
F
)
S
f
V
C
=
∑
f
p
F
S
f
V
C
+
∑
f
g
C
(
B
f
v
‾
⋅
d
C
F
)
S
f
V
C
=
p
F
∑
f
S
f
V
C
⏟
=
0
+
∑
f
g
C
(
B
f
v
‾
⋅
d
f
)
S
f
V
C
=
∑
f
g
C
(
B
f
v
‾
⋅
d
f
)
S
f
V
C
=
B
C
v
‾
‾
\begin{aligned} \nabla p_C &= \frac{\displaystyle\sum_f (g_C(p_F+\overline{\bold B_f^\bold v}\cdot \bold d_{CF})+(1-g_C)p_F) \bold S_f}{V_C} \\ &=\frac{\displaystyle\sum_f p_F\bold S_f}{V_C}+ \frac{\displaystyle\sum_f g_C(\overline{\bold B_f^\bold v}\cdot \bold d_{CF})\bold S_f}{V_C} \\ &=p_F\underbrace{\frac{\displaystyle\sum_f \bold S_f}{V_C}}_{=0}+ \frac{\displaystyle\sum_f g_C(\overline{\bold B_f^\bold v}\cdot \bold d_{f})\bold S_f}{V_C} \\ &= \frac{\displaystyle\sum_f g_C(\overline{\bold B_f^\bold v}\cdot \bold d_{f})\bold S_f}{V_C} \\ &= \overline{\overline{\bold B_C^\bold v}} \end{aligned}
∇pC=VCf∑(gC(pF+Bfv⋅dCF)+(1−gC)pF)Sf=VCf∑pFSf+VCf∑gC(Bfv⋅dCF)Sf=pF=0
VCf∑Sf+VCf∑gC(Bfv⋅df)Sf=VCf∑gC(Bfv⋅df)Sf=BCv
这表明
B
C
v
‾
‾
=
∑
f
g
C
(
B
f
v
‾
⋅
d
f
)
S
f
V
C
\overline{\overline{\bold B_C^\bold v}} = \frac{\displaystyle\sum_f g_C(\overline{\bold B_f^\bold v}\cdot \bold d_{f})\bold S_f}{V_C}
BCv=VCf∑gC(Bfv⋅df)Sf
第二个要求是单元面速度与交错网格情况下的方程类似
a
f
v
‾
v
f
=
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
−
V
f
‾
∇
p
f
+
V
f
B
f
v
‾
\overline{a_f^\bold v} \bold v_f = \overline{-\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v}-\overline{V_f}\nabla p_f+\overline{V_f\bold B_f^\bold v}
afvvf=−nb∼NB(C)∑anbvvnb+bfv−Vf∇pf+VfBfv
其中
b
C
v
\bold b_C^\bold v
bCv是动量方程中的源项,从中可提取出压力和体积力项。右端项中的第一项为
−
∑
n
b
∼
N
B
(
C
)
a
n
b
v
v
n
b
+
b
f
v
‾
=
−
g
C
(
∑
F
∼
N
B
(
C
)
a
F
v
v
F
+
b
C
v
)
−
g
F
(
∑
N
∼
N
B
(
C
)
a
N
v
v
N
+
b
F
v
)
=
g
C
[
a
C
v
v
C
+
V
C
∇
p
C
−
V
C
B
C
v
‾
‾
]
+
g
F
[
a
F
v
v
F
+
V
F
∇
p
F
−
V
F
B
F
v
‾
‾
]
=
a
f
v
v
f
‾
+
V
f
∇
p
f
‾
−
V
f
B
f
v
‾
‾
‾
\begin{aligned} -\overline{\sum_{nb\sim NB(C)}a_{nb}^\bold v \bold v_{nb} + \bold b_f^\bold v} =& -g_C\left(\sum_{F\sim NB(C)}a_{F}^\bold v \bold v_{F} + \bold b_C^\bold v\right) -g_F\left(\sum_{N\sim NB(C)}a_{N}^\bold v \bold v_{N} + \bold b_F^\bold v\right) \\ =&g_C\left[a_C^\bold v \bold v_C +V_C\nabla p_C-V_C\overline{\overline{\bold B_C^\bold v}}\right] + \\ &g_F\left[a_F^\bold v \bold v_F +V_F\nabla p_F-V_F\overline{\overline{\bold B_F^\bold v}}\right] \\ =&\overline{a_f^\bold v \bold v_f} +\overline{V_f\nabla p_f}-\overline{V_f\overline{\overline{\bold B_f^\bold v}}} \end{aligned}
−nb∼NB(C)∑anbvvnb+bfv===−gC⎝⎛F∼NB(C)∑aFvvF+bCv⎠⎞−gF⎝⎛N∼NB(C)∑aNvvN+bFv⎠⎞gC[aCvvC+VC∇pC−VCBCv]+gF[aFvvF+VF∇pF−VFBFv]afvvf+Vf∇pf−VfBfv
可得单元面速度
v
f
\bold v_f
vf的扩展Rhie-Chow插值
v
f
=
v
f
‾
−
D
f
v
‾
(
∇
p
f
−
∇
p
f
‾
)
+
D
f
v
‾
(
B
f
v
‾
−
B
f
v
‾
‾
‾
)
\bold v_f=\overline{\bold v_f}-\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f})+ \overline{\bold D_f^\bold v}(\overline{\bold B_f^\bold v}-\overline{\overline{\overline{\bold B_f^\bold v}}})
vf=vf−Dfv(∇pf−∇pf)+Dfv(Bfv−Bfv)
其中
B
f
v
‾
‾
‾
\overline{\overline{\overline{\bold B_f^\bold v}}}
Bfv为
B
f
v
‾
‾
‾
=
g
C
B
C
v
‾
‾
+
(
1
−
g
C
)
B
F
v
‾
‾
\overline{\overline{\overline{\bold B_f^\bold v}}}=g_C\overline{\overline{\bold B_C^\bold v}}+ (1-g_C)\overline{\overline{\bold B_F^\bold v}}
Bfv=gCBCv+(1−gC)BFv
上述对单元面速度的额外处理增加了求解过程整体的健壮性,尤其是对于那些体积力的变化影响较大的情况(比如,自由表面流动问题)。
9.4 欠松弛、瞬态和体积力项的联合处理
一般来说,前面三项应该一并处理,这样就要把Rhie-Chow插值改成同时考虑三种效应的形式。幸运的是,使用叠加原理可以很容易地推出如下的界面速度形式
v
f
=
v
f
‾
−
D
f
v
‾
(
∇
p
f
−
∇
p
f
‾
)
+
D
f
v
‾
(
B
f
v
‾
−
B
f
v
‾
‾
‾
)
+
a
f
∘
D
f
∘
‾
V
f
(
v
f
∘
−
v
f
∘
‾
)
+
(
1
−
λ
v
)
(
v
f
(
n
)
−
v
f
(
n
)
‾
)
\begin{aligned} \bold v_f=&\overline{\bold v_f}-\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f})+ \overline{\bold D_f^\bold v}(\overline{\bold B_f^\bold v}-\overline{\overline{\overline{\bold B_f^\bold v}}})\\ &+\frac{\overline{a_f^\circ\bold D_f^\circ}}{V_f}(\bold v_f^{\circ}-\overline{\bold v_f^{\circ}})+ (1-\lambda^\bold v)(\bold v_f^{(n)}-\overline{\bold v_f^{(n)}}) \end{aligned}
vf=vf−Dfv(∇pf−∇pf)+Dfv(Bfv−Bfv)+Vfaf∘Df∘(vf∘−vf∘)+(1−λv)(vf(n)−vf(n))
其中在计算
D
f
v
‾
\overline{\bold D_f^\bold v}
Dfv时,使用的是系数
a
C
v
a_C^\bold v
aCv的欠松弛值。
10 代码讲解
10.1 uFVM
在uFVM中,压力修正方程的实现是在cfdAssembleMdotTerm中进行的,下面给出了算法的核心,其中压力修正方程的系数是通过线性化每个内部面通量来组装的,此外,mdot场(面上的质量流量)是基于下式计算的
v
f
=
v
f
‾
−
D
f
v
‾
(
∇
p
f
−
∇
p
f
‾
)
+
D
f
v
‾
(
B
f
v
‾
−
B
f
v
‾
‾
‾
)
+
a
f
∘
D
f
∘
‾
V
f
(
v
f
∘
−
v
f
∘
‾
)
+
(
1
−
λ
v
)
(
v
f
(
n
)
−
v
f
(
n
)
‾
)
\begin{aligned} \bold v_f=&\overline{\bold v_f}-\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f})+ \overline{\bold D_f^\bold v}(\overline{\bold B_f^\bold v}-\overline{\overline{\overline{\bold B_f^\bold v}}})\\ &+\frac{\overline{a_f^\circ\bold D_f^\circ}}{V_f}(\bold v_f^{\circ}-\overline{\bold v_f^{\circ}})+ (1-\lambda^\bold v)(\bold v_f^{(n)}-\overline{\bold v_f^{(n)}}) \end{aligned}
vf=vf−Dfv(∇pf−∇pf)+Dfv(Bfv−Bfv)+Vfaf∘Df∘(vf∘−vf∘)+(1−λv)(vf(n)−vf(n))
共分成了9项(即,
I
\text I
I到
IX
\text{IX}
IX),并一步步组装来计算面速度,它们分别是
第 I \text{I} I项:插值速度场 v f ‾ \overline{\bold v_f} vf;
第 II \text{II} II项和第 III \text{III} III项:面和平均压力场 − D f v ‾ ( ∇ p f − ∇ p f ‾ ) -\overline{\bold D_f^\bold v}(\nabla p_f-\overline{\nabla p_f}) −Dfv(∇pf−∇pf);
第 IV \text{IV} IV项和第 V \text{V} V项:平均和重新分配体积力 D f v ‾ ( B f v ‾ − B f v ‾ ‾ ‾ ) \overline{\bold D_f^\bold v}(\overline{\bold B_f^\bold v}-\overline{\overline{\overline{\bold B_f^\bold v}}}) Dfv(Bfv−Bfv);
第 VI \text{VI} VI项和第 VII \text{VII} VII项:瞬态通量 a f ∘ D f ∘ ‾ V f ( v f ∘ − v f ∘ ‾ ) \dfrac{\overline{a_f^\circ\bold D_f^\circ}}{V_f}(\bold v_f^{\circ}-\overline{\bold v_f^{\circ}}) Vfaf∘Df∘(vf∘−vf∘);
第 VIII \text{VIII} VIII项和第 IX \text{IX} IX项:松弛修正项 ( 1 − λ v ) ( v f ( n ) − v f ( n ) ‾ ) (1-\lambda^\bold v)(\bold v_f^{(n)}-\overline{\bold v_f^{(n)}}) (1−λv)(vf(n)−vf(n))。
%
% assemble term I
% density_f [v]_f.Sf
%
U_bar_f = (dot(vel_bar_f(:,:)',Sf(:,:)'))';
local_FLUXVf = local_FLUXVf + density_f.*U_bar_f;
%
% Assemble term II and linearize it
% - density_f ([DPVOL]_f.P_grad_f).Sf
%
DUSf = [DU1_f.*Sf(:,1),DU2_f.*Sf(:,2),DU3_f.*Sf(:,3)];
geoDiff =( dot(Sf(:,:)',DUSf') ./ dot(CN(:,:)',Sf(:,:)'))';
local_FLUXCf1 = local_FLUXCf1 + density_f.*geoDiff;
local_FLUXCf2 = local_FLUXCf2 - density_f.*geoDiff;
local_FLUXVf = local_FLUXVf - density_f.*dot(p_grad_f',T')';
%
% assemble term III
% density_f ([P_grad]_f.([DPVOL]_f.Sf))
%
local_FLUXVf = local_FLUXVf +
density_f.*dot(p_grad_bar_f(iFaces,:)',DUSf(iFaces,:)')';
%
% assemble terms IV and V
% density_f [DBVOL]_f.([B]_f -[[B]]_f).S_f
%
local_FLUXVf = local_FLUXVf +
density_f[iFace]*FVVectorDotProduct(FVTensorVectorDotProduct(DB_f,FVVe
ctorSubstract(FVMakeVector(bf1_bar_f[iFace],bf2_bar_f[iFace]),FVMakeVe
ctor(bf1_redistributed_f[iFace],bf2_redistributed_f[iFace]))),S_f) ;
%
% assemble terms VI and VII
% [Dt]_f (U_Old_f -[v_old]_f.S_f)
%
U_bar_old_f = [velx_old_bar_f[iFace] vely_old_bar_f[iFace])] * S_f';
local_FLUXVf = local_FLUXVf + DT_f*(mdot_old_f[iFace] -
density_old_f[iFace]*U_bar_old_f);
%
% assemble terms VIII and IX
% (1-URF)(U_f -[v]_f.S_f)
%
local_FLUXVf = local_FLUXVf + (1.0-Mdot_URF)*(mdot_previous_f -
density_f.*U_bar_f);
%
% assemble the flow term dot for the face
%
local_mdot_f = local_FLUXCf_1*(pressure[iElement1]+ Pref) +
local_FLUXCf_2*(pressure[iElement2]+ Pref) + local_FLUXVf;
%
%
% Assemble in Global Fluxes
%
theFluxes.FLUXC1f(iFaces,1) = local_FLUXCf1;
theFluxes.FLUXC2f(iFaces,1) = local_FLUXCf2;
theFluxes.FLUXVf(iFaces,1) = local_FLUXVf;
%
theFluxes.FLUXTf(iFaces,1) = theFluxes.FLUXC1f.*pressureC(iFaces)
+ theFluxes.FLUXC2f.*pressureN(iFaces) + theFluxes.FLUXVf(iFaces);
%
mdot_f = theFluxes.FLUXTf(iFaces);
10.2 OpenFOAM
To be continued…