声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 4593|回复: 7

[Python] [系列]Python计算CFD问题

[复制链接]
发表于 2015-10-29 20:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
[系列]Python计算CFD问题<1>:一维线性对流问题
001DKwyezy6QyVQvsFE2e&amp;690.png
001DKwyezy6QyVQzlKs1c&amp;690.png
  1. #-*-coding=utf-8 -*-
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import time,sys

  5. nx=41 #空间节点数
  6. dx=2.0/(nx-1) #网格间距
  7. nt=25 #时间步数
  8. dt=0.025 #时间步长
  9. c=1

  10. #初始化节点
  11. u=np.ones(nx)
  12. u[0.5/dx:1/dx+1]=2
  13. plt.plot(np.linspace(0,2,nx),u,lw=2)

  14. #离散求解
  15. un=np.ones(nx)
  16. for n in range(nt):
  17.     un=u.copy()
  18.     for i in range(1,nx):
  19.         u[i]=un[i]-c*dt/dx*(un[i]-un[i-1])

  20. #显示计算结果
  21. plt.plot(np.linspace(0,2,nx),u,lw=2,color='red')
  22. plt.xlabel("$x$")
  23. plt.ylabel("$u(x)$")
复制代码


显示的计算结果如图所示:
001DKwyezy6QyVQSzIv43&amp;690.png
图中蓝色线条为初始速度分布,红色线条为0.625s(25个时间步,时间步长0.025s)后的速度分布。
利用matplotlib库也很容易制作动画,有兴趣的童鞋可以试着将各时间步上的速度分布以动画的形式输出。
回复
分享到:

使用道具 举报

 楼主| 发表于 2015-10-29 20:55 | 显示全部楼层
[系列]Python计算CFD问题<2>:一维非线性对流问题
001DKwyezy6QyWC0Yfy54&amp;690.png
001DKwyezy6QyWCl8bVfb&amp;690.png
  1. #-*-coding=utf-8 -*-
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import time,sys

  5. nx=41 #空间节点数
  6. dx=2.0/(nx-1) #网格间距
  7. nt=25 #时间步数
  8. dt=0.025 #时间步长
  9. c=1

  10. #初始化节点
  11. u=np.ones(nx)
  12. u[0.5/dx:1/dx+1]=2
  13. plt.plot(np.linspace(0,2,nx),u,lw=2)

  14. #离散求解
  15. un=np.ones(nx)
  16. for n in range(nt):
  17.     un=u.copy()
  18.     for i in range(1,nx):
  19.         u[i]=un[i]-un[i]*dt/dx*(un[i]-un[i-1])

  20. #显示计算结果
  21. plt.plot(np.linspace(0,2,nx),u,lw=2,color='red')
  22. plt.xlabel("$x$")
  23. plt.ylabel("$u(x)$")
复制代码


显示的计算结果如图所示:
001DKwyezy6QyWCp2LZ7f&amp;690.png
图中蓝色线条为初始速度分布,红色线条为0.625s(25个时间步,时间步长0.025s)后的速度分布。
【来源:http://nbviewer.ipython.org/gith ... ons/02_Step_2.ipynb
 楼主| 发表于 2015-10-29 21:00 | 显示全部楼层
本帖最后由 funi 于 2015-10-29 21:09 编辑

[系列]Python计算CFD问题<3>:关于CFL
对于前面的关于1D对流问题,计算过程中,采用的网格数为41,时间步数为25,时间步长为0.025,对于给定的条件,此参数配置能够获得较好的计算结果。那么这些计算参数能否影响最终计算结果?比如说增大或减小网格数量?增大或减小时间步长?下面来测试一下。
我们采用案例1的条件进行测试。修改程序如下:
  1. import numpy as np
  2. import matplotlib.pyplot as plt

  3. def linearconv(nx):
  4. dx=2.0/(nx-1)
  5. nt=20
  6. dt=0.025
  7. c=1

  8. u=np.ones(nx)
  9. u[.5/dx:1/dx+1]=2
  10. un=np.ones(nx)

  11. for n in range(nt):
  12. un=u.copy()
  13. for i in range(1,nx):
  14. u[i]=un[i]-c*dt/dx*(un[i]-un[i-1])
  15. plt.plot(np.linspace(0,2,nx),u,lw=2,color='red')
复制代码


