有限体积法求解二维方腔流(一)——动量方程和连续性方程的离散

1. 有限体积法求解二维方腔流–理论手册

1.1. 不可压缩流体控制方程

连续性方程
∇ ⋅ U = 0 (1) \nabla \cdot U=0 \tag{1} U=0(1)
动量方程
∂ U ∂ t + ∇ ⋅ ( U U ) = − ∇ p + ∇ ⋅ ( ν ∇ U ) (2) \frac{\partial U}{\partial t}+\nabla\cdot (UU)=-\nabla p + \nabla \cdot (\nu \nabla U) \tag{2} tU+(UU)=p+(νU)(2)
其中 p p p为真实压力与流体密度之比,量纲为 m 2 / s 2 m^2/s^2 m2/s2

上式中的扩散项为空间的二阶导数项,为了保证精度,对上式离散的空间精度也应至少满足二阶精度(Jasak, 1996, phd)

有限体积法对上式离散的第一步是积分:
∫ t t + Δ t [ ∂ ∂ t ∫ V P U d V + ∫ V P ∇ ⋅ ( U U ) d V ] d t = ∫ t t + Δ t [ − ∫ V P ∇ p d V + ∫ V P ∇ ⋅ ( ν ∇ U ) d V ] d t \int_t^{t+\Delta t}\left[ \frac{\partial }{\partial t}\int_{V_P} U dV + \int_{V_P}\nabla\cdot (UU) dV\right]dt=\int_t^{t+\Delta t}\left[ -\int_{V_P}\nabla p dV + \int_{V_P}\nabla \cdot (\nu \nabla U) dV \right]dt tt+Δt[tVPUdV+VP(UU)dV]dt=tt+Δt[VPpdV+VP(νU)dV]dt

1.2. 逐项离散

使用网格质心值代替网格平均值,有二阶精度,详情参考
∫ V p U d V = U P V P + ε ( Δ x 2 ) \int_{V_p} U dV = U_P V_P + \varepsilon(\Delta x^2) VpUdV=UPVP+ε(Δx2)

1.2.1. 非稳态项

∫ t t + Δ t ∂ ∂ t ∫ V P U d V d t ≈ U P t + Δ t − U P t Δ t Δ t V P = ( U P n + 1 − U P n ) V P \int_t^{t+\Delta t} \frac{\partial }{\partial t}\int_{V_P} U dVdt\approx \frac{U^{t+\Delta t}_P-U^t_P}{\Delta t} \Delta t V_P = (U_P^{n+1}-U_P^n) V_P tt+ΔttVPUdVdtΔtUPt+ΔtUPtΔtVP=(UPn+1UPn)VP

下文中以上标 ( n + 1 ) (n+1) (n+1)替代上标 ( t + Δ t ) (t+\Delta t) (t+Δt),以 n n n替代 t t t

1.2.2. 对流项

结合高斯散度定理,
∫ V P ∇ ⋅ ( U U ) d V = ∫ ∂ V P ( U U ) d S ≈ ∑ ( U U ) f S \int_{V_P}\nabla\cdot (UU) dV=\int_{\partial V_P} (UU) dS\approx\sum(UU)_f S VP(UU)dV=VP(UU)dS(UU)fS

注意上式中 ( U U ) f (UU)_f (UU)f为张量在面心上的平均值,二阶精度; S S S为矢量,将其乘积做线性化处理
∑ ( U U ) f S ≈ ∑ F f n U f n + 1 \sum(UU)_f S \approx \sum F^n_f U^{n+1}_f (UU)fSFfnUfn+1

其中 F f = S ⋅ U f F_f=S \cdot U_f Ff=SUf,为标量。本文中的面法向方向由内指向外,这与OpenFOAM中根据ownerneighbor来定义面法向的方式不同。对于二维情况, U = ( u , v ) U=(u,v) U=(u,v)
∑ F f n U f n + 1 = F w U w n + 1 + F e U e n + 1 + F s U s n + 1 + F n U n n + 1 \sum F_f^n U_f^{n+1}=F_wU_w^{n+1}+ F_eU_e^{n+1}+ F_sU_s^{n+1}+ F_nU_n^{n+1} FfnUfn+1=FwUwn+1+FeUen+1+FsUsn+1+FnUnn+1

F w = U w ⋅ S w = ( u w , v w ) ⋅ ( − h , 0 ) = − u w h = − u P + u W 2 h F_w=U_w\cdot S_w=(u_w,v_w)\cdot (-h,0)=-u_wh=-\frac{u_P+u_W}{2}h Fw=UwSw=(uw,vw)(h,0)=uwh=2uP+uWh

F e = U e ⋅ S e = ( u e , v e ) ⋅ ( h , 0 ) = u e h = u P + u E 2 h F_e=U_e\cdot S_e=(u_e,v_e)\cdot (h,0)=u_eh=\frac{u_P+u_E}{2}h Fe=UeSe=(ue,ve)(h,0)=ueh=2uP+uEh

F s = U s ⋅ S s = ( u s , v s ) ⋅ ( 0 , − h ) = − v s h = − v P + v S 2 h F_s=U_s\cdot S_s=(u_s,v_s)\cdot (0,-h)=-v_sh=-\frac{v_P+v_S}{2}h Fs=UsSs=(us,vs)(0,h)=vsh=2vP+vSh

F n = U n ⋅ S n = ( u n , v n ) ⋅ ( 0 , h ) = v n h = v P + v N 2 h F_n=U_n\cdot S_n=(u_n,v_n)\cdot (0,h)=v_nh=\frac{v_P+v_N}{2}h Fn=UnSn=(un,vn)(0,h)=vnh=2vP+vNh

