结构风振仿真-主题022-RANS模型与应用
主题022:RANS模型与应用
1. 引言
在计算流体力学(CFD)领域,湍流模拟一直是核心挑战之一。湍流是一种高度复杂的三维非定常流动现象,其特征是多尺度涡旋结构和能量级串。对于工程应用而言,直接数值模拟(DNS)虽然能够精确求解所有尺度的湍流运动,但其计算成本极高,难以应用于实际工程问题。大涡模拟(LES)虽然比DNS经济,但仍需要相当大的计算资源。因此,基于时间平均的雷诺平均纳维-斯托克斯(RANS)方法成为工程湍流模拟的主流方法。
RANS方法通过将流动变量分解为时均量和脉动量,对Navier-Stokes方程进行时间平均,得到描述时均流动的方程组。由于时间平均过程引入了新的未知量——雷诺应力,因此需要建立湍流模型来封闭方程组。自20世纪70年代以来,各种RANS湍流模型被提出并广泛应用于工程领域,从简单的零方程模型到复杂的多方程模型,为不同类型的流动问题提供了有效的解决方案。
在结构风振仿真中,RANS模型被广泛用于计算建筑物周围的风场分布、风压系数、以及评估风荷载特性。虽然RANS模型在预测复杂分离流动和涡脱落方面存在一定局限性,但对于定常或准定常风荷载分析、初步设计阶段的快速评估等应用场景,RANS模型仍然具有重要价值。本章将系统介绍RANS方法的基本理论、各类湍流模型的特点与应用,以及在结构风工程中的具体应用案例。