这里函数的形式,以方便后面的比较。这里分别比较nx=41、61、81、101、121时候,ux分布情况。
001DKwyezy6Qz36NV1963&amp;690.png
001DKwyezy6Qz36QOxO18&amp;690.png
001DKwyezy6Qz36TWPr65&amp;690.png
001DKwyezy6Qz37c46e02&amp;690.png
看出问题了没?
随着NX增大,即网格的加密,计算结果似乎越来越离谱了?是不是有点儿颠覆了俺们的常规认识了呢?这就是计算稳定性所导致的问题。为了找到导致突变的网格数,我们从80开始增大nx。从图中可以看出,在nx=80的时候,u(x)的分布是可以接受的,我们从80开始慢慢增加nx。
001DKwyezy6Qz37fXoM44&amp;690.png
001DKwyezy6Qz37hRlt4f&amp;690.png
当nx增大到82时,情况发生突变,说明此处是一个坎儿。
由于计算中采用了固定的时间步长,因此随着网格的加密,空间步长与时间步长的比值将会越来越小。这里定义库朗数:
001DKwyezy6Qz37pWLj65&amp;690.png
式中u为波速,在本例中u=1;σ为库朗数;σmax为所采用的离散算法确保稳定性的值。对于本例采用的离散算法,σmax=1,可以计算得nx最大值为81。
据此,可以修改计算程序,通过库朗数自动调整时间步长,以保证计算过程稳定。
修改后的计算程序为:
  1. #-*- coding=utf-8 -*-
  2. import numpy as np
  3. import matplotlib.pyplot as plt

  4. def linearconv(nx):
  5. dx=2.0/(nx-1)
  6. nt=20
  7. c=1
  8. sigma = 0.5 #库朗数
  9. dt=sigma*dx/c #计算时间步长

  10. u=np.ones(nx)
  11. u[.5/dx:1/dx+1]=2
  12. un=np.ones(nx)

  13. for n in range(nt):
  14. un=u.copy()
  15. for i in range(1,nx):
  16. u[i]=un[i]-c*dt/dx*(un[i]-un[i-1])
  17. plt.plot(np.linspace(0,2,nx),u,lw=2,color='red')
  18. linearconv(80)
复制代码

计算nx超过80后的ux曲线,如图所示。
001DKwyezy6Qz37pWLj65&amp;690.png
001DKwyezy6Qz37roYV19&amp;690.png
001DKwyezy6Qz37udo0e4&amp;690.png
001DKwyezy6Qz37y22347&amp;690.png
001DKwyezy6Qz37yEr8f2&amp;690.png
001DKwyezy6Qz37mf7W48&amp;690.png
从图中可以看出,通过库朗数定义计算时间步长,可以有效的避免计算不稳定情况。上面各图中因为采用的NX不同,所以导致时间步长有差异,在统一的时间步数情况下,最终计算时长存在差异,有感兴趣的童鞋可以通过调整时间步数以使它们的时间点一致。
总结:对于显式非稳态问题,库朗数是控制其计算稳定性的重要参数。减小时间步长或增大网格都有助于计算稳定。
【来源:http://nbviewer.ipython.org/gith ... CFL_Condition.ipynb
 楼主| 发表于 2015-10-29 21:14 | 显示全部楼层
[系列]Python计算CFD问题<4>:一维扩散方程
与对流方程不同,扩散方程是2阶的偏微分方程。一维扩散方程可用下面的方程进行描述:
001DKwyezy6Qz9c4L3yd8&amp;690.png
该方程可以离散为:
001DKwyezy6Qz9c4kEN71&amp;690.png
写成迭代的形式为:
001DKwyezy6Qz9c5PVY0e&amp;690.png
采用与前例相同的初始条件,及0.5<=x<=1时,u=1,其他位置u=2。扩散系数mu=0.3。
程序代码为:
001DKwyezy6Qz9canFc66&amp;690.png
利用函数diffision可查看各时刻速度分布(时间步数分别为0、50、100、150、200、250)。
001DKwyezy6Qz9ccFlAde&amp;690.png
001DKwyezy6Qz9ceMXS30&amp;690.png
001DKwyezy6Qz9ch3X02e&amp;690.png
001DKwyezy6Qz9ci4wmb6&amp;690.png
001DKwyezy6Qz9ciGhrb1&amp;690.png
001DKwyezy6Qz9cm3XE2e&amp;690.png
放到一起看起来可能更直观一些:
001DKwyegy6Qzh30zWZa5&amp;690.png
【来源:hhttp://nbviewer.ipython.org/gith ... ons/04_Step_3.ipynb
 楼主| 发表于 2015-10-29 21:17 | 显示全部楼层
