計算流體力學——從原理到代碼(一):對流方程的格式與實現
來自專欄 第三新東京市
先放最重要的,以後再慢慢修稿。
一般來說,流體方程(組)都是雙曲型偏微分方程(組),不了解的可以看這個答案:
流體力學中的歐拉方程並沒有二階偏導項,為什麼還是雙曲型的?對於線性對流方程(linear advection equation):
解析解:
這樣的解沿著x-t平面上的直線(如下)是常數:
我們把這樣的線稱為方程的特徵線,特徵線上,原來的偏微分方程退化成一個常微分方程。
(證明:
特徵線的示意圖:
理解得不太明白的可以看這個:
怎麼理解偏微分方程中的特徵線,什麼樣的線可以稱為特徵線?離散化:
目的:給計算機流體的初始條件,讓程序解這個方程,得到我們想要的某時刻之後的近似解。
流體問題 -> PDE求解(連續的數學問題) -> 演算法(離通過散方法,逼近連續問題的解)-> 流體問題近似的解
最簡單的考慮:空間[0,1] ,變成[0,1]之間100,1000,10000個等距格點:0.001,0.002,…
每一個格點上計算流體的量
時間也類似,0.001s, 0.002s, ……,不斷向前
如果解 在 處足夠的光滑,由Taylor Expansion:
那 在 處的估計,結果是一階精確:
或者,使用中心差分,結果是二階精確:
所以,最直接的格式FTCS(Forward time central space):
這個格式,空間上 2階精度,時間上 1階。
OK
那我們怎麼實現呢?
對於方程 ,將區間[ 0, 1],劃分成101個格點,前後再多加2個格點,為了實現outlet邊界條件(以後會講)
首先是設置變數
% This is a demo of Forward Time Central Space for Advection Equation clearclc% Set the parametersxmin = 0;xmax = 1;N = 100;dx = (xmax-xmin)/N;tmin = 0;tmax = 0.5;dt = 0.001;v = 1;% Set the initial conditionx = linspace(xmin-dx, xmax+dx, N+3);u0 = [ones(1,5), zeros(1,103-5)];utemp = u0;uplus = u0;nstep = tmax/dt;t = 0;
然後編寫主循環的思路是:
對於時間步數循環
- 計算邊界點的值
- 根據差分格式,更新每個點的值
- 時間和空間+1
for n = 1:nstep % calculate the boundary condition utemp(1) = utemp(3); utemp(N+3) = utemp(N+1); % calculate the new value for i = 2:N+2 uplus(i) = utemp(i) - v*dt*(utemp(i+1) - utemp(i-1))/(2*dx); % YOU ONLY NEED TO CHANGE THIS LINE!!! end % update time step and u t = t + dt; utemp = uplus; % visualization plot(x,utemp,bo-,markerfacecolor,b); shg; pause(dt); end
運行結果
這是一個非常不穩定的格式!
所以,一切沒有想像中那麼簡單,那麼,為什麼這麼一個看似能二階精度的格式會不穩定呢?
(不想搞懂理論解釋的,可以跳過下面這一部分)
von Neumann stability analysis
用有限傅立葉級數表示離散解(嚴格來說,這僅適用於周期性域中的線性問題):
下一個時刻的解: ,這個 表示對於第k個成分的復振幅因子
我們根據FTCS的格式 ,可以推出:
我們看到,無論選擇什麼時間步, 。 這意味著解決方案在時間上呈指數級放大,無條件不穩定!
所以,早些年,大量研究在尋找好的格式,和格式穩定性理論,其中著名的格式:
Lax-Friedrichs (LF) method
代碼:
uplus(i) = (utemp(i+1) + utemp(i-1))/2 - v*dt*(utemp(i+1) - utemp(i-1))/(2*dx);
(做gif太煩了!老子不幹了!)
同樣的,馮諾依曼分析一下, 格式:,
我們將解視為成傅里葉級數 組成
對於時間n+1步,
代入原格式,化簡得到:
所以,如果希望 ,則 滿足即可
其中, 就是大名鼎鼎的,由計算數學三個祖師爺名字構成的——庫朗-弗雷德里奇-李維條件是 Courant-Friedrichs-Lewy (CFL) condition。
從圖上結果,發現有耗散(就是物理中的能量耗散)
為什麼有耗散呢?
而這個最後一項
帶來了耗散!
還有一種格式
Upwind method
格式:
該方法穩定且擴散性較小,但仍然只有一階準確。
可以使用高階空間插值方案進行改進。
這是大名鼎鼎的Godnouv的前身
我知道你們要代碼
% This is a demo of First Order Upwind for Advection Equation clearclc% Set the parametersxmin = 0;xmax = 1;N = 100;dx = (xmax-xmin)/N;tmin = 0;tmax = 0.5;dt = 0.009;v = 1;% Set the initial conditionx = linspace(xmin-dx, xmax+dx, N+3);u0 = exp( -200*(x-0.25).^2 );% u0 = [ones(1,5), zeros(1,103-5)];utemp = u0;uplus = u0;nstep = tmax/dt;t = 0;for n = 1:nstep % calculate the boundary condition utemp(1) = utemp(3); utemp(N+3) = utemp(N+1); % calculate the new value for i = 2:N+2 uplus(i) = utemp(i) - v*dt*(utemp(i) - utemp(i-1))/dx; end % update time step and u t = t + dt; utemp = uplus; % calculate exact solution exact = exp(-200*(x-0.25-v*t).^2); % visualization plot(x,exact,r-) hold on plot(x,utemp,bo-,markerfacecolor,b); hold off shg; pause(dt); end
Lax-Wendroff method
這個格式的動機,對於時間我們希望更高的精度:
然後呢,因為時間的差分可以近似時間的偏導:
整理一下,就可以得到最上面的格式
(我建議一定要手推一下,記住推導的思想,以後就不用翻書,可以自己現推,而且……不難……)
LW格式的結果很有意思,方法是穩定的,但是:
1)不連續處的解會震蕩。
2)平滑區域的相移。
和cyf跑步去了
預告:
二里講有限體積法
三里講Riemann 問題求解器
四補充具體實現中關於邊界條件,量綱,物理參數等問題
五開始講N-S方程的數值方法
有心情就補充:
磁流體力學MHD方程的建立
保守場的數值方法(重力場、電磁場)
正壓模式和協壓模式
次網格方法和雷諾平均
推薦閱讀:
※淺談線性化
※MATLAB 高級數據結構連載 4 containers.Map
※MatLab 數據類型速覽
※如何用Matlab畫一朵花?
※告別mex崩潰調試法: 藉助visual studio調試