研0紀實:一維間斷Galerkin方法(DG)
本部分考慮簡單的一維問題:
。實際求解的算例為
並採用週期邊界條件(我導說用什麼邊界條件也是一個專門的研究方向,所以現在用什麼邊界條件不重要,能把演算法搞懂就行了)。
1。 間斷Galerkin方法(Discontinuous Galerkin Method)
假設問題的空間求解域為
,先定義網格節點:
每個單元
記作
,長度記為
。
DG方法與以前學的有限元方法的區別和優勢在於:
它不需要基函式是連續的,從而很大程度上提高了靈活性
。我們定義分片多項式空間
如下:
就是說
限制在每個單元上都是那個單元上的至多
次多項式。易知,它是
維的。
接下來推導方程的弱形式:設
是真解,則
我們可以選取
的這樣一組基:它只在一個單元上非零。所以上式等價於
利用分部積分:
這裡
在邊界上的取值就要借用隔壁的單元中的資訊了。所以這個時候,我們需要用一種叫
數值通量
的東西來代替
在邊界
處的值。
我們一般使用單調通量
,它應滿足三個條件:
1。 相容性:
。
2。 連續性:
對兩個變數都是Lipschitz連續的。
3。 單調性:
對第一個變數單調增,對第二個變數單調減。
(在理論證明的部分,我們會看到這幾個性質的具體用處)
至此,我們得到完整的弱形式:
對所有的單元
成立。
2。 數值求解
取定
的一組基為
,
,其中
是第
個單元上的一組基。對於
,數值通量可以簡單地取做迎風通量
。
在每個單元上設
(注意隨著
的變動,
都是
的函式),那麼弱形式等價於
寫成方程組即為:
其中
(太大了,全寫出來裝不下)
再利用週期邊界條件,得到整體的方程組為(記
):
再簡記為
,記
,這也就等價於
。
時間層上可以採用龍格-庫塔方法進行推進,常用的有3階格式:
%3階強保穩龍格庫塔方法
function
Qn
=
RK3
(
A,Q,t
)
k1
=
Q
+
t
*
L
(
A
,
Q
);
k2
=
(
3
/
4
)
*
Q
+
(
1
/
4
)
*
k1
+
(
1
/
4
)
*
t
*
L
(
A
,
k1
);
Qn
=
(
1
/
3
)
*
Q
+
(
2
/
3
)
*
k2
+
(
2
/
3
)
*
t
*
L
(
A
,
k2
);
end
以及4階格式:
%10階4級強保穩,SSP-RK4格式
function
Qn
=
RK4
(
A,Q,t
)
Q1
=
Q
;
Q2
=
Q
;
for
i
=
1
:
5
Q1
=
Q1
+
(
t
/
6
)
*
L
(
A
,
Q1
);
end
Q2
=
(
1
/
25
)
*
Q2
+
(
9
/
25
)
*
Q1
;
Q1
=
15
*
Q2
-
5
*
Q1
;
for
i
=
6
:
9
Q1
=
Q1
+
(
t
/
6
)
*
L
(
A
,
Q1
);
end
Qn
=
Q2
+
(
3
/
5
)
*
Q1
+
(
t
/
10
)
*
L
(
A
,
Q1
);
end
首先什麼是龍格庫塔方法,正常來說最自然的做法是Euler向前,即對於一個常微分方程
,我們的第一反應都是用
作為斜率,對
附近作一個線性的近似:
但是這個近似很糙,階數很低。為了獲得更高階的精度,我們把幾次上面的過程做一個加權的組合,就是龍格庫塔方法:
其中
和程式碼裡面的本質是一樣的,不過程式碼裡面使用的是所謂的“強保穩”格式,反正這樣做會大大加強穩定性,具體為什麼我暫時還不知道。
然後再解釋一下這裡的
是什麼:我們的方程是
,所以對於當前時間層的解向量
來說,
是
的一個近似,具體地位就相當於龍格庫塔方法裡面的
。
還要明確的一件事是:每個單元上的基如何選擇?一個很自然的想法是:選取
但這樣做有一個問題:我們發現
的最後一行是
當
很小時,
的最後一行會非常非常小(連MATLAB都會警告,工作精度接近奇異),所以不能選得這麼簡單。為了解決這個問題,可以對每一個基作一定的尺度變換,即除以
;另一種方法是,直接選取這個單元上的標準正交基:標準Legendre多項式,這樣一來我們的
甚至是一個對角陣,連求逆的工作都省了。
Legendre多項式的生成方式為:
所以它的導數為
標準化,再作尺度變換移動到第
個單元即為
要說明的細節就是這些了,接下來就寫正式的核心演算法吧:
首先寫一個Legendre多項式及其導數的生成程式:
%生成區間[a,b]上的標準Legendre多項式
function
[Pn,DPn]
=
Legendre
(
n,a,b
)
Q
=
@(
x
)
0。
*
x
;
DQ
=
@(
x
)
0。
*
x
;
R
=
@(
x
)
0。
*
x
+
1
;
DR
=
@(
x
)
0。
*
x
;
P
=
@(
x
)
((
2
*
0
+
1
)
。*
x
。*
R
(
x
)
-
0。
*
Q
(
x
))
/
(
0
+
1
);
DP
=
@(
x
)
((
2
*
0
+
1
)
。*
(
x
。*
DR
(
x
)
+
R
(
x
))
-
0。
*
DQ
(
x
))
/
(
0
+
1
);
if
n
==
-
1
Pn
=
Q
;
DPn
=
DQ
;
elseif
n
==
0
Pn
=
R
;
DPn
=
DR
;
elseif
n
==
1
Pn
=
P
;
DPn
=
DP
;
else
for
i
=
3
:
n
+
1
k
=
i
-
2
;
Q
=
R
;
DQ
=
DR
;
R
=
P
;
DR
=
DP
;
P
=
@(
x
)
((
2
*
k
+
1
)
。*
x
。*
R
(
x
)
-
k
。*
Q
(
x
))
/
(
k
+
1
);
DP
=
@(
x
)
((
2
*
k
+
1
)
。*
(
x
。*
DR
(
x
)
+
R
(
x
))
-
k
。*
DQ
(
x
))
/
(
k
+
1
);
end
Pn
=
P
;
DPn
=
DP
;
end
%尺度變換
c
=
(
a
+
b
)
/
2
;
h
=
(
b
-
a
)
/
2
;
Pn
=
@(
x
)
sqrt
((
2
*
n
+
1
)
/
(
2
*
h
))
*
Pn
((
x
-
c
)
/
h
);
DPn
=
@(
x
)
sqrt
((
2
*
n
+
1
)
/
(
2
*
h
^
3
))
*
DPn
((
x
-
c
)
/
h
);
end
初值條件(便於靈活調整,主程式裡只需統一寫成
):
%初值條件
function
y
=
f
(
x
)
y
=
sin
(
x
);
end
龍格庫塔的一步(一樣,便於靈活調整):
%龍格庫塔的一步
function
DX
=
L
(
A,X
)
DX
=
-
A
*
X
;
end
接下來就是真正的主函數了!幾個值得說明的點:quadgk(f,a,b)是Gauss積分,kron是張量積。
CFL數是為了待會兒精度檢驗要用。
%間斷有限元方法求解一維雙曲守恆率:
%u_t + u_x = 0,初值條件為 u(x,0) = f(x),
%邊界條件取週期邊界,時間上使用龍格庫塔方法
function
[X,T,Q,C]
=
LegendRKDG
(
xa,xb,tb,k,kt,N,CFL
)
%輸入:空間求解域[xa,xb],時間求解域[0,tb],
%空間剖分段數N(時間步長自適應生成),
%分片多項式的最高次數k,基函式使用尺度變換後的標準Legendre多項式
%時間階數kt,可選用3,4階龍格庫塔方法,以及CFL數
%輸出:空間網格X,時間網格T,近似解矩陣Q,
%以及基函式的係數矩陣C
%初始化
h
=
(
xb
-
xa
)
/
N
;
X
=
xa
:
h
:
xb
;
X
=
X
‘
;
T
=
0
;
%構造剛度矩陣(由於選取了標準正交基,質量矩陣是單位陣)
G
=
zeros
(
k
+
1
,
k
+
1
);
H
=
zeros
(
k
+
1
,
k
+
1
);
for
i
=
1
:
k
+
1
for
j
=
1
:
k
+
1
[
fi
,
Dfi
]
=
Legendre
(
i
-
1
,
-
h
/
2
,
h
/
2
);
fj
=
Legendre
(
j
-
1
,
-
h
/
2
,
h
/
2
);
fjDfi
=
@(
x
)
Dfi
(
x
)
。*
fj
(
x
);
G
(
i
,
j
)
=
-
quadgk
(
fjDfi
,
-
h
/
2
,
h
/
2
)
+
fj
(
h
/
2
)
*
fi
(
h
/
2
);
H
(
i
,
j
)
=
fj
(
h
/
2
)
*
fi
(
-
h
/
2
);
end
end
I
=
speye
(
N
);
v
=
[
2
:
N
,
1
];
W
=
I
(:,
v
);
A
=
kron
(
I
,
G
)
-
kron
(
W
,
H
);
%計算初值
for
p
=
1
:(
k
+
1
)
*
N
j
=
mod
(
p
-
1
,
k
+
1
);
i
=
(
p
-
1
-
j
)
/
(
k
+
1
)
+
1
;
fp
=
Legendre
(
j
,
X
(
i
),
X
(
i
+
1
));
g
=
@(
x
)
fp
(
x
)
。*
f
(
x
);
F
(
p
)
=
quadgk
(
g
,
X
(
i
),
X
(
i
+
1
));
end
%將初值裝填到C的第一列
C
=
F
’
;
C1
=
reshape
(
C
,[
k
+
1
,
N
]);
C1
=
C1
‘
;
%開始求解
while
T
(
end
)
<
tb
t
=
CFL
*
h
^
((
k
+
1
)
/
kt
);
if
T
(
end
)
+
t
>
=
tb
t
=
tb
-
T
(
end
);
end
T
=
[
T
;
T
(
end
)
+
t
];
if
kt
==
3
C
=
[
C
,
RK3
(
A
,
C
(:,
end
),
t
)];
elseif
kt
==
4
C
=
[
C
,
RK4
(
A
,
C
(:,
end
),
t
)];
end
end
%利用元胞陣列儲存每一個時間層上的係數矩陣
E
=
cell
(
length
(
T
),
1
);
for
j
=
1
:
length
(
T
)
R
=
reshape
(
C
(:,
j
),[
k
+
1
,
N
]);
E
{
j
}
=
R
’
;
end
C
=
E
;
%這裡計算Q在每個單元左端點的值
for
j
=
1
:
length
(
T
)
S
=
C
{
j
};
Le
=
cell
(
k
+
1
);
for
i
=
1
:
k
+
1
Le
{
i
}
=
Legendre
(
i
-
1
,
-
h
/
2
,
h
/
2
);
end
P
=
zeros
(
1
,
N
);
for
i
=
1
:
N
for
q
=
1
:
k
+
1
lrd
=
Le
{
q
};
P
(
i
)
=
P
(
i
)
+
S
(
i
,
q
)
*
lrd
(
-
h
/
2
);
end
end
Q
(:,
j
)
=
P
;
end
Q
=
[
Q
;
Q
(
1
,:)];
end
程式編寫好之後,輸入
[
X
,
T
,
Q
,
C
]
=
LegendRKDG
(
0
,
2
*
pi
,
4
*
pi
,
3
,
4
,
100
,
0。1
);
來求一個時間為
範圍內的解,選用三次多項式,四階龍格庫塔方法,100個單元,CFL數為0。1。求好之後,我們寫一個畫圖的程式來判斷它求的對不對。
%flash。m 顯示解隨時間變化規律
M
=
size
(
Q
,
2
);
figure
xlabel
(
‘X’
);
ylabel
(
‘Q’
);
s
=
[
X
(
1
),
X
(
end
),
-
2
,
2
];
axis
(
s
);
[
p
,
q
]
=
size
(
Q
);
Q2
=
zeros
(
p
,
q
);
for
i
=
1
:
p
for
j
=
1
:
q
Q2
(
i
,
j
)
=
sin
(
X
(
i
)
-
T
(
j
));
end
end
for
i
=
1
:
10
:
M
plot
(
X
,
Q
(:,
i
),
X
,
Q2
(:,
i
),
‘r。’
);
axis
(
s
);
pause
(
0。001
);
end
在命令列輸入flash,即可看到我們求得的解:
顯示解
https://www。zhihu。com/video/1449764962420359168
3。 理論部分
我導說這些都是套路,以後自己做的時候也得證明,所以還是整理一下。
3。1 解的存在唯一性
的弱解(弱形式的解)可能不是唯一的。但是在物理上,如果弱解滿足單元熵不等式,那麼它應該是唯一的。
單元熵不等式:
,其中
滿足
,
(它是一個原函式)。
一般來說證明單元熵不等式是比較困難的,但是可以證明:
性質1
的解
滿足下面形式的單元熵不等式:
其中
是平方熵,
是某個滿足相容性的數值通量。
證明
置
則因為
是
的解,對任意的
都有
。特別地,
,即
注意到
及
因此若記
,則
置
則容易驗證,這樣定義的
是滿足
的相容數值通量。現在我們可以寫
只需要證明
就好了(它的下標都是一樣的,下面省略)。由Lagrange中值定理,我們有
其中最後一個不等號是因為
根據Lagrange中值定理的要求,
在
之間。不妨設
,則根據數值通量
的單調性,顯然得到
於是
從而
。
□
性質2
(穩定性) 如果
具有
週期或緊支撐
的邊界,則
的解
是
穩定的,即
或
證明
由於邊界條件週期或緊支撐,將所有
上的單元熵不等式累加即得結論。□
引理
(投影定理)
稱為
到
的投影,如果
並且
。如果
是
到
的投影,那麼
這裡
依賴於
,但和
無關。
性質3
(收斂階) 對於線性問題
,如果其解
是光滑的,那麼其收斂階估計為
其中
是弱形式
的解,
依賴於
,但和
無關。
證明
沿用之前的記號,因為
是
的解,故
由於
是真解,故顯然也有
(這是因為:弱形式對於真解一定是對的)
由
的線性性,有
記
,則將
取做
,得:
對左邊,此前已經證明
其中
待會兒累加的時候可以消去,不用擔心,而
。所以這邊沒什麼大問題。而對於右邊,把它具體寫出來就是
由投影的第一條性質知
,由第二條性質知
,從而上式簡化為
將所有單元上的不等式累加起來,得到:
設
,則上式成為
由Gronwall不等式,可得
,從而
,即
因此即得
(這裡不是同一個
,但總之是個常數)
再結合穩定性理論,即有
□
4。 Numerical Result(數值結果,驗證收斂階)
我們在主演算法的程式裡已經寫了
這樣當空間步長變化時,時間步長自動減小,並且不會影響整體的收斂階。所以只要調空間的單元數就行了。
下面編寫測試指令碼,先寫一個計算各種誤差和Order的函式:
%誤差分析,對解和真解進行比較
function
[L1,L2,C,kL1,kL2,kC,meshsize]
=
analysisDG
(
xa,xb,tb,K,tk,N0,CFL,n,solve
)
%說明:
%輸入:X,T是空間和時間的網格剖分,Q為數值解矩陣,初始剖分段數N0,K0,
%加細次數n,用於求解的函式solve。
%輸出:L1模,L2模,L∞模隨時間變化的向量L1,L2,C,
%以及差比向量kL1,kL2,kC,用於驗證收斂階。
for
k
=
1
:
n
[
X
,
T
,
Q1
]
=
solve
(
xa
,
xb
,
tb
,
K
,
tk
,
N0
*
2
^
(
k
-
1
),
CFL
);
[
p
,
q
]
=
size
(
Q1
);
meshsize
(
k
,:)
=
[
p
-
1
,
q
-
1
];
Q2
=
zeros
(
p
,
q
);
for
i
=
1
:
p
for
j
=
1
:
q
Q2
(
i
,
j
)
=
sin
(
X
(
i
)
-
T
(
j
));
end
end
K0
=
length
(
T
);
%計算L1模
L1
(
k
)
=
sum
(
sum
(
abs
(
Q1
-
Q2
)))
/
(
N0
*
2
^
(
k
-
1
)
*
K0
);
%計算L2模
L2
(
k
)
=
sqrt
(
sum
(
sum
(
abs
((
Q1
-
Q2
)
。^
2
))))
/
sqrt
(
N0
*
2
^
(
k
-
1
)
*
K0
);
%計算L∞模
C
(
k
)
=
max
(
max
(
abs
(
Q1
-
Q2
)));
L1
=
L1
‘
;
L2
=
L2
’
;
C
=
C
‘
;
end
%計算階
kL1
=
L1
(
1
:
end
-
1
)
。/
L1
(
2
:
end
);
kL2
=
L2
(
1
:
end
-
1
)
。/
L2
(
2
:
end
);
kC
=
C
(
1
:
end
-
1
)
。/
C
(
2
:
end
);
kL1
=
log
(
kL1
)
/
log
(
2
);
kL2
=
log
(
kL2
)
/
log
(
2
);
kC
=
log
(
kC
)
/
log
(
2
);
end
然後就是測試指令碼:
%testDG。m,測試DG演算法的精度
N
=
10
;
N0
=
1
;
CFL
=
0。2
;
[
L1
,
L2
,
C
,
kL1
,
kL2
,
kC
,
meshsize
]
=
analysisDG
(
0
,
2
*
pi
,
2
*
pi
,
3
,
4
,
N0
,
CFL
,
N
,@
LegendRKDG
);
n
=
1
:
1
:
N
;
plot
(
n
,
L1
,
’-b‘
,
n
,
L2
,
’-r‘
,
n
,
C
,
’-k‘
)
legend
(
’L1 Norm‘
,
’L2 Norm‘
,
’L∞ Norm‘
)
xlabel
(
’n‘
)
ylabel
(
’Error‘
)
title
(
’Error - n‘
)
m
=
1
:
1
:
N
-
1
;
plot
(
m
,
kL1
,
’-b‘
,
m
,
kL2
,
’-r‘
,
m
,
kC
,
’-k‘
)
legend
(
’L1 Norm‘
,
’L2 Norm‘
,
’L∞ Norm‘
)
xlabel
(
’n‘
)
title
(
’EOC‘
)
(注意這裡CFL數要自己調一下,不然可能結果很差)
最後畫出來一些類似於這樣的圖:
這是使用3次多項式,4階龍格庫塔方法得到的結果,數值結果說明收斂階是4階,很好地驗證了上面理論部分的正確性。
最後,看論文裡面好像最後都是做成這種表格的形式,我也試著弄了一下:
3次多項式,4階龍格庫塔方法的詳細結果
(後來發現網格那裡只要寫空間的size就行了,但也懶得改了,就這樣吧)
Reference: Chi-Wang Shu, Discontinuous Galerkin Methods: General Approach and Stability
DGpaper。pdf
710。9K
·
百度網盤
DG文獻筆記。pdf
99。6K
·
百度網盤