[系列]Python计算CFD问题<5>:一维Burgers方程
一维Burgers方程形式为:
001DKwyezy6QzkcSNzIba&amp;amp.png
从方程形式上来看,该方程是前面的非线性对流方程与扩散方程的混合体。采用前面提到的离散方法,可以将Burgers方程离散成: 001DKwyezy6Qzkd86ya2e&amp;amp.png
将其写成迭代的形式为:
001DKwyezy6Qzkda4Yr73&amp;amp.png
除了迭代形式外,我们还必须知道初始条件和边界条件。
该方程有解析解:
001DKwyezy6QzkdbXC1d9&amp;amp.png
因此本次计算设初始条件为:
001DKwyezy6Qzkde5Jkae&amp;amp.png
设置边界条件为:
001DKwyezy6Qzkde15Bff&amp;amp.png
初始条件中含有偏导项,无法直接赋值,需要采用一些数学化简手段进行处理。
Python中提供了sympy库,该库是一个符号计算库,可以帮助进行化简。
完整的程序如下:
  1. # -*-coding:utf-8 -*-
  2. import numpy as np
  3. import sympy
  4. from sympy.utilities.lambdify import lambdify
  5. import matplotlib.pylab as plt

  6. x,nu,t = sympy.symbols("x,nu,t")
  7. phi = sympy.exp(-(x-4*t)**2/(4*nu*(t+1))) + sympy.exp(-(x-4*t-2*np.pi)**2/(4*nu*(t+1)))
  8. phiprime = phi.diff(x)
  9. u = -2*nu*(phiprime/phi)+4
  10. ufunc = lambdify((t,x,nu),u)

  11. nx = 101
  12. nt=100
  13. dx = 2*np.pi/(nx-1)
  14. nu=0.07
  15. dt=dx*nu

  16. x= np.linspace(0,2*np.pi,nx)
  17. un = np.empty(nx)
  18. t=0
  19. u=np.asarray([ufunc(t,x0,nu) for x0 in x]) #list 转化成 np.array

  20. plt.figure(figsize=(4,4),dpi=100)
  21. plt.plot(x,u,lw=2)
  22. plt.xlim([0,2*np.pi])
  23. plt.ylim([0,8])

  24. for n in range(nt):
  25. un = u.copy()
  26. for i in range(nx-1):
  27. u[i] = un[i] - un[i] * dt/dx *(un[i] - un[i-1]) + nu*dt/dx**2*(un[i+1]-2*un[i]+un[i-1])
  28. u[-1] = un[-1] - un[-1] * dt/dx * (un[-1] - un[-2]) + nu*dt/dx**2*(un[0]-2*un[-1]+un[-2])

  29. u_analytical = np.asarray([ufunc(nt*dt,xi,nu) for xi in x])

  30. plt.figure(figsize=(6,6),dpi=100)
  31. plt.plot(x,u,marker="o",color="blue",lw=2,label='Computational')
  32. plt.plot(x,u_analytical,color="yellow",label='analytical')
  33. plt.xlim([0,2*np.pi])
  34. plt.ylim([0,10])
  35. plt.legend()
  36. plt.show()
复制代码

初始条件如图:
001DKwyezy6QzkdkUdRab&amp;amp.jpg
计算结果如图:
001DKwyezy6QzkdqeHbed&amp;amp.jpg
【来源:http://nbviewer.ipython.org/gith ... ing-Time-with-SymPy
 楼主| 发表于 2015-10-29 21:22 | 显示全部楼层
[系列]Python计算CFD问题<6>:2D线性对流问题
在第一个例子中,我们提到了解一维线性对流问题。在本例中,我们将利用python数值求解二维线性对流问题。
2D线性对流问题可以用此方程进行表达:
001DKwyezy6QznjfBW73f&amp;690.png
时间项采用向前差分,空间项采用先后差分。离散后的方程为:
001DKwyezy6QznjhLUAf8&amp;690.png
换成迭代格式为:
001DKwyezy6Qznjfhma3a&amp;690.png
初始条件为:
001DKwyezy6QznjhvrBb3&amp;690.png
边界条件:
001DKwyezy6QznjtnRQ8e&amp;690 (1).png
编制计算程序为:
  1. from mpl_toolkits.mplot3d import Axes3D ##New Library required for projected 3d plots

  2. import numpy as np
  3. import matplotlib.pyplot as plt

  4. ###variable declarations
  5. nx = 81
  6. ny = 81
  7. nt = 100
  8. c = 1
  9. dx = 2.0/(nx-1)
  10. dy = 2.0/(ny-1)
  11. sigma = .2
  12. dt = sigma*dx

  13. x = np.linspace(0,2,nx)
  14. y = np.linspace(0,2,ny)

  15. u = np.ones((ny,nx)) ##create a 1xn vector of 1's
  16. un = np.ones((ny,nx)) ##

  17. ###Assign initial conditions
  18. u[.5/dy:1/dy+1,.5/dx:1/dx+1]=2
  19. ###Plot Initial Condition
  20. fig = plt.figure(figsize=(11,7), dpi=100)
  21. ax = fig.gca(projection='3d')
  22. X, Y = np.meshgrid(x,y)
  23. surf = ax.plot_surface(X,Y,u[:])

  24. u = np.ones((ny,nx))
  25. u[.5/dy:1/dy+1,.5/dx:1/dx+1]=2

  26. for n in range(nt+1): ##loop across number of time steps
  27. un = u.copy()
  28. for i in range(1, len(u)):
  29. for j in range(1, len(u)):
  30. u[i,j] = un[i, j] - (c*dt/dx*(un[i,j] - un[i-1,j]))-(c*dt/dy*(un[i,j]-un[i,j-1]))
  31. u[0,:] = 1
  32. u[-1,:] = 1
  33. u[:,0] = 1
  34. u[:,-1] = 1
  35. fig = plt.figure(figsize=(11,7), dpi=100)
  36. ax = fig.gca(projection='3d')
  37. surf2 = ax.plot_surface(X,Y,u[:])