上式中 U f n + 1 U_f^{n+1} Ufn+1的获取是有限体积法中的关键。介绍几种常用格式:

  • 一阶迎风
    ϕ e = { ϕ P F e > 0 ϕ E F e < 0 \phi_e=\left\{ \begin{matrix} \phi_P & F_e>0 \\ \phi_E & F_e<0 \end{matrix} \right. ϕe={ϕPϕEFe>0Fe<0

  • 二阶迎风
    ϕ e = { 0.5 ( 3 ϕ P − ϕ W ) F e > 0 0.5 ( 3 ϕ E − ϕ E E ) F e < 0 \phi_e=\left\{ \begin{matrix} 0.5(3\phi_P-\phi_W) & F_e>0 \\ 0.5(3\phi_E-\phi_{EE}) & F_e<0 \end{matrix} \right. ϕe={0.5(3ϕPϕW)0.5(3ϕEϕEE)Fe>0Fe<0

  • 中心差分
    ϕ e = ϕ P + ϕ E 2 \phi_e=\frac{\phi_P+\phi_E}{2} ϕe=2ϕP+ϕE

上式中 ϕ \phi ϕ为标量,下标 W , E W,E W,E分别为 P P P网格的左和右邻居网格, e e e表示 P P P网格的右面。如果不是六面体网格(三维)或矩形网格(二维),则上述格式需要修正。

OpenFOAM自带cavity算例中,system/fvSchemes-divSchemes-div(phi,U)使用的离散格式是Gauss linear,其中phi是已知值,所以线性插值仅是应用于变量U,换句话说,cavity默认的对流项离散方式是中心差分

按照中心差分, U f = ( U N + U P ) / 2 U_f=(U_N+U_P)/2 Uf=(UN+UP)/2
U w n + 1 = U P n + 1 + U W n + 1 2 U_w^{n+1}=\frac{U_P^{n+1}+U_W^{n+1}}{2} Uwn+1=2UPn+1+UWn+1

U e n + 1 = U P n + 1 + U E n + 1 2 U_e^{n+1}=\frac{U_P^{n+1}+U_E^{n+1}}{2} Uen+1=2UPn+1+UEn+1

U s n + 1 = U P n + 1 + U S n + 1 2 U_s^{n+1}=\frac{U_P^{n+1}+U_S^{n+1}}{2} Usn+1=2UPn+1+USn+1

U n n + 1 = U P n + 1 + U N n + 1 2 U_n^{n+1}=\frac{U_P^{n+1}+U_N^{n+1}}{2} Unn+1=2UPn+1+UNn+1

∑ F f n U f n + 1 = ( − u w n h ) U w n + 1 + ( u e n h ) U e n + 1 + ( − v s n h ) U s n + 1 + ( v n n h ) U n n + 1 = h 4 [ − ( u P n + u W n ) ( U P n + 1 + U W n + 1 ) + ( u P n + u E n ) ( U P n + 1 + U E n + 1 ) − ( v P n + v S n ) ( U P n + 1 + U S n + 1 ) + ( v P n + v N n ) ( U P n + 1 + U N n + 1 ) ] = h 4 [ ( u E n − u W n + v N n − v S n ) U P n + 1 − ( u P n + u W n ) U W n + 1 + ( u P n + u E n ) U E n + 1 − ( v P n + v S n ) U S n + 1 + ( v P n + v N n ) U N n + 1 ] \sum F^n_fU^{n+1}_f = (-u_w^n h)U_w^{n+1} + (u_e^n h)U_e^{n+1} + (-v_s^n h)U_s^{n+1} + (v_n^n h)U_n^{n+1} \\ =\frac{h}{4}\left[ -(u_P^n+u_W^n)(U^{n+1}_P+U^{n+1}_W)+(u_P^n+u_E^n)(U^{n+1}_P+U^{n+1}_E)-(v_P^n+v_S^n)(U^{n+1}_P+U^{n+1}_S)+(v_P^n+v_N^n)(U^{n+1}_P+U^{n+1}_N)\right] \\ =\frac{h}{4}\left[ (u_E^n-u_W^n+v_N^n-v_S^n)U^{n+1}_P -(u_P^n+u_W^n)U^{n+1}_W+(u_P^n+u_E^n)U^{n+1}_E-(v_P^n+v_S^n)U^{n+1}_S+(v_P^n+v_N^n)U^{n+1}_N \right] FfnUfn+1=(uwnh)Uwn+1+(uenh)Uen+1+(vsnh)Usn+1+(vnnh)Unn+1=4h[(uPn+uWn)(UPn+1+UWn+1)+(uPn+uEn)(UPn+1+UEn+1)(vPn+vSn)(UPn+1+USn+1)+(vPn+vNn)(UPn+1+UNn+1)]=4h[(uEnuWn+vNnvSn)UPn+1(uPn+uWn)UWn+1+(uPn+uEn)UEn+1(vPn+vSn)USn+1+(vPn+vNn)UNn+1]

按照一阶迎风,
U w n + 1 = { U W n + 1 F w > 0 U P n + 1 F w ≤ 0 U_w^{n+1}=\left\{ \begin{matrix} U_W^{n+1} & F_w>0 \\ U_P^{n+1} & F_w\leq0 \end{matrix} \right. Uwn+1={UWn+1UPn+1Fw>0Fw0

U e n + 1 = { U P n + 1 F e > 0 U E n + 1 F e ≤ 0 U_e^{n+1}=\left\{ \begin{matrix} U_P^{n+1} & F_e>0 \\ U_E^{n+1} & F_e\leq0 \end{matrix} \right. Uen+1={UPn+1UEn+1Fe>0Fe0

U s n + 1 = { U S n + 1 F s > 0 U P n + 1 F s ≤ 0 U_s^{n+1}=\left\{ \begin{matrix} U_S^{n+1} & F_s>0 \\ U_P^{n+1} & F_s\leq0 \end{matrix} \right. Usn+1={USn+1UPn+1Fs>0Fs0

U n n + 1 = { U P n + 1 F n > 0 U N n + 1 F n ≤ 0 U_n^{n+1}=\left\{ \begin{matrix} U_P^{n+1} & F_n>0 \\ U_N^{n+1} & F_n\leq0 \end{matrix} \right. Unn+1={UPn+1UNn+1Fn>0Fn0

1.2.3. 扩散项

∫ V P ∇ ⋅ ( ν ∇ U ) d V = ∫ ∂ V P ( ν ∇ U ) d S ≈ ∑ ν ( ∇ U ) f S \int_{V_P}\nabla \cdot (\nu \nabla U) dV = \int_{\partial V_P} (\nu \nabla U) dS \approx \sum \nu (\nabla U)_f S VP(νU)dV=VP(νU)dSν(U)fS
上式中面上梯度项 ( ∇ U ) (\nabla U) (U)的方向从 P P P指向 N N N,即该矢量的方向和网格 P P P与网格 N N N体心连线共线,如果体心连线和面法向矢量不垂直,则需要引入非正交修正,关于这部分的讨论可参考Jasak(1996, phd)。另外,这篇文章提到了两种面上梯度的计算方法,其区别在无痛苦NS方程笔记laplacian(ϕ) = div(grad(ϕ))?这一小节提到。

注意到,面上速度梯度(二阶矢量)与面矢量的乘积仍为矢量,下式为icoFoam解析中对该项的分析
( ∇ U n + 1 ) f S = ( ( ∇ U n + 1 ) f ⋅ S S f ) S f = U N n + 1 − U P n + 1 d S f (\nabla U^{n+1})_f S=\left( (\nabla U^{n+1})_f \cdot \frac{S}{S_f} \right)S_f=\frac{U^{n+1}_N-U^{n+1}_P}{d}S_f (Un+1)fS=((Un+1)fSfS)Sf=dUNn+1UPn+1Sf

S f S_f Sf为面积, d d d为网格体心间距,均为标量。将上式写成向量乘积的形式为
( ∇ U ) f ⋅ S S f = ( i , j ) ( ∂ u / ∂ x ∂ v / ∂ x ∂ u / ∂ y ∂ v / ∂ y ) = ( i ∂ u / ∂ x + j ∂ u / ∂ y ,   i ∂ v / ∂ x + j ∂ v / ∂ y ) (\nabla U)_f \cdot \frac{S}{S_f} = \left( i,j \right) \left( \begin{matrix} {\partial u}/{\partial x} & {\partial v}/{\partial x} \\ {\partial u}/{\partial y} & {\partial v}/{\partial y} \end{matrix} \right) = \left( i\partial u/\partial x+j\partial u/\partial y,\ i\partial v/\partial x+j\partial v/\partial y \right) (U)fSfS=(i,j)(u/xu/yv/xv/y)=(iu/x+ju/y, iv/x+jv/y)

上式相当于OpenFOAM中的snGrad(U),其中 ( i , j ) (i,j) (i,j)为面的单位矢量,相当于 S / S f S/S_f S/Sf。对于 e e e面,单位矢量为 ( 1 , 0 ) (1,0) (1,0),代入上式为
( ∇ U ) e ⋅ S e S f = ( ∂ u / ∂ x ,   ∂ v / ∂ x ) = 1 d ( u E − u P ,   v E − v P ) = 1 d ( U E − U P ) (\nabla U)_e \cdot \frac{S_e}{S_f} =\left( \partial u/\partial x,\ \partial v/\partial x \right)=\frac{1}{d} \left( u_E-u_P,\ v_E-v_P \right) = \frac{1}{d} \left( U_E-U_P \right) (U)eSfSe=(u/x, v/x)=d1(uEuP, vEvP)=d1(UEUP)

对于 w w w面,单位矢量为 ( − 1 , 0 ) (-1,0) (1,0),则
( ∇ U ) w ⋅ S w S f = ( − ∂ u / ∂ x ,   − ∂ v / ∂ x ) = 1 d ( u W − u P ,   v W − v P ) = 1 d ( U W − U P ) (\nabla U)_w \cdot \frac{S_w}{S_f} =\left( -\partial u/\partial x,\ -\partial v/\partial x \right)=\frac{1}{d} \left( u_W-u_P,\ v_W-v_P \right) = \frac{1}{d} \left( U_W-U_P \right) (U)wSfSw=(u/x, v/x)=d1(uWuP, vWvP)=d1(UWUP)

此过程证明了面法向梯度(上式最左端)与体心速度之间的关系。推导过程中
∂ u ∂ x ∣ e = u E − u P x E − x P \frac{\partial u}{\partial x}\bigg|_e=\frac{u_E-u_P}{x_E-x_P} xue=xExPuEuP

为什么二阶矢量与面矢量做乘法的时候,面矢量在左?这是因为本文定义的矢量是行矢量,或者说是1行2列的矩阵。二阶矢量与面矢量乘积为矢量,按照矩阵乘法,2*2的矩阵和1*2矩阵相乘,只能是1*2的矩阵在左,所得结果为1*2的矩阵。

按上述推导过程,扩散项的离散结果为
∑ ν ( ∇ U n + 1 ) f S = ν [ ( ∇ U n + 1 ) w S w + ( ∇ U n + 1 ) e S e + ( ∇ U n + 1 ) s S s + ( ∇ U n + 1 ) n S n ] = ν S f d [ ( U W − U P ) + ( U E − U P ) + ( U S − U P ) + ( U N − U P ) ] = ν S f d [ U W + U E + U S + U N − 4 U P ] \sum \nu(\nabla U^{n+1})_f S=\nu \left[ (\nabla U^{n+1})_w S_w + (\nabla U^{n+1})_e S_e + (\nabla U^{n+1})_s S_s + (\nabla U^{n+1})_n S_n \right] \\ = \frac{\nu S_f}{d}\left[ (U_W-U_P) + (U_E-U_P) + (U_S-U_P) + (U_N-U_P) \right] = \frac{\nu S_f}{d}\left[ U_W + U_E + U_S + U_N-4U_P \right] ν(Un+1)fS=ν[(Un+1)wSw+(Un+1)eSe+(Un+1)sSs+(Un+1)nSn]=dνSf[(UWUP)+(UEUP)+(USUP)+(UNUP)]=dνSf[UW+UE+US+UN4UP]

1.2.4. 压力项

∫ V P ∇ p d V = ∫ ∂ V P p d S ≈ ∑ p f S \int_{V_P}\nabla p dV = \int_{\partial V_P} p dS \approx \sum p_f S VPpdV=VPpdSpfS

按照中心差分, p f = ( p P + p N ) / 2 p_f=(p_P+p_N)/2 pf=(pP+pN)/2
∑ p f S = p W + p P 2 ( − h , 0 ) + p E + p P 2 ( h , 0 ) + p S + p P 2 ( 0 , − h ) + p N + p P 2 ( 0 , h ) = h 2 ( p E − p W ,   p N − p S ) \sum p_fS=\frac{p_W+p_P}{2}\left( -h,0 \right)+\frac{p_E+p_P}{2}\left( h,0 \right)+\frac{p_S+p_P}{2}\left( 0,-h \right)+\frac{p_N+p_P}{2}\left( 0,h \right) =\frac{h}{2}\left( p_E-p_W,\ p_N-p_S \right) pfS=2pW+pP(h,0)+2pE+pP(h,0)+2pS+pP(0,h)+2pN+pP(0,h)=2h(pEpW, pNpS)

1.3. 动量方程离散结果

对以上各项的离散结果汇总如下,
U P n + 1 − U P n Δ t V P + ∑ F f n U f n + 1 = ∑ ν ( ∇ U n + 1 ) f S − ∑ p f n S (3) \frac{U^{n+1}_P-U^n_P}{\Delta t}V_P + \sum F^n_f U^{n+1}_f = \sum \nu (\nabla U^{n+1})_f S - \sum p^n_f S \tag{3} ΔtUPn+1UPnVP+FfnUfn+1=ν(Un+1)fSpfnS(3)

假设网格均一,对流项采用中心差分,压力项采用中心差分,将以上对流项、压力项、扩散项替换到离散方程中可得
A P n U P n + 1 = ∑ A N n U N n + 1 + S P n − ∑ p P n + p N n 2 S (4) A_P^n U_P^{n+1}=\sum A_N^n U_N^{n+1} + S_P^n -\sum \frac{p_P^n+p_N^n}{2} S \tag{4} APnUPn+1=ANnUNn+1+SPn2pPn+pNnS(4)

其中各个系数项为
A P n = V P Δ t + ∑ F f n 2 + ∑ ν S f d A_P^n=\frac{V_P}{\Delta t}+\sum\frac{F_f^n}{2}+\sum \nu \frac{S_f}{d} APn=ΔtVP+2Ffn+νdSf

A N n = ν S f d − F f n 2 A_N^n= \nu \frac{S_f}{d} - \frac{F_f^n}{2} ANn=νdSf2Ffn

S P n = V P Δ t U P n S_P^n=\frac{V_P}{\Delta t}U_P^n SPn=ΔtVPUPn

可以看出,以上系数均为 t t t时刻的值即已知值。进一步展开可得
A P n U P n + 1 = A W n U W n + 1 + A E n U E n + 1 + A S n U S n + 1 + A N n U N n + 1 + S P n − ∑ p f n S A_P^n U_P^{n+1}=A_W^n U_W^{n+1}+A_E^n U_E^{n+1}+A_S^n U_S^{n+1}+A_N^n U_N^{n+1}+S_P^n-\sum p_f^n S APnUPn+1=AWnUWn+1+AEnUEn+1+ASnUSn+1+ANnUNn+1+SPnpfnS

A P n = V P Δ t + h 4 ( u E n − u W n + v N n − v S n ) + 4 ν S f d A_P^n =\frac{V_P}{\Delta t}+\frac{h}{4}(u_E^n -u_W^n +v_N^n -v_S^n )+\frac{4\nu S_f}{d} APn=ΔtVP+4h(uEnuWn+vNnvSn)+d4νSf

A W n = h 4 ( u P n + u W n ) + ν S f d A_W^n =\frac{h}{4}(u_P^n +u_W^n )+\frac{\nu S_f}{d} AWn=4h(uPn+uWn)+dνSf

A E n = − h 4 ( u P n + u E n ) + ν S f d A_E^n =-\frac{h}{4}(u_P^n +u_E^n )+\frac{\nu S_f}{d} AEn=4h(uPn+uEn)+dνSf

A S n = h 4 ( v P n + v S n ) + ν S f d A_S^n =\frac{h}{4}(v_P^n +v_S^n )+\frac{\nu S_f}{d} ASn=4h(vPn+vSn)+dνSf

A N n = − h 4 ( v P n + v N n ) + ν S f d A_N^n =-\frac{h}{4}(v_P^n +v_N^n )+\frac{\nu S_f}{d} ANn=4h(vPn+vNn)+dνSf

S P n = V P Δ t U P n S_P^n=\frac{V_P}{\Delta t}U^{n}_P SPn=ΔtVPUPn

1.3.1. u方程

A P u P n + 1 = A W u W n + 1 + A E u E n + 1 + A S u S n + 1 + A N u N n + 1 + V P Δ t u P n + h 2 ( p W n − p E n ) A_P u_P^{n+1} = A_W u_W^{n+1}+ A_E u_E^{n+1}+ A_S u_S^{n+1}+ A_N u_N^{n+1} + \frac{V_P}{\Delta t}u_P^n +\frac{h}{2}(p_W^n-p_E^n) APuPn+1=AWuWn+1+AEuEn+1+ASuSn+1+ANuNn+1+ΔtVPuPn+2h(pWnpEn)

1.3.2. v方程

A P v P n + 1 = A W v W n + 1 + A E v E n + 1 + A S v S n + 1 + A N v N n + 1 + V P Δ t v P n + h 2 ( p S n − p N n ) A_P v_P^{n+1} = A_W v_W^{n+1}+ A_E v_E^{n+1}+ A_S v_S^{n+1}+ A_N v_N^{n+1} + \frac{V_P}{\Delta t}v_P^n +\frac{h}{2}(p_S^n-p_N^n) APvPn+1=AWvWn+1+AEvEn+1+ASvSn+1+ANvNn+1+ΔtVPvPn+2h(pSnpNn)

1.4. 压力修正方法

以上推导出了速度迭代通式,即由初始时刻 n n n演化到下一时刻 n + 1 n+1 n+1的方程。然而上式中的压力仅靠动量方程无法求解,可想而知还需用到连续性方程求出压力。思路是通过给定的速度场(或者由上述动量方程解出的速度场)来校正压力,使压力满足连续性方程。在此过程中可得压力的修正值 p ′ p^{\prime} p,对此处理方法可分为两种

  1. 参考《数值传热学》SIMPLE算法章节,直接解 p ′ p^{\prime} p方程
  2. OpenFOAM的做法,直接解压力泊松方程

以上两种做法殊途同归,详情可参考该文献

A slight variation of the SIMPLE algorithm can be considered where pressure equation is formulated directly to solve for p p p and not for p ′ p^{\prime} p

1.4.1. 连续性方程离散

对连续性方程做积分并运用高斯散度定理可得
∑ U f n + 1 S = 0 (5) \sum U^{n+1}_f S = 0 \tag{5} Ufn+1S=0(5)

若收敛,则有离散方程成立
A P n U P n + 1 = ∑ A N n U N n + 1 + S P n − ∑ p f n + 1 S (6) A_P^{n} U_P^{n+1}=\sum A_N^{n} U_N^{n+1} + S_P^{n} -\sum p_f^{n+1} S \tag{6} APnUPn+1=ANnUNn+1+SPnpfn+1S(6)

注意:系数 A P , A N , S P A_P, A_N, S_P AP,AN,SP包含的速度均为上一步速度

移项可得
U P n + 1 = H b y A ∣ P n + 1 − 1 A P n ∑ p f n + 1 S (7) U_P^{n+1}=HbyA\big|_P^{n+1} -\frac{1}{A_P^n}\sum p_f^{n+1} S \tag{7} UPn+1=HbyAPn+1APn1pfn+1S(7)

其中
H b y A ∣ P n + 1 = ∑ A N n U N n + 1 + S P n A P n (8) HbyA\big|_P^{n+1} =\frac{\sum A_N^{n} U_N^{n+1} + S_P^{n}}{A_P^n} \tag{8} HbyAPn+1=APnANnUNn+1+SPn(8)

Rhie-Chow提出动量插值法(MIM),由体心速度的迭代通式直接类比成面心速度:
U f n + 1 = H b y A ∣ f n + 1 − 1 A f ( ∑ p f n + 1 S ) f (9) U_f^{n+1}=HbyA\big|_f^{n+1} -\frac{1}{A_f} \left(\sum p_f^{n+1} S \right)_f \tag{9} Ufn+1=HbyAfn+1Af1(pfn+1S)f(9)

将上式代入到连续性方程的离散方程中可得:
∑ U f n + 1 ⋅ S = ∑ [ H b y A ∣ f n + 1 − 1 A f ( ∑ p f n + 1 S ) f ] ⋅ S = 0 \sum U^{n+1}_f \cdot S = \sum \left[ HbyA\big|_f^{n+1} -\frac{1}{A_f} \left( \sum p_f^{n+1} S \right)_f \right] \cdot S =0 Ufn+1S=[HbyAfn+1Af1(pfn+1S)f]S=0

∑ H b y A ∣ f n + 1 ⋅ S = ∑ 1 A f ( ∑ p f n + 1 S ) f ⋅ S (9.5) \sum HbyA\big|_f^{n+1} \cdot S =\sum \frac{1}{A_f} \left( \sum p_f^{n+1} S \right)_f \cdot S \tag{9.5} HbyAfn+1S=Af1(pfn+1S)fS(9.5)

根据高斯散度定理,可以将上式反推为
∇ ⋅ H b y A ∣ n + 1 = ∇ ⋅ ( V P A ∇ p n + 1 ) (10) \nabla \cdot HbyA\big|^{n+1} = \nabla \cdot \left( \frac{V_P}{A}\nabla p^{n+1} \right) \tag{10} HbyAn+1=(AVPpn+1)(10)

可见,上式是关于压力 p p p的泊松方程,其中 V P V_P VP为网格体积。然而上式左右两端均为未知量,无法求解。

面心值需要体心值插值得到,插值算法定义在system/fvSchemes文件中

上式中产生网格体积 V P V_P VP的原因是
( ∇ p ) P V P ≈ ∫ ∇ p d V = ∫ p f d S ≈ ∑ p f S (\nabla p)_P V_P \approx \int \nabla p dV=\int p_f dS \approx \sum p_f S (p)PVPpdV=pfdSpfS

1.4.1.1. HbyA的讨论

上文中引进了一个新的场量,HbyA。CFD将一个物理问题转化为了代数方程组的求解问题,该代数方程组的形式为 A ϕ = Q A\phi=Q Aϕ=Q,其中 A A A为系数矩阵,而本文中的 A P A_P AP正是系数矩阵 A A A的主对角线,对应的OpenFOAM中的代码就是UEqn.A(),在一个时间步内,UEqn.A()不变,而UEqn.H()由于包含新计算出的邻居速度,因此会变

1.4.2. 压力修正值方程推导

由上文动量方程的离散结果可知, U n + 1 U^{n+1} Un+1的计算通式应为公式 ( 4 ) (4) (4),但由于该式中压力仍为上一步值,因此存在滞后,实际上收敛后的 U n + 1 U^{n+1} Un+1应满足公式 ( 6 ) (6) (6),因此此处将公式 ( 4 ) (4) (4)的计算出的速度命名为 U ∗ U^* U,而公式 ( 6 ) (6) (6)计算的速度为 U n + 1 U^{n+1} Un+1,两者相减即为修正值方程
A P U P ′ = ∑ A N U N ′ − ∑ p f ′ S (11) A_PU_P^{\prime} = \sum A_NU_N^{\prime} -\sum p_f^{\prime} S \tag{11} APUP=ANUNpfS(11)

引入略去邻点假设 U P ∗ U_P^{*} UP U P n + 1 U_P^{n+1} UPn+1之间的区别仅是由 p n p^n pn p n + 1 p^{n+1} pn+1引发,而忽略周围邻居的影响,因此
A P U P ′ ≈ − ∑ p f ′ S (12) A_PU_P^{\prime} \approx -\sum p_f^{\prime} S \tag{12} APUPpfS(12)

可以看出,如果求出 p ′ p^{\prime} p,就能求出 U ′ U^{\prime} U,与 U ∗ U^{*} U相加就能求出 U n + 1 U^{n+1} Un+1,因此现在的目标转化为求出 p ′ p^{\prime} p。将公式 ( 12 ) (12) (12)与公式 ( 4 ) (4) (4)相加,
A P n U P n + 1 = ∑ A N n U N ∗ + S P n − ∑ p f n + 1 S (13) A_P^{n} U_P^{n+1}=\sum A_N^{n} U_N^{*} + S_P^{n} -\sum p_f^{n+1} S \tag{13} APnUPn+1=ANnUN+SPnpfn+1S(13)

其中 U n + 1 = U ∗ + U ′ U^{n+1}=U^{*}+U^{\prime} Un+1=U+U p n + 1 = p n + p ′ p^{n+1}=p^n+p^{\prime} pn+1=pn+p,移项并组建压力泊松方程可得
U P n + 1 = H b y A ∣ P ∗ − 1 A P ∑ p f n + 1 S (14) U_P^{n+1}=HbyA\big|_P^{*} -\frac{1}{A_P}\sum p_f^{n+1} S \tag{14} UPn+1=HbyAPAP1pfn+1S(14)

∇ ⋅ H b y A ∣ ∗ = ∇ ⋅ ( V P A ∇ p n + 1 ) (15) \nabla \cdot HbyA\big|^{*} = \nabla \cdot \left( \frac{V_P}{A}\nabla p^{n+1} \right) \tag{15} HbyA=(AVPpn+1)(15)

上式左端已知,右端未知,可以求解。求出压力后,代入公式 ( 14 ) (14) (14)可以计算出新的速度。

可以从另一角度理解。给定初始时刻速度场 U 0 U_0 U0和压力场 p 0 p_0 p0,通过上文离散的动量方程,可解出更新后的速度场 U 1 U_1 U1,注意 U 1 U_1 U1是由 p 0 p_0 p0解出的,可想而知不满足连续性方程,因此要代入连续性方程解出和 U 1 U_1 U1匹配的压力场 p 1 p_1 p1

1.4.3. 压力泊松方程

待求解的压力泊松方程为
∑ ( H b y A ) f ⋅ S = ∑ 1 A f ( ∑ p f n + 1 S ) f ⋅ S \sum (HbyA)_f\cdot S=\sum \frac{1}{A_f} \left( \sum p_f^{n+1} S \right)_f \cdot S (HbyA)fS=Af1(pfn+1S)fS

1.4.3.1. 左端项–HbyA项

HbyA是定义在网格体心的矢量,注意,HbyA应由新计算出的速度场构建,原因在下文给出
H b y A ∣ P = 1 A P n ( A W n U W n + 1 + A E n U E n + 1 + A S n U S n + 1 + A N n U N n + 1 + S P n ) HbyA\big|_P=\frac{1}{A_P^n } (A_W^n U_W^{n+1}+A_E^n U_E^{n+1}+A_S^n U_S^{n+1}+A_N^n U_N^{n+1}+S_P^n) HbyAP=APn1(AWnUWn+1+AEnUEn+1+ASnUSn+1+ANnUNn+1+SPn)

H b y A ∣ P = 1 A P n ( A W n u W n + 1 + A E n u E n + 1 + A S n u S n + 1 + A N n u N n + 1 + V P Δ t u P n A W n v W n + 1 + A E n v E n + 1 + A S n v S n + 1 + A N n v N n + 1 + V P Δ t v P n ) HbyA\big|_P=\frac{1}{A_P^n }\left( A_W^n u_W^{n+1}+A_E^n u_E^{n+1}+A_S^n u_S^{n+1}+A_N^n u_N^{n+1}+\frac{V_P}{\Delta t}u_P^n \quad A_W^n v_W^{n+1}+A_E^n v_E^{n+1}+A_S^n v_S^{n+1}+A_N^n v_N^{n+1}+\frac{V_P}{\Delta t}v_P^n \right) HbyAP=APn1(AWnuWn+1+AEnuEn+1+ASnuSn+1+ANnuNn+1+ΔtVPuPnAWnvWn+1+AEnvEn+1+ASnvSn+1+ANnvNn+1+ΔtVPvPn)

HbyA定义式先计算出 H b y A ∣ P HbyA\big|_P HbyAP H b y A ∣ N HbyA\big|_N HbyAN,然后再计算面上值
( H b y A ) f = H b y A ∣ P + H b y A ∣ N 2 (HbyA)_f=\frac{HbyA\big|_P+HbyA\big|_N}{2} (HbyA)f=2HbyAP+HbyAN

则压力泊松方程的左端为
∑ ( H b y A ) f ⋅ S = H b y A ∣ P + H b y A ∣ E 2 ⋅ ( h , 0 ) + H b y A ∣ P + H b y A ∣ W 2 ⋅ ( − h , 0 ) + H b y A ∣ P + H b y A ∣ N 2 ⋅ ( 0 , h ) + H b y A ∣ P + H b y A ∣ S 2 ⋅ ( 0 , − h ) = ( H b y A ∣ e , x − H b y A ∣ w , x + H b y A ∣ n , y − H b y A ∣ s , y ) h \sum (HbyA)_f\cdot S=\frac{HbyA\big|_P+HbyA\big|_E}{2}\cdot (h,0) + \frac{HbyA\big|_P+HbyA\big|_W}{2}\cdot (-h,0) + \frac{HbyA\big|_P+HbyA\big|_N}{2}\cdot (0,h) + \frac{HbyA\big|_P+HbyA\big|_S}{2}\cdot (0,-h) \\ =(HbyA\big|_{e,x} - HbyA\big|_{w,x} + HbyA\big|_{n,y} - HbyA\big|_{s,y})h (HbyA)fS=2HbyAP+HbyAE(h,0)+2HbyAP+HbyAW(h,0)+2HbyAP+HbyAN(0,h)+2HbyAP+HbyAS(0,h)=(HbyAe,xHbyAw,x+HbyAn,yHbyAs,y)h

上述方程对应着OpenFOAM中的代码

fvc::div(phiHbyA)

1.4.3.2. 右端项–求解压力项的两种方法

  1. 由上文 ∑ p f S \sum p_f S pfS的计算方法,同样先计算网格值再计算面上值
    ( ∑ p f n + 1 S ) f = ( ∑ p f n + 1 S ) P + ( ∑ p f n + 1 S ) N 2 \left( \sum p_f^{n+1} S \right)_f=\frac{\left( \sum p_f^{n+1} S \right)_P+\left( \sum p_f^{n+1} S \right)_N}{2} (pfn+1S)f=2(pfn+1S)P+(pfn+1S)N

∑ ( ∑ p f n + 1 S ) f ⋅ S = ∑ ( ∑ p f n + 1 S ) w ⋅ S w + ∑ ( ∑ p f n + 1 S ) e ⋅ S e + ∑ ( ∑ p f n + 1 S ) s ⋅ S s + ∑ ( ∑ p f n + 1 S ) n ⋅ S n \sum \left( \sum p_f^{n+1} S \right)_f \cdot S = \sum \left( \sum p_f^{n+1} S \right)_w \cdot S_w + \sum \left( \sum p_f^{n+1} S \right)_e \cdot S_e + \sum \left( \sum p_f^{n+1} S \right)_s \cdot S_s + \sum \left( \sum p_f^{n+1} S \right)_n \cdot S_n (pfn+1S)fS=(pfn+1S)wSw+(pfn+1S)eSe+(pfn+1S)sSs+(pfn+1S)nSn

这种求解方法对应的代码是

fvc::div(fvc::grad(p))
  1. ∑ p f S \sum p_f S pfS还原为原始形式 ∇ p V P \nabla p V_P pVP
    ∫ ∇ ⋅ ( ∇ p V P ) d V = V P ∫ ∇ p d S = V P ∑ ( ∇ p ) f S = V P ∑ ( ( ∇ p ) f ⋅ S S f ) S f \int \nabla \cdot (\nabla p V_P) dV=V_P \int \nabla p dS = V_P \sum (\nabla p)_f S = V_P \sum \left( (\nabla p)_f \cdot \frac{S}{S_f} \right) S_f (pVP)dV=VPpdS=VP(p)fS=VP((p)fSfS)Sf

其中大括号内的项对应的代码为snGrad(p),而上式整个对应的代码为

fvm::laplacian(p)

关于这两种方法的讨论在无痛苦NS方程笔记laplacian(ϕ) = div(grad(ϕ))?这一小节提到。而icoFoam求解器中采用的方法为第二种。按这种方法,

∑ ( ( ∇ p ) f ⋅ S S f ) S f = p E − p P d h + p P − p W d ( − h ) + p N − p P d h + p P − p S d ( − h ) \sum \left( (\nabla p)_f \cdot \frac{S}{S_f} \right) S_f = \frac{p_E-p_P}{d}h + \frac{p_P-p_W}{d}(-h) + \frac{p_N-p_P}{d}h + \frac{p_P-p_S}{d}(-h) ((p)fSfS)Sf=dpEpPh+dpPpW(h)+dpNpPh+dpPpS(h)

( A P ) f (A_P)_f (AP)f加入进来构成以下求解代码

fvm::laplacian(rAU, p)

C = 1 / A P C=1/A_P C=1/AP则整理后
V P ∑ C f ( ( ∇ p ) f ⋅ S S f ) S f = V P [ C e p E − p P d h + C w p P − p W d ( − h ) + C n p N − p P d h + C s p P − p S d ( − h ) ] = V P h d [ C w ∗ p W + C e ∗ p E + C s ∗ p S + C n ∗ p N − ( C w + C e + C s + C n ) p P ] V_P \sum C_f \left( (\nabla p)_f \cdot \frac{S}{S_f} \right) S_f = V_P \left[ C_e\frac{p_E-p_P}{d}h + C_w\frac{p_P-p_W}{d}(-h) + C_n\frac{p_N-p_P}{d}h + C_s\frac{p_P-p_S}{d}(-h) \right] \\ =\frac{V_Ph}{d} [C_w*p_W+C_e*p_E+C_s*p_S+C_n*p_N -(C_w+C_e+C_s+C_n)p_P] VPCf((p)fSfS)Sf=VP[CedpEpPh+CwdpPpW(h)+CndpNpPh+CsdpPpS(h)]=dVPh[CwpW+CepE+CspS+CnpN(Cw+Ce+Cs+Cn)pP]

加上泊松方程的左端项sumPhiHbyA,则得到压力的更新方程
p P = C w ∗ p W + C e ∗ p E + C s ∗ p S + C n ∗ p N − s u m P h i H b y A ∗ d / h / V P C w + C e + C s + C n p_P=\frac{C_w*p_W+C_e*p_E+C_s*p_S+C_n*p_N-sumPhiHbyA*d/h/V_P}{C_w+C_e+C_s+C_n} pP=Cw+Ce+Cs+CnCwpW+CepE+CspS+CnpNsumPhiHbyAd/h/VP

本文中 A P A_P AP为系数,标量。注意到方程中求解的是rAU 1 / A f 1/A_f 1/Af,因此 1 / A f = ( 1 / A P + 1 / A N ) / 2 1/A_f=(1/A_P+1/A_N)/2 1/Af=(1/AP+1/AN)/2,详情参考文献。至此为止,压力方程组建完毕,可以求解。

1.4.3.3. AP和HbyA在边界面上的插值

目前看到两种处理方法,

  1. 来自openfoamwiki的simpleFoam解析的第2.2.3小节,相当于在边界面上使用Rhie-Chow插值

The velocity at the boundary face should satisfy following equation:
U ∣ b f = H ( U ) a P ∣ b f − ∇ p a P ∣ b f U\big|_{bf}=\frac{H(U)}{a_P}\bigg|_{bf}-\frac{\nabla p}{a_P}\bigg|_{bf} Ubf=aPH(U)bfaPpbf

由于面上的 U U U ∇ p \nabla p p已知,因此由该方程可以解出边界面上的HbyA

  1. 来自李东岳的回答。

phi, phiHbyA是通量,通量的边界是固定的,不需要插值

这种说法是有道理的,因为我观察了icoFoam计算出的phi,发现其大小为内部面的个数,即phi文件的元素个数和polyMesh/neighbour文件相同

本文的处理方法:回归原本的连续性方程。对于左上角网格, U w = ( 0 , 0 ) , U n = ( 1 , 0 ) U_w=(0,0), U_n=(1,0) Uw=(0,0),Un=(1,0)
∑ U f ⋅ S = U e S e + U w S w + U s S s + U n S n = U e S e + U s S s = [ H b y A ∣ e ∗ − 1 A e ( ∑ p f n + 1 S ) e ] ( h , 0 ) + [ H b y A ∣ s ∗ − 1 A s ( ∑ p f n + 1 S ) s ] ( 0 , − h ) = 0 \sum U_f \cdot S = U_e S_e+U_w S_w + U_s S_s + U_n S_n = U_e S_e + U_s S_s \\ =\left[ HbyA\big|_e^{*} -\frac{1}{A_e} \left(\sum p_f^{n+1} S \right)_e \right] (h,0) + \left[ HbyA\big|_s^{*} -\frac{1}{A_s} \left(\sum p_f^{n+1} S \right)_s\right] (0,-h) = 0 UfS=UeSe+UwSw+UsSs+UnSn=UeSe+UsSs=[HbyAeAe1(pfn+1S)e](h,0)+[HbyAsAs1(pfn+1S)s](0,h)=0

你可能感兴趣的:(理论基础,算法,线性代数)