2. RANS方法的理论基础
2.1 雷诺分解
RANS方法的核心是雷诺分解,即将瞬时流动变量分解为时均量和脉动量两部分。对于任意流动变量φ,可以表示为:
φ=φˉ+φ′ φ = \bar{φ} + φ' φ=φˉ+φ′
其中,φˉ\bar{φ}φˉ是时均值,φ′φ'φ′是脉动量。时均值的定义为:
φˉ=limT→∞1T∫t0t0+Tφ dt \bar{φ} = \lim_{T \to \infty} \frac{1}{T} \int_{t_0}^{t_0+T} φ \, dt φˉ=T→∞limT1∫t0t0+Tφdt
在实际计算中,取足够长的时间间隔T,使得平均结果不再随T变化。对于定常流动,时间平均等价于系综平均;对于非定常流动,可以采用相平均或滤波平均。
雷诺分解具有以下重要性质:
-
时均量的时均等于自身:
φˉ‾=φˉ \overline{\bar{φ}} = \bar{φ} φˉ=φˉ -
脉动量的时均等于零:
φ′‾=0 \overline{φ'} = 0 φ′=0 -
时均量与脉动量乘积的时均等于零:
φˉφ′‾=φˉ⋅φ′‾=0 \overline{\bar{φ}φ'} = \bar{φ} \cdot \overline{φ'} = 0 φˉφ′=φˉ⋅φ′=0 -
两个脉动量乘积的时均一般不为零:
φ′ψ′‾≠0 \overline{φ'ψ'} \neq 0 φ′ψ′=0
2.2 雷诺平均Navier-Stokes方程
对不可压缩流动的Navier-Stokes方程进行时间平均,得到RANS方程组。
连续性方程:
∂uˉi∂xi=0 \frac{\partial \bar{u}_i}{\partial x_i} = 0 ∂xi∂uˉi=0
动量方程:
∂uˉi∂t+uˉj∂uˉi∂xj=−1ρ∂pˉ∂xi+ν∂2uˉi∂xj∂xj−∂∂xj(ui′uj′‾) \frac{\partial \bar{u}_i}{\partial t} + \bar{u}_j \frac{\partial \bar{u}_i}{\partial x_j} = -\frac{1}{\rho} \frac{\partial \bar{p}}{\partial x_i} + \nu \frac{\partial^2 \bar{u}_i}{\partial x_j \partial x_j} - \frac{\partial}{\partial x_j}(\overline{u_i' u_j'}) ∂t∂uˉi+uˉj∂xj∂uˉi=−ρ1∂xi∂pˉ+ν∂xj∂xj∂2uˉi−∂xj∂(ui′uj′)
其中,ui′uj′‾\overline{u_i' u_j'}ui′uj′是雷诺应力张量,表示湍流脉动对时均流动的影响。雷诺应力是一个对称张量,包含6个独立分量:
τij(t)=−ρui′uj′‾=(−ρu′2‾−ρu′v′‾−ρu′w′‾−ρu′v′‾−ρv′2‾−ρv′w′‾−ρu′w′‾−ρv′w′‾−ρw′2‾) \tau_{ij}^{(t)} = -\rho \overline{u_i' u_j'} = \begin{pmatrix} -\rho \overline{u'^2} & -\rho \overline{u'v'} & -\rho \overline{u'w'} \\ -\rho \overline{u'v'} & -\rho \overline{v'^2} & -\rho \overline{v'w'} \\ -\rho \overline{u'w'} & -\rho \overline{v'w'} & -\rho \overline{w'^2} \end{pmatrix} τij(t)=−ρui′uj′= −ρu′2−ρu′v′−ρu′w′−ρu′v′−ρv′2−ρv′w′−ρu′w′−ρv′w′−ρw′2
2.3 封闭问题
RANS方程组中,未知量包括3个速度分量、压力和6个雷诺应力分量,共10个未知量,而方程只有4个(1个连续性方程+3个动量方程)。因此,需要建立6个额外的关系式来封闭方程组,这就是湍流模型的任务。
湍流模型的基本思想是建立雷诺应力与时均速度场之间的关系。根据建模方式的不同,湍流模型可以分为以下几类:
- 代数模型(零方程模型):直接建立雷诺应力与时均速度梯度的代数关系
- 一方程模型:引入一个湍流特征量(通常是湍动能k)的输运方程
- 两方程模型:引入两个湍流特征量的输运方程,如k-ε模型、k-ω模型
- 雷诺应力模型(RSM):直接求解雷诺应力的输运方程
- 非线性涡粘模型:在涡粘假设基础上引入非线性修正
2.4 涡粘假设
大多数工程湍流模型基于Boussinesq涡粘假设,即雷诺应力与平均应变率成正比:
−ui′uj′‾=νt(∂uˉi∂xj+∂uˉj∂xi)−23kδij -\overline{u_i' u_j'} = \nu_t \left( \frac{\partial \bar{u}_i}{\partial x_j} + \frac{\partial \bar{u}_j}{\partial x_i} \right) - \frac{2}{3} k \delta_{ij} −ui′uj′=νt(∂xj∂uˉi+∂xi∂uˉj)−32kδij
其中,νt\nu_tνt是涡粘系数(湍流粘性系数),k是湍动能,δij\delta_{ij}δij是Kronecker delta符号。
涡粘系数的量纲为[L2/T][L^2/T][L2/T],可以表示为湍流特征速度utu_tut和特征长度ltl_tlt的乘积:
νt=Cutlt \nu_t = C u_t l_t νt=Cutlt
其中C是常数。不同湍流模型的主要区别在于如何确定这两个特征量。
3. 零方程模型
3.1 混合长度理论
零方程模型是最简单的湍流模型,它不需要求解额外的输运方程,直接通过代数关系计算涡粘系数。Prandtl混合长度理论是最早的零方程模型。
Prandtl假设湍流脉动速度与平均速度梯度和混合长度成正比:
∣u′∣≈lm∣duˉdy∣ |u'| \approx l_m \left| \frac{d\bar{u}}{dy} \right| ∣u′∣≈lm dyduˉ
涡粘系数表示为:
νt=lm2∣duˉdy∣ \nu_t = l_m^2 \left| \frac{d\bar{u}}{dy} \right| νt=lm2 dyduˉ
混合长度lml_mlm需要根据流动类型确定。对于边界层流动,通常取:
lm=κy l_m = \kappa y lm=κy
其中,κ=0.41\kappa = 0.41κ=0.41是von Kármán常数,y是到壁面的距离。在外层区域,混合长度趋于常数:
lm=λδ l_m = \lambda \delta lm=λδ
其中,λ≈0.09\lambda \approx 0.09λ≈0.09,δ\deltaδ是边界层厚度。
3.2 Cebeci-Smith模型
Cebeci-Smith模型是一种改进的混合长度模型,适用于边界层流动。该模型将边界层分为内层和外层:
内层(y≤ycy \leq y_cy≤yc):
νt(i)=l2∣∂uˉ∂y∣γtr \nu_t^{(i)} = l^2 \left| \frac{\partial \bar{u}}{\partial y} \right| \gamma_{tr} νt(i)=l2 ∂y∂uˉ γtr
其中,l=κy[1−exp(−y+/A+)]l = \kappa y [1 - \exp(-y^+/A^+)]l=κy[1−exp(−y+/A+)],y+=yuτ/νy^+ = y u_\tau / \nuy+=yuτ/ν,A+=26A^+ = 26A+=26,γtr\gamma_{tr}γtr是转捩因子。
外层(y>ycy > y_cy>yc):
νt(o)=αuˉeδ∗γtrFKleb \nu_t^{(o)} = \alpha \bar{u}_e \delta^* \gamma_{tr} F_{Kleb} νt(o)=αuˉeδ∗γtrFKleb
其中,α=0.0168\alpha = 0.0168α=0.0168,uˉe\bar{u}_euˉe是边界层外缘速度,δ∗\delta^*δ∗是位移厚度,FKlebF_{Kleb}FKleb是Klebanoff间歇因子。
内外层在ycy_cyc处平滑过渡,ycy_cyc是使νt(i)=νt(o)\nu_t^{(i)} = \nu_t^{(o)}νt(i)=νt(o)的位置。
3.3 Baldwin-Lomax模型
Baldwin-Lomax模型是另一种广泛使用的零方程模型,特别适用于分离流动。该模型同样分为内外两层:
内层:
νt(i)=l2∣ω∣ \nu_t^{(i)} = l^2 |\omega| νt(i)=l2∣ω∣
其中,∣ω∣|\omega|∣ω∣是涡量大小,l=κy[1−exp(−y+/A+)]l = \kappa y [1 - \exp(-y^+/A^+)]l=κy[1−exp(−y+/A+)]。
外层:
νt(o)=KCcpFwakeFKleb \nu_t^{(o)} = K C_{cp} F_{wake} F_{Kleb} νt(o)=KCcpFwakeFKleb
其中,Fwake=min(ymaxFmax,CwkymaxUdif2/Fmax)F_{wake} = \min(y_{max} F_{max}, C_{wk} y_{max} U_{dif}^2/F_{max})Fwake=min(ymaxFmax,CwkymaxUdif2/Fmax),F=y∣ω∣[1−exp(−y+/A+)]F = y|\omega|[1 - \exp(-y^+/A^+)]F=y∣ω∣[1−exp(−y+/A+)]。
模型常数:κ=0.4\kappa = 0.4κ=0.4,A+=26A^+ = 26A+=26,K=0.0168K = 0.0168K=0.0168,Ccp=1.6C_{cp} = 1.6Ccp=1.6,Cwk=0.25C_{wk} = 0.25Cwk=0.25。
3.4 零方程模型的特点与应用
优点:
- 计算简单,不需要求解额外的输运方程
- 计算成本低,收敛性好
- 对简单剪切流动(如边界层、管道流)预测较好
缺点:
- 无法考虑湍流的历史效应和对流输运
- 对复杂流动(分离流、回流区)预测较差
- 混合长度需要针对不同流动类型调整
应用:
- 航空器外部流场初步分析
- 简单管道流动和边界层计算
- 作为更复杂模型的初始场
4. 一方程模型
4.1 湍动能方程
一方程模型通过求解湍动能k的输运方程来确定涡粘系数。湍动能定义为:
k=12(u′2‾+v′2‾+w′2‾) k = \frac{1}{2}(\overline{u'^2} + \overline{v'^2} + \overline{w'^2}) k=21(u′2+v′2+w′2)
湍动能的精确输运方程可以从Navier-Stokes方程推导得到:
∂k∂t+uˉj∂k∂xj=Pk−ε+∂∂xj[ν∂k∂xj−12ui′ui′uj′‾−1ρp′uj′‾] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - \varepsilon + \frac{\partial}{\partial x_j} \left[ \nu \frac{\partial k}{\partial x_j} - \frac{1}{2}\overline{u_i' u_i' u_j'} - \frac{1}{\rho}\overline{p' u_j'} \right] ∂t∂k+uˉj∂xj∂k=Pk−ε+∂xj∂[ν∂xj∂k−21ui′ui′uj′−ρ1p′uj′]
其中,Pk=−ui′uj′‾∂uˉi∂xjP_k = -\overline{u_i' u_j'} \frac{\partial \bar{u}_i}{\partial x_j}Pk=−ui′uj′∂xj∂uˉi是湍动能生成项,ε=ν∂ui′∂xj∂ui′∂xj‾\varepsilon = \nu \overline{\frac{\partial u_i'}{\partial x_j}\frac{\partial u_i'}{\partial x_j}}ε=ν∂xj∂ui′∂xj∂ui′是湍动能耗散率。
4.2 模型封闭
一方程模型假设涡粘系数与湍动能和特征长度相关:
νt=CμkL \nu_t = C_\mu \sqrt{k} L νt=CμkL
其中,CμC_\muCμ是模型常数,L是湍流长度尺度。长度尺度通常由代数关系给出,如:
L=min(κy,CLδ) L = \min(\kappa y, C_L \delta) L=min(κy,CLδ)
湍动能耗散率通过:
ε=CDk3/2L \varepsilon = C_D \frac{k^{3/2}}{L} ε=CDLk3/2
湍流扩散项采用梯度扩散假设:
−12ui′ui′uj′‾−1ρp′uj′‾=νtσk∂k∂xj -\frac{1}{2}\overline{u_i' u_i' u_j'} - \frac{1}{\rho}\overline{p' u_j'} = \frac{\nu_t}{\sigma_k} \frac{\partial k}{\partial x_j} −21ui′ui′uj′−ρ1p′uj′=σkνt∂xj∂k
最终得到模型化的湍动能输运方程:
∂k∂t+uˉj∂k∂xj=Pk−CDk3/2L+∂∂xj[(ν+νtσk)∂k∂xj] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - C_D \frac{k^{3/2}}{L} + \frac{\partial}{\partial x_j} \left[ \left(\nu + \frac{\nu_t}{\sigma_k}\right) \frac{\partial k}{\partial x_j} \right] ∂t∂k+uˉj∂xj∂k=Pk−CDLk3/2+∂xj∂[(ν+σkνt)∂xj∂k]
4.3 一方程模型的特点
优点:
- 考虑了湍动能的对流和扩散输运
- 比零方程模型更适合非平衡流动
- 计算成本仍然较低
缺点:
- 长度尺度仍需经验确定
- 对复杂流动的适用性有限
- 不如两方程模型通用
代表模型:
- Prandtl-Kolmogorov模型
- Wolfshtein模型
- Baldwin-Barth模型
5. 标准k-ε模型
5.1 模型方程
k-ε模型是目前应用最广泛的湍流模型之一。该模型引入湍动能k和湍动能耗散率ε两个变量,通过求解各自的输运方程来确定涡粘系数。
湍动能输运方程:
∂k∂t+uˉj∂k∂xj=Pk−ε+∂∂xj[(ν+νtσk)∂k∂xj] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - \varepsilon + \frac{\partial}{\partial x_j} \left[ \left(\nu + \frac{\nu_t}{\sigma_k}\right) \frac{\partial k}{\partial x_j} \right] ∂t∂k+uˉj∂xj∂k=Pk−ε+∂xj∂[(ν+σkνt)∂xj∂k]
耗散率输运方程:
∂ε∂t+uˉj∂ε∂xj=Cε1εkPk−Cε2ε2k+∂∂xj[(ν+νtσε)∂ε∂xj] \frac{\partial \varepsilon}{\partial t} + \bar{u}_j \frac{\partial \varepsilon}{\partial x_j} = C_{\varepsilon 1} \frac{\varepsilon}{k} P_k - C_{\varepsilon 2} \frac{\varepsilon^2}{k} + \frac{\partial}{\partial x_j} \left[ \left(\nu + \frac{\nu_t}{\sigma_\varepsilon}\right) \frac{\partial \varepsilon}{\partial x_j} \right] ∂t∂ε+uˉj∂xj∂ε=Cε1kεPk−Cε2kε2+∂xj∂[(ν+σενt)∂xj∂ε]
涡粘系数:
νt=Cμk2ε \nu_t = C_\mu \frac{k^2}{\varepsilon} νt=Cμεk2
湍动能生成项:
Pk=νt(∂uˉi∂xj+∂uˉj∂xi)∂uˉi∂xj P_k = \nu_t \left( \frac{\partial \bar{u}_i}{\partial x_j} + \frac{\partial \bar{u}_j}{\partial x_i} \right) \frac{\partial \bar{u}_i}{\partial x_j} Pk=νt(∂xj∂uˉi+∂xi∂uˉj)∂xj∂uˉi
5.2 模型常数
标准k-ε模型的常数通过拟合简单流动(如衰减各向同性湍流、均匀剪切流、对数律边界层)的实验数据确定:
| 常数 | 数值 | 物理意义 |
|---|---|---|
| CμC_\muCμ | 0.09 | 涡粘系数常数 |
| Cε1C_{\varepsilon 1}Cε1 | 1.44 | 生成项系数 |
| Cε2C_{\varepsilon 2}Cε2 | 1.92 | 耗散项系数 |
| σk\sigma_kσk | 1.0 | k的Prandtl数 |
| σε\sigma_\varepsilonσε | 1.3 | ε的Prandtl数 |
这些常数在广泛流动中表现良好,但对于某些特定流动可能需要调整。
5.3 边界条件
入口边界:
- 给定k和ε的值,或给定湍流强度I和特征长度L:
k=32(UI)2,ε=Cμ3/4k3/2L k = \frac{3}{2}(U I)^2, \quad \varepsilon = C_\mu^{3/4} \frac{k^{3/2}}{L} k=23(UI)2,ε=Cμ3/4Lk3/2
出口边界:
- 通常采用零梯度条件:∂k∂n=0\frac{\partial k}{\partial n} = 0∂n∂k=0,∂ε∂n=0\frac{\partial \varepsilon}{\partial n} = 0∂n∂ε=0
对称边界:
- 法向梯度为零,法向速度为零
固壁边界:
- 使用壁面函数或低雷诺数修正
5.4 壁面处理
壁面函数法:
在壁面附近,采用壁面函数避免求解粘性底层。对于对数律区域(y+>30y^+ > 30y+>30):
ut=κyuτ,u+=1κln(Ey+) u_t = \kappa y u_\tau, \quad u^+ = \frac{1}{\kappa} \ln(E y^+)ut=κyuτ,u+=κ1ln(Ey+)
壁面剪切应力:
τw=ρuτ2=ρCμ1/4k1/2uˉu+ \tau_w = \rho u_\tau^2 = \rho C_\mu^{1/4} k^{1/2} \frac{\bar{u}}{u^+} τw=ρuτ2=ρCμ1/4k1/2u+uˉ
壁面处k和ε的边界条件:
∂k∂n=0,ε=Cμ3/4k3/2κy \frac{\partial k}{\partial n} = 0, \quad \varepsilon = \frac{C_\mu^{3/4} k^{3/2}}{\kappa y} ∂n∂k=0,ε=κyCμ3/4k3/2
低雷诺数修正:
对于需要求解到壁面的情况(y+<1y^+ < 1y+<1),采用低雷诺数k-ε模型,引入衰减函数:
νt=Cμfμk2ε~,ε=ε~+D \nu_t = C_\mu f_\mu \frac{k^2}{\tilde{\varepsilon}}, \quad \varepsilon = \tilde{\varepsilon} + Dνt=Cμfμε~k2,ε=ε~+D
其中,fμf_\mufμ是粘性衰减函数,D是近壁修正项。
5.5 标准k-ε模型的特点
优点:
- 简单、稳定、计算成本低
- 对简单剪切流动和回流区预测较好
- 广泛验证,有大量应用经验
缺点:
- 对强逆压梯度流动预测不足
- 对旋转流动、曲率效应敏感
- 对圆形射流的扩展率预测过高
- 近壁区域需要特殊处理
6. RNG k-ε模型
6.1 重整化群理论
RNG(Renormalization Group)k-ε模型基于重整化群理论推导得到。RNG理论通过系统性地消除小尺度涡的影响,从大尺度方程推导湍流模型。
6.2 模型方程
RNG k-ε模型与标准k-ε模型形式相似,但系数不同:
k方程:
∂k∂t+uˉj∂k∂xj=Pk−ε+∂∂xj[αkνeff∂k∂xj] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - \varepsilon + \frac{\partial}{\partial x_j} \left[ \alpha_k \nu_{eff} \frac{\partial k}{\partial x_j} \right] ∂t∂k+uˉj∂xj∂k=Pk−ε+∂xj∂[αkνeff∂xj∂k]
ε方程:
∂ε∂t+uˉj∂ε∂xj=Cε1∗εkPk−Cε2ε2k+∂∂xj[αενeff∂ε∂xj] \frac{\partial \varepsilon}{\partial t} + \bar{u}_j \frac{\partial \varepsilon}{\partial x_j} = C_{\varepsilon 1}^* \frac{\varepsilon}{k} P_k - C_{\varepsilon 2} \frac{\varepsilon^2}{k} + \frac{\partial}{\partial x_j} \left[ \alpha_\varepsilon \nu_{eff} \frac{\partial \varepsilon}{\partial x_j} \right] ∂t∂ε+uˉj∂xj∂ε=Cε1∗kεPk−Cε2kε2+∂xj∂[αενeff∂xj∂ε]
其中,νeff=ν+νt\nu_{eff} = \nu + \nu_tνeff=ν+νt,αk=αε≈1.393\alpha_k = \alpha_\varepsilon \approx 1.393αk=αε≈1.393。
6.3 关键改进
应变率修正:
Cε1∗=Cε1−η(1−η/η0)1+βη3 C_{\varepsilon 1}^* = C_{\varepsilon 1} - \frac{\eta(1 - \eta/\eta_0)}{1 + \beta\eta^3} Cε1∗=Cε1−1+βη3η(1−η/η0)
其中,η=Sk/ε\eta = S k / \varepsilonη=Sk/ε,S=2SijSijS = \sqrt{2S_{ij}S_{ij}}S=2SijSij是应变率大小,η0=4.377\eta_0 = 4.377η0=4.377,β=0.012\beta = 0.012β=0.012。
有效粘性:
RNG模型给出了低雷诺数情况下的有效粘性公式:
νeff=ν[1+H(ε~ν3/2−100)]1/3 \nu_{eff} = \nu [1 + H(\frac{\tilde{\varepsilon}}{\nu^{3/2}} - 100)]^{1/3} νeff=ν[1+H(ν3/2ε~−100)]1/3
其中,H是Heaviside函数。
6.4 RNG k-ε模型的特点
优点:
- 对高应变率和弯曲流线流动预测更好
- 对分离流和回流区预测改进
- 对室内通风、旋转机械等应用更合适
- 包含低雷诺数效应,无需壁面函数
缺点:
- 计算成本略高于标准k-ε模型
- 对圆形射流预测仍不理想
- 某些情况下可能过度预测湍流生成
7. Realizable k-ε模型
7.1 可实现性约束
标准k-ε模型在某些流动条件下违反可实现性条件,即雷诺应力可能取非物理值。Realizable k-ε模型通过修正涡粘系数和耗散率方程来保证可实现性。
7.2 模型方程
涡粘系数:
νt=Cμ∗k2ε \nu_t = C_\mu^* \frac{k^2}{\varepsilon} νt=Cμ∗εk2
其中,Cμ∗C_\mu^*Cμ∗是应变率的函数:
Cμ∗=1A0+AskU∗ε C_\mu^* = \frac{1}{A_0 + A_s \frac{k U^*}{\varepsilon}} Cμ∗=A0+AsεkU∗1
U∗=SijSij+Ω~ijΩ~ij,A0=4.04,As=6cosϕ U^* = \sqrt{S_{ij}S_{ij} + \tilde{\Omega}_{ij}\tilde{\Omega}_{ij}}, \quad A_0 = 4.04, \quad A_s = \sqrt{6}\cos\phiU∗=SijSij+Ω~ijΩ~ij,A0=4.04,As=6cosϕ
ε方程:
∂ε∂t+uˉj∂ε∂xj=C1Sε−C2ε2k+νε+∂∂xj[(ν+νtσε)∂ε∂xj] \frac{\partial \varepsilon}{\partial t} + \bar{u}_j \frac{\partial \varepsilon}{\partial x_j} = C_1 S \varepsilon - C_2 \frac{\varepsilon^2}{k + \sqrt{\nu\varepsilon}} + \frac{\partial}{\partial x_j} \left[ \left(\nu + \frac{\nu_t}{\sigma_\varepsilon}\right) \frac{\partial \varepsilon}{\partial x_j} \right] ∂t∂ε+uˉj∂xj∂ε=C1Sε−C2k+νεε2+∂xj∂[(ν+σενt)∂xj∂ε]
其中,C1=max(0.43,η5+η)C_1 = \max(0.43, \frac{\eta}{5 + \eta})C1=max(0.43,5+ηη),η=Sk/ε\eta = S k / \varepsilonη=Sk/ε。
7.3 Realizable k-ε模型的特点
优点:
- 满足可实现性条件,数值稳定性好
- 对平面射流、圆形射流、轴对称射流预测一致
- 对分离流和复杂二次流预测改进
- 对强剪切流动和旋转流动更合适
缺点:
- 计算成本略高
- 对壁面边界层需要仔细处理
- 某些情况下可能预测过度分离
8. k-ω模型
8.1 模型方程
k-ω模型由Wilcox提出,用比耗散率ω代替ε。ω的定义为:
ω=εCμk=ε0.09k \omega = \frac{\varepsilon}{C_\mu k} = \frac{\varepsilon}{0.09 k} ω=Cμkε=0.09kε
k方程:
∂k∂t+uˉj∂k∂xj=Pk−β∗kω+∂∂xj[(ν+σkkω)∂k∂xj] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - \beta^* k \omega + \frac{\partial}{\partial x_j} \left[ \left(\nu + \sigma_k \frac{k}{\omega}\right) \frac{\partial k}{\partial x_j} \right] ∂t∂k+uˉj∂xj∂k=Pk−β∗kω+∂xj∂[(ν+σkωk)∂xj∂k]
ω方程:
∂ω∂t+uˉj∂ω∂xj=αωkPk−βω2+∂∂xj[(ν+σωkω)∂ω∂xj] \frac{\partial \omega}{\partial t} + \bar{u}_j \frac{\partial \omega}{\partial x_j} = \alpha \frac{\omega}{k} P_k - \beta \omega^2 + \frac{\partial}{\partial x_j} \left[ \left(\nu + \sigma_\omega \frac{k}{\omega}\right) \frac{\partial \omega}{\partial x_j} \right] ∂t∂ω+uˉj∂xj∂ω=αkωPk−βω2+∂xj∂[(ν+σωωk)∂xj∂ω]
涡粘系数:
νt=kω \nu_t = \frac{k}{\omega} νt=ωk
8.2 模型常数
Wilcox k-ω模型的常数:
| 常数 | 数值 |
|---|---|
| α\alphaα | 5/9 |
| β\betaβ | 3/40 |
| β∗\beta^*β∗ | 9/100 |
| σk\sigma_kσk | 1/2 |
| σω\sigma_\omegaσω | 1/2 |
8.3 壁面边界条件
k-ω模型的一个优势是可以直接应用到壁面,无需壁面函数:
壁面处:
k=0,ω=6νβy2 k = 0, \quad \omega = \frac{6\nu}{\beta y^2} k=0,ω=βy26ν
或采用渐进边界条件:
ω=uτ2ν或ω=4000uτy12 \omega = \frac{u_\tau^2}{\nu} \quad \text{或} \quad \omega = \frac{4000 u_\tau}{y_1^2} ω=νuτ2或ω=y124000uτ
8.4 k-ω模型的特点
优点:
- 对逆压梯度流动和分离流预测更好
- 可以积分到壁面,无需壁面函数
- 对低雷诺数流动适用
- 对尾流和剪切层预测较好
缺点:
- 对自由流ω值敏感
- 在k-ω和k-ε模型转换区可能不稳定
- 对圆形射流预测仍不理想
9. SST k-ω模型
9.1 混合函数
SST(Shear Stress Transport)k-ω模型由Menter提出,结合了k-ω模型在近壁区的优势和k-ε模型在远场的优势。通过混合函数实现两种模型的平滑过渡。
9.2 模型方程
k方程:
∂k∂t+uˉj∂k∂xj=Pk−β∗kω+∂∂xj[(ν+σkνt)∂k∂xj] \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = P_k - \beta^* k \omega + \frac{\partial}{\partial x_j} \left[ \left(\nu + \sigma_k \nu_t\right) \frac{\partial k}{\partial x_j} \right] ∂t∂k+uˉj∂xj∂k=Pk−β∗kω+∂xj∂[(ν+σkνt)∂xj∂k]
ω方程:
∂ω∂t+uˉj∂ω∂xj=ανtPk−βω2+∂∂xj[(ν+σωνt)∂ω∂xj]+2(1−F1)σω2ω∂k∂xj∂ω∂xj \frac{\partial \omega}{\partial t} + \bar{u}_j \frac{\partial \omega}{\partial x_j} = \frac{\alpha}{\nu_t} P_k - \beta \omega^2 + \frac{\partial}{\partial x_j} \left[ \left(\nu + \sigma_\omega \nu_t\right) \frac{\partial \omega}{\partial x_j} \right] + 2(1 - F_1) \frac{\sigma_{\omega 2}}{\omega} \frac{\partial k}{\partial x_j} \frac{\partial \omega}{\partial x_j} ∂t∂ω+uˉj∂xj∂ω=νtαPk−βω2+∂xj∂[(ν+σωνt)∂xj∂ω]+2(1−F1)ωσω2∂xj∂k∂xj∂ω
涡粘系数:
νt=a1kmax(a1ω,SF2) \nu_t = \frac{a_1 k}{\max(a_1 \omega, S F_2)} νt=max(a1ω,SF2)a1k
其中,S=2SijSijS = \sqrt{2S_{ij}S_{ij}}S=2SijSij是应变率大小。
9.3 混合函数
内层函数:
F1=tanh({min[max(kβ∗ωy,500νy2ω),4σω2kCDkωy2]}4) F_1 = \tanh\left( \left\{ \min\left[ \max\left(\frac{\sqrt{k}}{\beta^* \omega y}, \frac{500\nu}{y^2 \omega}\right), \frac{4\sigma_{\omega 2} k}{CD_{k\omega} y^2} \right] \right\}^4 \right) F1=tanh {min[max(β∗ωyk,y2ω500ν),CDkωy24σω2k]}4
其中,CDkω=max(2σω21ω∂k∂xj∂ω∂xj,10−10)CD_{k\omega} = \max\left(2\sigma_{\omega 2}\frac{1}{\omega}\frac{\partial k}{\partial x_j}\frac{\partial \omega}{\partial x_j}, 10^{-10}\right)CDkω=max(2σω2ω1∂xj∂k∂xj∂ω,10−10)。
外层函数:
F2=tanh([max(2kβ∗ωy,500νy2ω)]2) F_2 = \tanh\left( \left[ \max\left(\frac{2\sqrt{k}}{\beta^* \omega y}, \frac{500\nu}{y^2 \omega}\right) \right]^2 \right) F2=tanh [max(β∗ωy2k,y2ω500ν)]2
9.4 模型常数
模型常数通过混合函数加权:
ϕ=F1ϕ1+(1−F1)ϕ2 \phi = F_1 \phi_1 + (1 - F_1) \phi_2 ϕ=F1ϕ1+(1−F1)ϕ2
其中,ϕ1\phi_1ϕ1是k-ω模型的常数,ϕ2\phi_2ϕ2是k-ε模型的常数。
| 常数 | 内层(1) | 外层(2) |
|---|---|---|
| α\alphaα | 5/9 | 0.44 |
| β\betaβ | 3/40 | 0.0828 |
| β∗\beta^*β∗ | 9/100 | 9/100 |
| σk\sigma_kσk | 0.85 | 1.0 |
| σω\sigma_\omegaσω | 0.5 | 0.856 |
9.5 剪切应力限制器
SST模型引入了Bradshaw假设,限制剪切应力与湍动能的关系:
τxy=ρa1k,a1=0.31 \tau_{xy} = \rho a_1 k, \quad a_1 = 0.31 τxy=ρa1k,a1=0.31
这通过修改涡粘系数实现:
νt=a1kmax(a1ω,SF2) \nu_t = \frac{a_1 k}{\max(a_1 \omega, S F_2)} νt=max(a1ω,SF2)a1k
9.6 SST k-ω模型的特点
优点:
- 对逆压梯度流动和分离流预测优秀
- 可以积分到壁面
- 对翼型和航空应用特别成功
- 对自由流值不敏感
- 在广泛流动中表现一致
缺点:
- 计算成本略高于标准k-ε模型
- 需要计算到壁面的网格
- 对复杂三维流动可能需要验证
10. 雷诺应力模型(RSM)
10.1 模型思想
雷诺应力模型(Reynolds Stress Model,RSM)也称为二阶矩封闭模型,直接求解雷诺应力的输运方程,而不是基于涡粘假设。这种方法理论上更精确,能够捕捉湍流的各向异性效应。
10.2 雷诺应力输运方程
雷诺应力的精确输运方程为:
∂ui′uj′‾∂t+uˉk∂ui′uj′‾∂xk=Pij+Dij−εij+Πij+Ωij \frac{\partial \overline{u_i' u_j'}}{\partial t} + \bar{u}_k \frac{\partial \overline{u_i' u_j'}}{\partial x_k} = P_{ij} + D_{ij} - \varepsilon_{ij} + \Pi_{ij} + \Omega_{ij} ∂t∂ui′uj′+uˉk∂xk∂ui′uj′=Pij+Dij−εij+Πij+Ωij
各项的物理意义:
生成项:
Pij=−(ui′uk′‾∂uˉj∂xk+uj′uk′‾∂uˉi∂xk) P_{ij} = -\left( \overline{u_i' u_k'} \frac{\partial \bar{u}_j}{\partial x_k} + \overline{u_j' u_k'} \frac{\partial \bar{u}_i}{\partial x_k} \right) Pij=−(ui′uk′∂xk∂uˉj+uj′uk′∂xk∂uˉi)
扩散项:
Dij=−∂∂xk(ui′uj′uk′‾+1ρp′(ui′δjk+uj′δik)‾−ν∂ui′uj′‾∂xk) D_{ij} = -\frac{\partial}{\partial x_k} \left( \overline{u_i' u_j' u_k'} + \frac{1}{\rho}\overline{p'(u_i' \delta_{jk} + u_j' \delta_{ik})} - \nu \frac{\partial \overline{u_i' u_j'}}{\partial x_k} \right) Dij=−∂xk∂(ui′uj′uk′+ρ1p′(ui′δjk+uj′δik)−ν∂xk∂ui′uj′)
耗散项:
εij=2ν∂ui′∂xk∂uj′∂xk‾ \varepsilon_{ij} = 2\nu \overline{\frac{\partial u_i'}{\partial x_k} \frac{\partial u_j'}{\partial x_k}} εij=2ν∂xk∂ui′∂xk∂uj′
压力-应变项:
Πij=1ρp′(∂ui′∂xj+∂uj′∂xi)‾ \Pi_{ij} = \frac{1}{\rho} \overline{p' \left( \frac{\partial u_i'}{\partial x_j} + \frac{\partial u_j'}{\partial x_i} \right)} Πij=ρ1p′(∂xj∂ui′+∂xi∂uj′)
旋转项:
Ωij=−2Ωk(uj′um′‾eikm+ui′um′‾ejkm) \Omega_{ij} = -2\Omega_k \left( \overline{u_j' u_m'} e_{ikm} + \overline{u_i' u_m'} e_{jkm} \right) Ωij=−2Ωk(uj′um′eikm+ui′um′ejkm)
10.3 封闭模型
RSM需要模型化扩散项、耗散项和压力-应变项。
扩散项模型化:
Dij=∂∂xk(Cskεuk′ul′‾∂ui′uj′‾∂xl+ν∂ui′uj′‾∂xk) D_{ij} = \frac{\partial}{\partial x_k} \left( C_s \frac{k}{\varepsilon} \overline{u_k' u_l'} \frac{\partial \overline{u_i' u_j'}}{\partial x_l} + \nu \frac{\partial \overline{u_i' u_j'}}{\partial x_k} \right) Dij=∂xk∂(Csεkuk′ul′∂xl∂ui′uj′+ν∂xk∂ui′uj′)
耗散项模型化:
对于高雷诺数流动:
εij=23εδij \varepsilon_{ij} = \frac{2}{3} \varepsilon \delta_{ij} εij=32εδij
压力-应变项模型化(LRR模型):
Πij=−C1εk(ui′uj′‾−23kδij)−C2(Pij−23Pkδij) \Pi_{ij} = -C_1 \frac{\varepsilon}{k} \left( \overline{u_i' u_j'} - \frac{2}{3}k\delta_{ij} \right) - C_2 (P_{ij} - \frac{2}{3}P_k\delta_{ij}) Πij=−C1kε(ui′uj′−32kδij)−C2(Pij−32Pkδij)
其中,C1=1.8C_1 = 1.8C1=1.8,C2=0.6C_2 = 0.6C2=0.6。
10.4 尺度方程
RSM还需要求解湍动能和耗散率的输运方程来确定湍流时间尺度:
∂k∂t+uˉj∂k∂xj=12Pii−ε+∂∂xj(Ckkεuj′uk′‾∂k∂xk) \frac{\partial k}{\partial t} + \bar{u}_j \frac{\partial k}{\partial x_j} = \frac{1}{2}P_{ii} - \varepsilon + \frac{\partial}{\partial x_j} \left( C_k \frac{k}{\varepsilon} \overline{u_j' u_k'} \frac{\partial k}{\partial x_k} \right) ∂t∂k+uˉj∂xj∂k=21Pii−ε+∂xj∂(Ckεkuj′uk′∂xk∂k)
∂ε∂t+uˉj∂ε∂xj=Cε1Pkεk−Cε2ε2k+∂∂xj(Cεkεuj′uk′‾∂ε∂xk) \frac{\partial \varepsilon}{\partial t} + \bar{u}_j \frac{\partial \varepsilon}{\partial x_j} = C_{\varepsilon 1} \frac{P_k \varepsilon}{k} - C_{\varepsilon 2} \frac{\varepsilon^2}{k} + \frac{\partial}{\partial x_j} \left( C_\varepsilon \frac{k}{\varepsilon} \overline{u_j' u_k'} \frac{\partial \varepsilon}{\partial x_k} \right) ∂t∂ε+uˉj∂xj∂ε=Cε1kPkε−Cε2kε2+∂xj∂(Cεεkuj′uk′∂xk∂ε)
10.5 雷诺应力模型的特点
优点:
- 自动考虑湍流各向异性
- 对强旋流、曲率效应、浮力效应预测更好
- 理论上更严格,适用范围更广
- 对二次流和复杂三维流动预测改进
缺点:
- 计算成本高(7个额外的输运方程)
- 数值稳定性较差,收敛困难
- 模型常数多,标定复杂
- 对简单流动优势不明显
11. 非线性涡粘模型
11.1 模型思想
非线性涡粘模型(Nonlinear Eddy Viscosity Models,NLEVM)在Boussinesq线性涡粘假设基础上,引入应变率和旋转张量的高阶项,以捕捉湍流的各向异性效应。
11.2 应力-应变关系
非线性涡粘模型的一般形式为:
ui′uj′‾=23kδij−2νtSij+∑n=1Nfn(Sij,Ωij) \overline{u_i' u_j'} = \frac{2}{3}k\delta_{ij} - 2\nu_t S_{ij} + \sum_{n=1}^{N} f_n(S_{ij}, \Omega_{ij}) ui′uj′=32kδij−2νtSij+n=1∑Nfn(Sij,Ωij)
其中,Sij=12(∂uˉi∂xj+∂uˉj∂xi)S_{ij} = \frac{1}{2}(\frac{\partial \bar{u}_i}{\partial x_j} + \frac{\partial \bar{u}_j}{\partial x_i})Sij=21(∂xj∂uˉi+∂xi∂uˉj)是应变率张量,Ωij=12(∂uˉi∂xj−∂uˉj∂xi)\Omega_{ij} = \frac{1}{2}(\frac{\partial \bar{u}_i}{\partial x_j} - \frac{\partial \bar{u}_j}{\partial x_i})Ωij=21(∂xj∂uˉi−∂xi∂uˉj)是旋转张量。
11.3 二次模型
Speziale提出的二次非线性模型:
ui′uj′‾=23kδij−2νtSij+C1k3ε2(SikSkj−13SklSklδij)+C2k3ε2(SikΩkj+SjkΩki) \overline{u_i' u_j'} = \frac{2}{3}k\delta_{ij} - 2\nu_t S_{ij} + C_1 \frac{k^3}{\varepsilon^2} (S_{ik}S_{kj} - \frac{1}{3}S_{kl}S_{kl}\delta_{ij}) + C_2 \frac{k^3}{\varepsilon^2} (S_{ik}\Omega_{kj} + S_{jk}\Omega_{ki}) ui′uj′=32kδij−2νtSij+C1ε2k3(SikSkj−31SklSklδij)+C2ε2k3(SikΩkj+SjkΩki)
11.4 三次模型
Craft等人提出的三次模型包含更多非线性项:
ui′uj′‾=23kδij−2νtSij+∑n=15CnTij(n) \overline{u_i' u_j'} = \frac{2}{3}k\delta_{ij} - 2\nu_t S_{ij} + \sum_{n=1}^{5} C_n T_{ij}^{(n)} ui′uj′=32kδij−2νtSij+n=1∑5CnTij(n)
其中,Tij(n)T_{ij}^{(n)}Tij(n)是应变率和旋转张量的各种组合。
11.5 显式代数应力模型(EASM)
EASM将雷诺应力模型中的对流和扩散项模型化,得到显式的应力-应变关系:
ui′uj′‾=k(23δij+∑λαλβλTij(λ)) \overline{u_i' u_j'} = k \left( \frac{2}{3}\delta_{ij} + \sum_{\lambda} \frac{\alpha_\lambda}{\beta_\lambda} T_{ij}^{(\lambda)} \right) ui′uj′=k(32δij+λ∑βλαλTij(λ))
其中,系数αλ\alpha_\lambdaαλ和βλ\beta_\lambdaβλ是应变率和旋转张量不变量的函数。
11.6 非线性涡粘模型的特点
优点:
- 计算成本低于RSM
- 能捕捉湍流各向异性的主要效应
- 对二次流和分离流预测改进
- 数值稳定性比RSM好
缺点:
- 模型复杂,常数标定困难
- 对某些流动的预测仍不如RSM
- 理论严格性不如RSM
12. RANS模型在结构风工程中的应用
12.1 建筑物风荷载分析
RANS模型广泛用于计算建筑物表面的风压分布。对于规则形状的建筑物,稳态RANS计算可以提供平均风压系数,用于结构设计。
应用流程:
- 建立几何模型和计算域
- 生成合适的计算网格(重点关注壁面和分离区)
- 选择湍流模型(通常SST k-ω或Realizable k-ε)
- 设置边界条件(入口速度剖面、出口压力、壁面无滑移)
- 进行稳态计算直至收敛
- 提取表面风压系数分布
- 计算等效静力风荷载
注意事项:
- RANS模型主要提供平均风压,脉动风压需要结合湍流强度估计
- 对强分离流动(如钝体绕流),RANS可能低估脉动分量
- 对于重要工程,建议结合风洞试验或LES验证
12.2 风环境评估
在城市规划和建筑设计中,需要评估行人高度的风环境舒适性。RANS模型可以计算建筑群周围的平均风速分布。
评估指标:
- 行人高度(1.5-2.0m)的风速比
- 风环境舒适度等级
- 风加速区域识别
湍流模型选择:
- 标准k-ε模型:计算快,适合初步评估
- RNG k-ε模型:对复杂建筑群预测更好
- SST k-ω模型:对分离流和尾流区预测更准确
12.3 桥梁风荷载
大跨度桥梁的风荷载分析是RANS模型的重要应用。主要关注:
- 主梁断面表面风压分布
- 静力三分力系数(阻力、升力、力矩)
- 桥面风环境
计算策略:
- 采用二维断面计算获取静力系数
- 结合抖振理论计算动力响应
- 对于颤振分析,需要结合CFD与结构动力学
12.4 冷却塔和烟囱
大型冷却塔和烟囱等高耸结构的风荷载分析需要考虑:
- 结构表面的风压分布
- 尾流区的涡脱落效应
- 群体效应(多塔干扰)
RANS模型的局限性:
- 稳态RANS无法捕捉涡脱落的非定常特性
- 对脉动风压的预测不足
- 建议采用非定常RANS(URANS)或DES/LES方法
13. RANS模型的选择指南
13.1 模型选择原则
选择合适的RANS模型需要考虑以下因素:
-
流动特性:
- 是否存在分离流
- 逆压梯度的大小
- 旋转或曲率效应
- 自由剪切层还是壁面约束流
-
计算资源:
- 网格规模
- 计算时间限制
- 精度要求
-
验证数据:
- 是否有实验数据验证
- 模型在类似流动中的应用经验
13.2 不同流动的模型推荐
| 流动类型 | 推荐模型 | 备选模型 |
|---|---|---|
| 简单边界层 | 标准k-ε | SST k-ω |
| 逆压梯度分离流 | SST k-ω | Realizable k-ε |
| 旋转机械 | SST k-ω | RNG k-ε |
| 强旋流/曲率流 | RSM | SST k-ω |
| 射流流动 | Realizable k-ε | RNG k-ε |
| 复杂三维流动 | SST k-ω | RSM |
| 航空翼型 | SST k-ω | k-ω |
13.3 工程实践建议
-
从简单模型开始:
- 先用标准k-ε模型进行初步计算
- 评估流动特性,识别关键区域
-
网格敏感性分析:
- 检查近壁面y+值
- 确保分离区和尾流区网格足够密
-
模型验证:
- 与实验数据对比
- 评估不同模型的预测差异
-
结合多种方法:
- RANS用于初步设计和参数研究
- LES/DES用于详细分析和验证
- 风洞试验用于最终确认
14. RANS模型的局限性与发展趋势
14.1 主要局限性
-
无法捕捉大尺度非定常结构:
- 涡脱落的周期性
- 大尺度相干结构
- 湍流的瞬态特性
-
对分离流的预测不足:
- 分离点位置偏差
- 再附长度预测不准
- 脉动分量低估
-
模型常数的普适性问题:
- 不同流动需要调整常数
- 缺乏严格的物理基础
-
各向同性假设的局限:
- 涡粘假设忽略了湍流各向异性
- 对强旋流和曲率效应预测不足
14.2 改进方向
-
混合RANS-LES方法:
- DES(Detached Eddy Simulation)
- DDES(Delayed DES)
- IDDES(Improved DDES)
- 在壁面区用RANS,在分离区用LES
-
非定常RANS(URANS):
- 捕捉周期性流动特征
- 计算成本低于LES
- 对涡脱落流动有一定改善
-
机器学习辅助模型:
- 数据驱动的湍流模型
- 基于DNS/LES数据的模型训练
- 提高模型的适应性和精度
-
壁面模型LES:
- 减少近壁面网格需求
- 结合RANS壁面模型与LES外区
15. Python仿真案例
15.1 案例一:平板边界层流动模拟
本案例使用简化的RANS方法模拟平板边界层发展,比较不同湍流模型的效果。
"""
平板边界层流动的RANS模拟
使用简化的涡粘模型求解边界层发展
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import matplotlib
matplotlib.use('Agg')
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
class BoundaryLayerRANS:
"""
平板边界层RANS求解器
使用积分方法求解边界层发展
"""
def __init__(self, U_inf, nu, L, Nx=200):
"""
初始化求解器
参数:
U_inf: 自由流速度 [m/s]
nu: 运动粘度 [m^2/s]
L: 平板长度 [m]
Nx: 流向网格数
"""
self.U_inf = U_inf
self.nu = nu
self.L = L
self.Nx = Nx
# 流向网格
self.x = np.linspace(0.001, L, Nx) # 从0.001开始避免奇点
# 雷诺数
self.Re_L = U_inf * L / nu
def blasius_solution(self, eta_max=10, N=100):
"""
Blasius方程数值解(层流边界层)
参数:
eta_max: 相似变量最大值
N: 网格数
返回:
eta, f, f', f''
"""
eta = np.linspace(0, eta_max, N)
# Blasius方程: f''' + 0.5*f*f'' = 0
# 转化为方程组:
# y0' = y1 (f' = u)
# y1' = y2 (f'' = du/deta)
# y2' = -0.5*y0*y2
def blasius_ode(y, eta):
return [y[1], y[2], -0.5*y[0]*y[2]]
# 边界条件: f(0)=0, f'(0)=0, f'(inf)=1
# 使用打靶法求解 f''(0)
def shoot(s):
y0 = [0, 0, s]
sol = odeint(blasius_ode, y0, eta)
return sol[-1, 1] - 1 # f'(inf) - 1 = 0
# 二分法求解
s_low, s_high = 0.1, 1.0
while abs(s_high - s_low) > 1e-6:
s_mid = (s_low + s_high) / 2
if shoot(s_low) * shoot(s_mid) < 0:
s_high = s_mid
else:
s_low = s_mid
s_optimal = (s_low + s_high) / 2
y0 = [0, 0, s_optimal]
sol = odeint(blasius_ode, y0, eta)
return eta, sol[:, 0], sol[:, 1], sol[:, 2]
def turbulent_velocity_profile(self, y_delta, Re_theta, model='mixing_length'):
"""
湍流边界层速度剖面
参数:
y_delta: 无量纲高度 y/δ
Re_theta: 动量厚度雷诺数
model: 湍流模型 ('mixing_length', 'k_epsilon')
返回:
u_Uinf: 无量纲速度 u/U_inf
"""
if model == 'mixing_length':
# 混合长度模型 - 使用壁面律
# 内层: u+ = y+ (粘性底层)
# 外层: u+ = (1/κ)ln(y+) + B (对数律)
kappa = 0.41
B = 5.0
# 假设壁面摩擦速度 u_tau
# 对于零压力梯度边界层: Cf ≈ 0.026/Re_theta^0.25
Cf = 0.026 * Re_theta**(-0.25)
u_tau = np.sqrt(Cf / 2) * self.U_inf
# 边界层厚度估计
delta = self.nu * Re_theta / u_tau
y = y_delta * delta
y_plus = y * u_tau / self.nu
u_plus = np.zeros_like(y_plus)
# 粘性底层
mask_viscous = y_plus < 11.6
u_plus[mask_viscous] = y_plus[mask_viscous]
# 对数律层
mask_log = y_plus >= 11.6
u_plus[mask_log] = (1/kappa) * np.log(y_plus[mask_log]) + B
# 尾流律修正
# Coles尾流函数
Pi = 0.55 # 尾流强度参数
wake = (2/kappa) * np.sin(np.pi/2 * y_delta)**2
u_plus = u_plus + Pi * wake
# 限制最大速度
u_plus = np.minimum(u_plus, self.U_inf / u_tau)
return u_plus * u_tau / self.U_inf
elif model == 'power_law':
# 幂律速度剖面
n = 7 # 幂律指数 (随Re变化)
if Re_theta > 10000:
n = 8
elif Re_theta > 100000:
n = 9
return y_delta**(1/n)
else:
raise ValueError(f"未知模型: {model}")
def calculate_boundary_layer_params(self, model='mixing_length'):
"""
计算边界层参数沿平板的发展
参数:
model: 湍流模型
返回:
delta, delta_star, theta, Cf: 边界层厚度、位移厚度、动量厚度、摩擦系数
"""
delta = np.zeros(self.Nx)
delta_star = np.zeros(self.Nx)
theta = np.zeros(self.Nx)
Cf = np.zeros(self.Nx)
for i, x in enumerate(self.x):
Re_x = self.U_inf * x / self.nu
if Re_x < 5e5: # 层流
# Blasius解
delta[i] = 5.0 * x / np.sqrt(Re_x)
delta_star[i] = 1.72 * x / np.sqrt(Re_x)
theta[i] = 0.664 * x / np.sqrt(Re_x)
Cf[i] = 0.664 / np.sqrt(Re_x)
else: # 湍流
# 经验公式 (基于1/7幂律)
delta[i] = 0.37 * x / (Re_x**0.2)
delta_star[i] = 0.046 * x / (Re_x**0.2)
theta[i] = 0.036 * x / (Re_x**0.2)
Cf[i] = 0.026 / (Re_x**0.2)
return delta, delta_star, theta, Cf
def compare_velocity_profiles(self):
"""
比较不同湍流模型的速度剖面
"""
fig, axes = plt.subplots(2, 2, figsize=(14, 12))
# 1. 层流Blasius解
ax1 = axes[0, 0]
eta, f, fp, fpp = self.blasius_solution()
ax1.plot(fp, eta, 'b-', linewidth=2, label='Blasius解')
ax1.set_xlabel('u/U_∞', fontsize=11)
ax1.set_ylabel('η = y√(U_∞/νx)', fontsize=11)
ax1.set_title('层流边界层速度剖面 (Blasius解)', fontsize=12)
ax1.grid(True, alpha=0.3)
ax1.legend()
# 2. 湍流速度剖面比较
ax2 = axes[0, 1]
y_delta = np.linspace(0.001, 1, 100)
Re_theta_values = [1000, 5000, 10000]
colors = ['blue', 'green', 'red']
for Re_theta, color in zip(Re_theta_values, colors):
u = self.turbulent_velocity_profile(y_delta, Re_theta, 'mixing_length')
ax2.plot(u, y_delta, color=color, linewidth=2,
label=f'Re_θ = {Re_theta}')
# 幂律剖面
u_power = self.turbulent_velocity_profile(y_delta, 5000, 'power_law')
ax2.plot(u_power, y_delta, 'k--', linewidth=2, label='1/7幂律')
ax2.set_xlabel('u/U_∞', fontsize=11)
ax2.set_ylabel('y/δ', fontsize=11)
ax2.set_title('湍流边界层速度剖面比较', fontsize=12)
ax2.grid(True, alpha=0.3)
ax2.legend()
# 3. 边界层厚度发展
ax3 = axes[1, 0]
delta, delta_star, theta, Cf = self.calculate_boundary_layer_params()
ax3.plot(self.x, delta, 'b-', linewidth=2, label='δ (边界层厚度)')
ax3.plot(self.x, delta_star, 'r--', linewidth=2, label='δ* (位移厚度)')
ax3.plot(self.x, theta, 'g:', linewidth=2, label='θ (动量厚度)')
# 标记转捩点
Re_trans = 5e5
x_trans = Re_trans * self.nu / self.U_inf
ax3.axvline(x=x_trans, color='k', linestyle='-.', alpha=0.5, label='转捩点')
ax3.set_xlabel('x [m]', fontsize=11)
ax3.set_ylabel('厚度 [m]', fontsize=11)
ax3.set_title('边界层厚度沿平板发展', fontsize=12)
ax3.grid(True, alpha=0.3)
ax3.legend()
# 4. 壁面摩擦系数
ax4 = axes[1, 1]
# 层流理论
Re_x_lam = np.linspace(1e4, 5e5, 100)
Cf_lam = 0.664 / np.sqrt(Re_x_lam)
# 湍流经验公式
Re_x_turb = np.linspace(5e5, self.Re_L, 100)
Cf_turb = 0.026 / (Re_x_turb**0.2)
ax4.semilogy(Re_x_lam, Cf_lam, 'b-', linewidth=2, label='层流 (Blasius)')
ax4.semilogy(Re_x_turb, Cf_turb, 'r-', linewidth=2, label='湍流 (经验公式)')
# 计算结果
Re_x_calc = self.U_inf * self.x / self.nu
ax4.semilogy(Re_x_calc, Cf, 'g--', linewidth=2, alpha=0.7, label='混合计算')
ax4.axvline(x=5e5, color='k', linestyle='-.', alpha=0.5)
ax4.set_xlabel('Re_x', fontsize=11)
ax4.set_ylabel('C_f', fontsize=11)
ax4.set_title('壁面摩擦系数', fontsize=12)
ax4.grid(True, alpha=0.3)
ax4.legend()
plt.tight_layout()
plt.savefig('boundary_layer_rans.png', dpi=150, bbox_inches='tight')
plt.close()
print("边界层RANS分析图已保存为 'boundary_layer_rans.png'")
def analyze_turbulence_models(self):
"""
分析不同湍流模型的边界层特性
"""
fig, axes = plt.subplots(2, 2, figsize=(14, 12))
# 计算位置
x_eval = self.L / 2
Re_x = self.U_inf * x_eval / self.nu
# 1. 不同模型的速度剖面
ax1 = axes[0, 0]
y_delta = np.linspace(0.001, 1, 100)
# 混合长度模型
Re_theta = 5000
u_ml = self.turbulent_velocity_profile(y_delta, Re_theta, 'mixing_length')
ax1.plot(u_ml, y_delta, 'b-', linewidth=2, label='混合长度模型')
# 幂律模型
u_pl = self.turbulent_velocity_profile(y_delta, Re_theta, 'power_law')
ax1.plot(u_pl, y_delta, 'r--', linewidth=2, label='1/7幂律')
ax1.set_xlabel('u/U_∞', fontsize=11)
ax1.set_ylabel('y/δ', fontsize=11)
ax1.set_title(f'湍流模型速度剖面比较 (Re_x={Re_x:.2e})', fontsize=12)
ax1.grid(True, alpha=0.3)
ax1.legend()
# 2. 形状因子比较
ax2 = axes[0, 1]
Re_range = np.logspace(4, 7, 100)
# 层流形状因子
H_lam = np.ones_like(Re_range) * 2.59 # Blasius解
# 湍流形状因子 (经验公式)
H_turb = 1.3 + 0.5 * (Re_range/1e6)**(-0.1)
H_turb = np.clip(H_turb, 1.28, 1.6)
ax2.semilogx(Re_range, H_lam, 'b-', linewidth=2, label='层流 (H=2.59)')
ax2.semilogx(Re_range, H_turb, 'r-', linewidth=2, label='湍流 (经验)')
ax2.axvline(x=5e5, color='k', linestyle='-.', alpha=0.5, label='转捩')
ax2.set_xlabel('Re_x', fontsize=11)
ax2.set_ylabel('形状因子 H', fontsize=11)
ax2.set_title('边界层形状因子', fontsize=12)
ax2.grid(True, alpha=0.3)
ax2.legend()
ax2.set_ylim([1.2, 3.0])
# 3. 动量厚度雷诺数发展
ax3 = axes[1, 0]
_, _, theta, _ = self.calculate_boundary_layer_params()
Re_theta_calc = self.U_inf * theta / self.nu
ax3.semilogy(self.x, Re_theta_calc, 'b-', linewidth=2)
ax3.axvline(x=5e5*self.nu/self.U_inf, color='k', linestyle='-.', alpha=0.5, label='转捩点')
ax3.set_xlabel('x [m]', fontsize=11)
ax3.set_ylabel('Re_θ', fontsize=11)
ax3.set_title('动量厚度雷诺数发展', fontsize=12)
ax3.grid(True, alpha=0.3)
ax3.legend()
# 4. 湍流模型特性对比
ax4 = axes[1, 1]
models = ['零方程\\n(混合长度)', '标准k-ε', 'RNG k-ε', 'Realizable\\nk-ε', 'SST k-ω', 'RSM']
accuracy = [3, 6, 7, 7.5, 8.5, 9] # 分离流预测精度
cost = [2, 4, 4.5, 5, 5.5, 9] # 计算成本
x_pos = np.arange(len(models))
width = 0.35
bars1 = ax4.bar(x_pos - width/2, accuracy, width, label='分离流预测精度', color='steelblue')
bars2 = ax4.bar(x_pos + width/2, cost, width, label='计算成本', color='coral')
ax4.set_ylabel('评分 (1-10)', fontsize=11)
ax4.set_title('湍流模型特性对比', fontsize=12)
ax4.set_xticks(x_pos)
ax4.set_xticklabels(models, fontsize=9)
ax4.legend()
ax4.grid(True, alpha=0.3, axis='y')
# 添加数值标签
for bar in bars1:
height = bar.get_height()
ax4.annotate(f'{height:.1f}',
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3),
textcoords="offset points",
ha='center', va='bottom', fontsize=8)
for bar in bars2:
height = bar.get_height()
ax4.annotate(f'{height:.1f}',
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3),
textcoords="offset points",
ha='center', va='bottom', fontsize=8)
plt.tight_layout()
plt.savefig('turbulence_model_analysis.png', dpi=150, bbox_inches='tight')
plt.close()
print("湍流模型分析图已保存为 'turbulence_model_analysis.png'")
# 运行分析
if __name__ == "__main__":
# 创建求解器实例
solver = BoundaryLayerRANS(U_inf=10.0, nu=1.5e-5, L=5.0, Nx=200)
print("=" * 60)
print("平板边界层RANS模拟分析")
print("=" * 60)
print(f"自由流速度: {solver.U_inf} m/s")
print(f"运动粘度: {solver.nu} m²/s")
print(f"平板长度: {solver.L} m")
print(f"雷诺数: Re_L = {solver.Re_L:.2e}")
print("=" * 60)
# 边界层分析
solver.compare_velocity_profiles()
# 湍流模型分析
solver.analyze_turbulence_models()
print("\n分析完成!")
15.2 案例二:方柱绕流RANS模拟
本案例使用简化的RANS方法模拟方柱绕流,比较不同湍流模型对分离流和阻力的预测。
"""
方柱绕流的简化RANS模拟
使用涡粘模型模拟湍流效应
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy.sparse import diags
from scipy.sparse.linalg import spsolve
import matplotlib
matplotlib.use('Agg')
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
class SquareCylinderRANS:
"""
方柱绕流RANS求解器(简化模型)
基于势流理论修正+涡粘模型
"""
def __init__(self, D=1.0, U_inf=1.0, Re=1e4, turbulence_model='k_epsilon'):
"""
初始化求解器
参数:
D: 方柱边长
U_inf: 来流速度
Re: 雷诺数
turbulence_model: 湍流模型类型
"""
self.D = D
self.U_inf = U_inf
self.Re = Re
self.turbulence_model = turbulence_model
# 计算域
self.Lx = 20 * D
self.Ly = 10 * D
# 网格参数
self.Nx = 200
self.Ny = 100
self.dx = self.Lx / (self.Nx - 1)
self.dy = self.Ly / (self.Ny - 1)
# 方柱位置
self.cylinder_x = 5 * D
self.cylinder_y = self.Ly / 2
# 初始化场
self.u = np.ones((self.Nx, self.Ny)) * U_inf
self.v = np.zeros((self.Nx, self.Ny))
self.p = np.zeros((self.Nx, self.Ny))
self.k = np.ones((self.Nx, self.Ny)) * 0.001 * U_inf**2
self.epsilon = np.ones((self.Nx, self.Ny)) * 0.001 * U_inf**3 / D
# 标记方柱区域
self.create_cylinder_mask()
def create_cylinder_mask(self):
"""
创建方柱掩码
"""
self.cylinder_mask = np.zeros((self.Nx, self.Ny), dtype=bool)
for i in range(self.Nx):
for j in range(self.Ny):
x = i * self.dx
y = j * self.dy
if (abs(x - self.cylinder_x) <= self.D/2 and
abs(y - self.cylinder_y) <= self.D/2):
self.cylinder_mask[i, j] = True
# 在方柱内部设置速度为零
self.u[self.cylinder_mask] = 0
self.v[self.cylinder_mask] = 0
def calculate_nu_t(self):
"""
计算湍流涡粘系数
"""
if self.turbulence_model == 'k_epsilon':
# 标准k-ε模型
C_mu = 0.09
nu_t = C_mu * self.k**2 / (self.epsilon + 1e-10)
elif self.turbulence_model == 'mixing_length':
# 混合长度模型
# 计算涡量
dvdx = np.gradient(self.v, self.dx, axis=0)
dudy = np.gradient(self.u, self.dy, axis=1)
omega = np.abs(dudy - dvdx)
# 混合长度
lm = 0.09 * self.D # 简化处理
nu_t = lm**2 * omega
else:
# 常数涡粘模型
nu_t = np.ones_like(self.u) * 0.01 * self.U_inf * self.D
return np.clip(nu_t, 0, 10 * self.U_inf * self.D)
def solve_potential_flow(self, iterations=1000):
"""
求解势流场(简化模型)
使用迭代方法求解速度场
"""
nu_t = self.calculate_nu_t()
nu_eff = 1.5e-5 / (self.U_inf * self.D) + nu_t # 无量纲有效粘度
for _ in range(iterations):
u_old = self.u.copy()
v_old = self.v.copy()
# 内部点更新(不包括边界和方柱)
for i in range(1, self.Nx-1):
for j in range(1, self.Ny-1):
if self.cylinder_mask[i, j]:
continue
# 简化的速度更新(考虑对流和扩散)
# 使用迎风格式处理对流项
if u_old[i,j] > 0:
dudx = (u_old[i,j] - u_old[i-1,j]) / self.dx
dvdx = (v_old[i,j] - v_old[i-1,j]) / self.dx
else:
dudx = (u_old[i+1,j] - u_old[i,j]) / self.dx
dvdx = (v_old[i+1,j] - v_old[i,j]) / self.dx
if v_old[i,j] > 0:
dudy = (u_old[i,j] - u_old[i,j-1]) / self.dy
dvdy = (v_old[i,j] - v_old[i,j-1]) / self.dy
else:
dudy = (u_old[i,j+1] - u_old[i,j]) / self.dy
dvdy = (v_old[i,j+1] - v_old[i,j]) / self.dy
# 扩散项(Laplacian)
d2udx2 = (u_old[i+1,j] - 2*u_old[i,j] + u_old[i-1,j]) / self.dx**2
d2udy2 = (u_old[i,j+1] - 2*u_old[i,j] + u_old[i,j-1]) / self.dy**2
d2vdx2 = (v_old[i+1,j] - 2*v_old[i,j] + v_old[i-1,j]) / self.dx**2
d2vdy2 = (v_old[i,j+1] - 2*v_old[i,j] + v_old[i,j-1]) / self.dy**2
# 更新速度(松弛迭代)
omega_relax = 0.1
self.u[i,j] = (1-omega_relax) * u_old[i,j] + omega_relax * (
u_old[i,j] - 0.1 * (u_old[i,j]*dudx + v_old[i,j]*dudy -
nu_eff[i,j] * (d2udx2 + d2udy2))
)
self.v[i,j] = (1-omega_relax) * v_old[i,j] + omega_relax * (
v_old[i,j] - 0.1 * (u_old[i,j]*dvdx + v_old[i,j]*dvdy -
nu_eff[i,j] * (d2vdx2 + d2vdy2))
)
# 应用边界条件
self.apply_boundary_conditions()
def apply_boundary_conditions(self):
"""
应用边界条件
"""
# 入口:均匀来流
self.u[0, :] = self.U_inf
self.v[0, :] = 0
# 出口:零梯度
self.u[-1, :] = self.u[-2, :]
self.v[-1, :] = self.v[-2, :]
# 上下边界:对称或自由滑移
self.u[:, 0] = self.u[:, 1]
self.v[:, 0] = 0
self.u[:, -1] = self.u[:, -2]
self.v[:, -1] = 0
# 方柱表面:无滑移
self.u[self.cylinder_mask] = 0
self.v[self.cylinder_mask] = 0
def calculate_pressure_coefficient(self):
"""
计算压力系数分布
"""
# 基于速度计算压力(伯努利方程简化)
velocity_magnitude = np.sqrt(self.u**2 + self.v**2)
Cp = 1 - (velocity_magnitude / self.U_inf)**2
return Cp
def calculate_drag_lift_coefficients(self):
"""
计算阻力系数和升力系数(简化估算)
"""
Cp = self.calculate_pressure_coefficient()
# 提取方柱表面的压力系数
# 前表面
front_mask = np.zeros_like(self.cylinder_mask)
i_front = int(self.cylinder_x / self.dx - self.D/2/self.dx)
j_min = int((self.cylinder_y - self.D/2) / self.dy)
j_max = int((self.cylinder_y + self.D/2) / self.dy)
front_mask[i_front, j_min:j_max] = True
# 后表面
back_mask = np.zeros_like(self.cylinder_mask)
i_back = int(self.cylinder_x / self.dx + self.D/2/self.dx)
back_mask[i_back, j_min:j_max] = True
# 计算平均压力系数
Cp_front = np.mean(Cp[front_mask]) if np.any(front_mask) else 1.0
Cp_back = np.mean(Cp[back_mask]) if np.any(back_mask) else -0.5
# 阻力系数估算
Cd = (Cp_front - Cp_back) # 简化计算
return Cd, 0.0 # 升力系数在此简化模型中为0
def visualize_results(self):
"""
可视化计算结果
"""
fig, axes = plt.subplots(2, 3, figsize=(16, 10))
# 创建网格
X = np.linspace(0, self.Lx, self.Nx)
Y = np.linspace(0, self.Ly, self.Ny)
X, Y = np.meshgrid(X, Y)
# 1. 速度矢量图
ax1 = axes[0, 0]
skip = 5
ax1.quiver(X[::skip, ::skip], Y[::skip, ::skip],
self.u[::skip, ::skip].T, self.v[::skip, ::skip].T,
scale=20, alpha=0.7)
# 绘制方柱
rect = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax1.add_patch(rect)
ax1.set_xlabel('x [m]', fontsize=10)
ax1.set_ylabel('y [m]', fontsize=10)
ax1.set_title('速度矢量场', fontsize=11)
ax1.set_aspect('equal')
ax1.set_xlim([0, self.Lx])
ax1.set_ylim([0, self.Ly])
# 2. 流线图
ax2 = axes[0, 1]
speed = np.sqrt(self.u.T**2 + self.v.T**2)
strm = ax2.streamplot(X, Y, self.u.T, self.v.T,
color=speed, cmap='viridis', density=2, linewidth=1)
plt.colorbar(strm.lines, ax=ax2, label='速度 [m/s]')
rect2 = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax2.add_patch(rect2)
ax2.set_xlabel('x [m]', fontsize=10)
ax2.set_ylabel('y [m]', fontsize=10)
ax2.set_title('流线图', fontsize=11)
ax2.set_aspect('equal')
# 3. 压力系数分布
ax3 = axes[0, 2]
Cp = self.calculate_pressure_coefficient()
contour = ax3.contourf(X, Y, Cp.T, levels=20, cmap='RdBu_r', vmin=-1.5, vmax=1.5)
plt.colorbar(contour, ax=ax3, label='Cp')
rect3 = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax3.add_patch(rect3)
ax3.set_xlabel('x [m]', fontsize=10)
ax3.set_ylabel('y [m]', fontsize=10)
ax3.set_title('压力系数分布', fontsize=11)
ax3.set_aspect('equal')
# 4. 湍动能分布
ax4 = axes[1, 0]
k_plot = np.log10(self.k.T + 1e-10)
contour_k = ax4.contourf(X, Y, k_plot, levels=20, cmap='hot')
plt.colorbar(contour_k, ax=ax4, label='log₁₀(k)')
rect4 = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax4.add_patch(rect4)
ax4.set_xlabel('x [m]', fontsize=10)
ax4.set_ylabel('y [m]', fontsize=10)
ax4.set_title('湍动能分布 (log尺度)', fontsize=11)
ax4.set_aspect('equal')
# 5. 涡粘系数分布
ax5 = axes[1, 1]
nu_t = self.calculate_nu_t()
contour_nut = ax5.contourf(X, Y, nu_t.T, levels=20, cmap='plasma')
plt.colorbar(contour_nut, ax=ax5, label='νt [m²/s]')
rect5 = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax5.add_patch(rect5)
ax5.set_xlabel('x [m]', fontsize=10)
ax5.set_ylabel('y [m]', fontsize=10)
ax5.set_title('涡粘系数分布', fontsize=11)
ax5.set_aspect('equal')
# 6. 中心线速度分布
ax6 = axes[1, 2]
j_center = int(self.cylinder_y / self.dy)
ax6.plot(X[:, j_center], self.u[:, j_center], 'b-', linewidth=2, label='u/U∞')
ax6.axvline(x=self.cylinder_x - self.D/2, color='r', linestyle='--', alpha=0.5, label='方柱前缘')
ax6.axvline(x=self.cylinder_x + self.D/2, color='r', linestyle='--', alpha=0.5, label='方柱后缘')
ax6.set_xlabel('x [m]', fontsize=10)
ax6.set_ylabel('u/U∞', fontsize=10)
ax6.set_title('中心线速度分布', fontsize=11)
ax6.grid(True, alpha=0.3)
ax6.legend()
plt.tight_layout()
plt.savefig('square_cylinder_rans.png', dpi=150, bbox_inches='tight')
plt.close()
print("方柱绕流RANS分析图已保存为 'square_cylinder_rans.png'")
def compare_turbulence_models(self):
"""
比较不同湍流模型的结果
"""
models = ['constant', 'mixing_length', 'k_epsilon']
model_names = ['常数涡粘', '混合长度', 'k-ε模型']
fig, axes = plt.subplots(2, 3, figsize=(16, 10))
for idx, (model, name) in enumerate(zip(models, model_names)):
self.turbulence_model = model
self.u = np.ones((self.Nx, self.Ny)) * self.U_inf
self.v = np.zeros((self.Nx, self.Ny))
# 求解
self.solve_potential_flow(iterations=500)
X = np.linspace(0, self.Lx, self.Nx)
Y = np.linspace(0, self.Ly, self.Ny)
X, Y = np.meshgrid(X, Y)
# 速度云图
ax = axes[0, idx]
speed = np.sqrt(self.u.T**2 + self.v.T**2)
contour = ax.contourf(X, Y, speed, levels=20, cmap='viridis', vmin=0, vmax=self.U_inf*1.2)
plt.colorbar(contour, ax=ax, label='速度 [m/s]')
rect = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax.add_patch(rect)
ax.set_title(f'{name} - 速度场', fontsize=11)
ax.set_xlabel('x [m]', fontsize=10)
ax.set_ylabel('y [m]', fontsize=10)
ax.set_aspect('equal')
# 压力系数
ax2 = axes[1, idx]
Cp = self.calculate_pressure_coefficient()
contour2 = ax2.contourf(X, Y, Cp.T, levels=20, cmap='RdBu_r', vmin=-1.5, vmax=1.5)
plt.colorbar(contour2, ax=ax2, label='Cp')
rect2 = plt.Rectangle((self.cylinder_x - self.D/2, self.cylinder_y - self.D/2),
self.D, self.D, fill=True, color='gray', alpha=0.8)
ax2.add_patch(rect2)
ax2.set_title(f'{name} - 压力系数', fontsize=11)
ax2.set_xlabel('x [m]', fontsize=10)
ax2.set_ylabel('y [m]', fontsize=10)
ax2.set_aspect('equal')
plt.tight_layout()
plt.savefig('turbulence_model_comparison.png', dpi=150, bbox_inches='tight')
plt.close()
print("湍流模型比较图已保存为 'turbulence_model_comparison.png'")
# 运行分析
if __name__ == "__main__":
print("=" * 60)
print("方柱绕流RANS模拟")
print("=" * 60)
# 创建求解器实例
solver = SquareCylinderRANS(D=1.0, U_inf=10.0, Re=1e4, turbulence_model='k_epsilon')
print(f"方柱边长: {solver.D} m")
print(f"来流速度: {solver.U_inf} m/s")
print(f"雷诺数: Re = {solver.Re:.2e}")
print("=" * 60)
# 求解流场
print("求解流场...")
solver.solve_potential_flow(iterations=1000)
# 计算气动力系数
Cd, Cl = solver.calculate_drag_lift_coefficients()
print(f"\n估算阻力系数: Cd ≈ {Cd:.3f}")
print(f"估算升力系数: Cl ≈ {Cl:.3f}")
print("(注: 简化模型结果,仅供参考)")
# 可视化结果
print("\n生成可视化结果...")
solver.visualize_results()
# 比较不同湍流模型
print("\n比较不同湍流模型...")
solver.compare_turbulence_models()
print("\n分析完成!")
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)