复制代码


输出结果:
初始条件:
001DKwyezy6QznjtnRQ8e&amp;690.png
最终结果:
001DKwyezy6Qznjy4Su42&amp;690.jpg
做CFD计算的童鞋可能更容易理解云图,这里以云图的方式显示:
001DKwyegy6QAfuVQQkb4&amp;690.png
001DKwyegy6QAfvbD8M74&amp;690.png
只需修改图形显示代码:
  1. plt.figure()
  2. im=plt.imshow(u,interpolation='bilinear',origin='lower',cmap=cm.rainbow)
  3. plt.contour(X,Y,u)
  4. plt.colorbar(im,orientation='vertical')
复制代码

【来源:http://nbviewer.ipython.org/gith ... ons/07_Step_5.ipynb
 楼主| 发表于 2015-10-29 21:25 | 显示全部楼层
[系列]Python计算CFD问题<7>:2D对流问题
在前面的例子中,我们处理了2D线性对流问题,虽然问题是二维的,但实际上还是一维的,因为只有计算域是2D,物理变量只有X方向速度是变量。在本例中,我们来处理真正的2D对流问题。
2D对流问题可以用此方程组进行表达:
001DKwyezy6QAihScyKba&amp;690.png
时间项采用向前差分,空间项采用先后差分。离散后的方程为:
001DKwyezy6QAihS5o70b&amp;690.png
换成迭代格式为:
001DKwyegy6QAisi4LJ8f&amp;690.png
初始条件为: 001DKwyezy6QAiiS2gC3e&amp;690.png
边界条件:
001DKwyezy6QAij6RUO56&amp;690.png
编制计算程序为:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import matplotlib.cm as cm

  4. nx=101
  5. ny=101
  6. nt=80

  7. dx=2.0/(nx-1)
  8. dy=2.0/(ny-1)
  9. sigma=0.2
  10. dt=sigma*dx

  11. x=np.linspace(0,2,nx)
  12. y=np.linspace(0,2,ny)

  13. u=np.ones((nx,ny))
  14. v=np.ones((nx,ny))
  15. un=np.ones((nx,ny))
  16. vn=np.ones((nx,ny))

  17. u[.5/dx:1/dx+1,.5/dy:1/dy+1]=2
  18. v[.5/dx:1/dx+1,.5/dy:1/dy+1]=2

  19. for n in range(nt+1):
  20. un=u.copy()
  21. vn=v.copy()
  22. u[1:,1:]=un[1:,1:]-(un[1:,1:]*dt/dx*(un[1:,1:]-un[0:-1,1:]))-vn[1:,1:]*dt/dy*(un[1:,1:]-un[1:,0:-1])
  23. v[1:,1:]=vn[1:,1:]-(un[1:,1:]*dt/dx*(vn[1:,1:]-vn[0:-1,1:]))-vn[1:,1:]*dt/dy*(vn[1:,1:]-vn[1:,0:-1])

  24. u[0,:]=1
  25. u[-1,:]=1
  26. u[:,0]=1
  27. u[:,-1]=1

  28. v[0,:]=1
  29. v[-1,:]=1
  30. v[:,0]=1
  31. v[:,-1]=1

  32. X,Y=np.meshgrid(x,y)
  33. plt.figure()
  34. im=plt.imshow(u,interpolation='bilinear',origin='lower',cmap=cm.rainbow)
  35. plt.contour(X,Y,v)
  36. plt.colorbar(im,orientation='vertical')
复制代码

输出结果:
初始条件(u,v分布)
001DKwyezy6QAijbjbqa8&amp;690.png
001DKwyezy6QAijdO3j1d&amp;690.png
最终结果(u,v分布):
001DKwyezy6QAij2zBp7b&amp;690.png
001DKwyezy6QAijgcWMdc&amp;690.png
【来源:http://nbviewer.ipython.org/gith ... ons/07_Step_5.ipynb
发表于 2016-4-5 13:38 | 显示全部楼层
大拇指,厉害。先收藏了。
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-12-28 12:32 , Processed in 0.310893 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表