基本原理
守恆型方程
使用空間中心差分離散
其中和表示網格點與兩側網格點和的中點。構造函數()使得則稱函數構造出的爲數值通量。利用進行時間離散推進得到的格式爲守恆型差分格式。而構造函數即是對通量的重構,因此這個方法稱爲通量重構。
這個方法保證了通量在網格單元的交界面()兩側始終是相等的,不會因爲網格離散而產生數值散度,從而在網格交界面上出現非物理的源和匯。
對流方程
初場爲週期邊界
令,時間推進使用歐拉單步推進,得到離散方程
化簡之後我們可一看到就是前面提到的一階中心差分的格式,根據前面一階中心差分格式的分析可以知道這個格式不穩定,需要添加人工粘性,這裏就不解這個方程了。
Burgers方程
利用通量重構求解
初場爲週期邊界
同樣使用上面的離散方法進行離散得到
具體代碼如下
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
const int NE=32,//空間點數
NS=100;//時間步數
const double rb=-5,l=10,//計算域左邊界,計算域長度
dt=0.1,//時間步長
dx=l/NE;
void init_guass(vector<double> &u0)//設置高斯函數初場
{
for(int i=0;i<u0.size();i++)
{
u0[i]=exp(-pow((l*double(i)/(NE-1)+rb),2));
}
}
void advance(vector<double>& u)
{
vector<double> t(u);
for(int i=1;i<u.size()-1;i++)
{
u[i]=t[i]-0.25*(t[i+1]*t[i+1]-t[i-1]*t[i-1])*dt/dx;
}
int i=0;
u[i]=t[i]-0.25*(t[i+1]*t[i+1]-t[u.size()-1]*t[u.size()-1])*dt/dx;
i=u.size()-1;
u[i]=t[i]-0.25*(t[0]*t[0]-t[i-1]*t[i-1])*dt/dx;
}
ostream& operator<<(ostream& out,const vector<double>& A)
{
for(int j=0;j<A.size()-1;j++)
{
out<<A[j]<<'\t';
}
out<<A[A.size()-1];
return out;
}
int main()
{
vector<double> u(NE+1);
init_guass(u);
cout<<NE+1<<'\t'<<NS<<'\t'<<rb<<'\t'<<l<<'\n';
cout<<u<<'\n';
for(int i=0;i<NS;i++)
{
advance(u);
cout<<u<<'\n';
}
return 0;
}
可以看到計算髮散了,從前面對流方程可以看到以這種單元兩側的平均值作爲通量點的值實際上是一種中心差分格式,那麼顯示推進必然不穩定,必須添加人工粘性。因此這裏考慮使用迎風格式來進行計算。
令則得到推進公式爲
得到advance函數爲
void advance(vector<double>& u)
{
vector<double> t(u);
for(int i=1;i<u.size()-1;i++)
{
u[i]=t[i]-0.5*(t[i]*t[i]-t[i-1]*t[i-1])*dt/dx;
}
int i=0;
u[i]=t[i]-0.5*(t[i]*t[i]-t[u.size()-1]*t[u.size()-1])*dt/dx;
}
計算結果如下
可以看到使用迎風的通量重構即可得到穩定的顯式推進格式,並且結果也基本上沒有明顯問題。
這裏使用更高階格式嘗試一下。
可以得到
於是有新的推進格式
得到新的advance函數爲
void advance(vector<double>& u)
{
vector<double> t(u);
for(int i=1;i<u.size()-1;i++)
{
u[i]=t[i]-0.25*(3*t[i]*t[i]-4*t[i-1]*t[i-1]+t[i-2]*t[i-2])*dt/dx;
}
int i=0;
u[i]=t[i]-0.25*(3*t[i]*t[i]-4*t[u.size()-1]*t[u.size()-1]+t[u.size()-2]*t[u.size()-2])*dt/dx;
i=1;
u[i]=t[i]-0.25*(3*t[i]*t[i]-4*t[i-1]*t[i-1]+t[u.size()-1]*t[u.size()-1])*dt/dx;
}
計算結果如下
可以看到間斷部分更加尖銳,更貼近真解,不像之前那樣間斷的拐角處比較光滑。但是可以看到在間斷結束的位置有一個向下的小尖峯,這是使用高階耗散(高於二階的耗散)時總會出現的一個現象,具體產生的原因我也不是很清楚,似乎類似於吉布斯現象。