Metody numeryczne rozwiązywania równania adwekcji

Transkrypt

Metody numeryczne rozwiązywania równania adwekcji
UNIWERSYTET MARII CURIE-SKŁODOWSKIEJ W LUBLINIE
WYDZIAŁ MATEMATYKI FIZYKI I INFORMATYKI
Marcin Roman
Metody numeryczne rozwiązywania
równania adwekcji
Numerical methods for solving
advection equation
Praca licencjacka wykonana
pod kierunkiem
prof. dra hab. Krzysztofa Murawskiego
Lublin 2009
Składam serdeczne podziękowania
Panu prof. dr. hab. Krzysztofowi Murawskiemu
za poświęcony czas, cenne wskazówki,
cierpliwość i wszelką pomoc okazaną
podczas pisania niniejszej pracy.
Spis treści
Wstęp
iv
1. Podstawowe pojęcia
1.1. Równania różniczkowe zwyczajne . . . . . . . . . . . . . . . . . . . .
1.2. Równania różniczkowe cząstkowe . . . . . . . . . . . . . . . . . . . .
1.3. Równanie adwekcji . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2. Metody numeryczne rozwiązywania
2.1. Metody różnic skończonych . . . . .
2.2. Metoda Laxa-Friedrichsa . . . . . .
2.3. Metoda Laxa-Wendroffa . . . . . .
2.4. Metoda niejawna Wendroffa . . . .
2.5. Metoda Beama-Warminga . . . . .
2.6. Metoda MacCormacka . . . . . . .
2.7. Metody objętości skończonych . . .
2.8. Metoda Godunowa . . . . . . . . .
2.9. Metody wyższych rzędów . . . . . .
równań różniczkowych
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
3. Projekt własny - program komputerowy
adwekcji
3.1. Interfejs użytkownika . . . . . . . . . . . .
3.2. Szczegóły implementacyjne . . . . . . . . .
3.3. Symulacje numeryczne . . . . . . . . . . .
Podsumowanie
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
3
7
10
12
14
15
15
16
16
17
18
19
rozwiązujący równanie
23
. . . . . . . . . . . . . . . 23
. . . . . . . . . . . . . . . 24
. . . . . . . . . . . . . . . 28
31
iii
Wstęp
Wiele zjawisk daje się opisać w naturalny i intuicyjny sposób jako zależności
funkcji i ich pochodnych. Jako przykład rozważmy prosty model ruchu swobodnie
spadającego ciała puszczonego z pewnej wysokości. Działają na niego siła grawitacji
i siły tarcia związane z ruchem. Siła tarcia kinetycznego jest proporcjonalna do
prędkości. Związek ten możemy zapisać następująco:
y 00 = g − ky 0 ,
jest prędkością ciała, a k jest współczynnikiem proporcjonalności.
gdzie y 0 = dy
dt
Mając tak postawiony problem chcielibyśmy znaleźć taką funkcję y(t), która będzie
spełniała powyższe równanie.
Stosując teorię równań różniczkowych możemy także badać wiele innych,
bardziej złożonych zjawisk, takich jak rozpad promieniotwórczy, rozwój populacji,
rozchodzenie się fal na wodzie, czy też kształtowanie się zjawisk atmosferycznych.
W informatyce równania różniczkowe stosuje się między innymi do modelowania
ruchu w sieciach komputerowych, przetwarzania obrazów oraz do estymacji i
kompensacji ruchu (ang. optical flow ). W tej pracy zostaną omówione metody
numeryczne rozwiązywania hiperbolicznych równań różniczkowych na przykładzie
równania adwekcji, które modeluje procesy unoszenia i stanowi najprostsze równanie
hiperboliczne.
W pierwszym rozdziale zostaną krótko przedstawione niezbędne pojęcia oraz
model analityczny adwekcji. Rozdział drugi jest poświęcony problemowi konstrukcji
schematów numerycznych. W ostatniej części zostały opisane przeprowadzone przez
autora pracy symulacje numeryczne przy użyciu zaimplementowanych schematów.
iv
Rozdział 1
Podstawowe pojęcia
1.1. Równania różniczkowe zwyczajne
Równanie różniczkowe to równanie, w którym występują pochodne funkcji
szukanej [2]. W ujęciu formalnym:
Równanie różniczkowe. Niech F będzie funkcją ciągłą na zbiorze otwartym U , x :
t 7→ x(t) szukaną funkcją n-krotnie różniczkowalną. Równanie w postaci uwikłanej:
F (t, x(t), x0 (t), . . . , x(n) (t)) = 0
nazywamy równaniem różniczkowym zwyczajnym (ang. Ordinary Differential
Equation, ODE ) rzędu n.
Postać normalna powyższego równania to:
F (t, x(t), x0 (t), . . . , x(n−1) (t)) = x(n) (t).
(1.1)
Ze względu na częstą fizyczną interpretację zmienna niezależna t nazywana jest
czasem. Jeśli F jest wielomianem zmiennej x, to jego stopień nazywamy stopniem
odpowiadającego mu równania. Na przykład równania pierwszego stopnia nazywamy
równaniami różniczkowymi liniowymi.
Definicja 1. Niech X będzie przestrzenią wektorową, S ⊂ R×X zbiorem otwartym,
s : S 7→ X, a ∆ przedziałem. Mówimy, że funkcja s : ∆ 7→ R jest rozwiązaniem
(całką) równania (1.1), jeśli:
1. s jest n-krotnie różniczkowalna w przedziale ∆,
2.
V
(t, s(t)) ∈ S,
t∈∆
1
3. po podstawieniu s do równania (1.1) otrzymujemy tożsamość.
Ponieważ równanie (1.1) jest równoważne układowi równań rzędu pierwszego,
będziemy dalej rozważali równanie x0 = f (t, x), które zapisane w postaci różniczek
wygląda następująco: dx = f (t, x)dt.
Równanie różniczkowe wraz z warunkiem początkowym x(t0 ) = x0 nazywamy
problemem początkowym lub problemem Cauchy’ego. Jeśli nie weźmiemy pod
uwagę warunku początkowego i żadnych innych ograniczeń, to rozwiązanie będzie
zależeć od pewnych stałych. Jest to tzw. rozwiązanie ogólne równania. Mając
rozwiązanie ogólne możemy otrzymać z niego wszystkie rozwiązania szczególne
poprzez wyznaczenie stałych [6].
Zauważmy, że rozwiązanie może nie istnieć. Zgodnie z definicją 1 ma to miejsce, jeśli
f nie jest ciągła. Aby można było udowodnić istnienie rozwiązania, trzeba poczynić
pewne założenia o funkcji f .
Twierdzenie Peano (o istnieniu rozwiązania). Jeśli funkcja f jest ciągła
w otoczeniu punktu (t0 , x0 ) ∈ D = {(t, x) : |t0 − t| < a, |x0 − x| < b}, wtedy problem
Cauchy’ego ma rozwiązanie dla |t0 − t| 6 min(a, Mb ), gdzie M = supD |f (t, x)|.
Problem początkowy może mieć wiele rozwiązań. Jego jednoznaczność możemy
udowodnić na przykład dla funkcji f spełniających nierówność Lipschitza:
|f (x1 ) − f (x2 )| 6 L|x1 − x2 |.
Twierdzenie Picarda (o jednoznaczności rozwiązania). Jeśli funkcja f
spełnia twierdzenie Peano o istnieniu rozwiązania oraz warunek Lipschitza względem
zmiennej x dla pewnej stałej L, to problem Cauchy’ego ma jednoznaczne rozwiązanie
dla |t0 − t| 6 min(a, Mb , L1 ) [5].
Oczywiście rozwiązanie może istnieć (i być jednoznaczne) w szerszych
przedziałach od tych podanych w powyższych twierdzeniach [1].
Przykład 1. Jako przykład rozważmy model zmian rozmiaru okna TCP
zaproponowany w [10]. Do ważnych cech TCP należą unikanie przeciążeń i kontrola
przepływu danych. Aby to osiągnąć, można, bazując na obserwacji strat pakietów,
tak dostosowywać rozmiar okna, aby wykrywać przeciążenia albo ich unikać.
Jednocześnie chcielibyśmy uzyskać jak najlepszą efektywność transmisji. W praktyce
nie znamy rzeczywistego obciążenia poszczególnych węzłów, dlatego ważna jest
dobra technika aproksymacji. W zaproponowanym modelu rozmiar okna jest opisany
2
za pomocą stochastycznego równania różniczkowego:
dW =
dt
−W
+(
)dNT D + (1 − W )dNT O .
RT T
2
(1.2)
Tutaj W oznacza rozmiar okna, RT T czas powrotu (ang. Round Trip Time), NT D
i NT O są zmiennymi losowymi w procesie Poissona, odpowiadającymi odpowiednio
liczbie strat spowodowanych pominięciem potwierdzenia (Triple Duplicate ACK) i
nie nadejściem potwierdzenia w określonym czasie (Timeout). Wyjaśnijmy charakter
pierwszego rodzaju strat. Jeśli pakiet z wyższym numerem sekwencyjnym nadejdzie
do odbiorcy przed pakietem wcześniejszym, wówczas emitowane jest potwierdzenie
wskazujące, że odbiorca oczekuje na ten wcześniejszy pakiet (Duplicate ACK ). W
ten sposób nadawca dowiaduje się, że nieodebrany pakiet został utracony albo
dotrze później. Otrzymanie kilku potwierdzeń Duplicate ACK może wskazywać z
dużym prawdopodobieństwem, że pakiet został utracony (Triple Duplicate ACK ).
Wówczas nie czekając na timeout nadawca dokonuje retransmisji. Pierwszy składnik
powyższego równania symuluje zwiększanie rozmiaru okna, a dwa pozostałe są
związane z multiplikatywnym zmniejszaniem rozmiaru. Ten prosty model pomija
zachowanie powolnego startu i kilka innych mniej istotnych problemów, jednak nie
wpływa to znacząco na wyniki. Jeśli obliczymy wartość oczekiwaną, otrzymamy:
1
λT D
dE[W ]
=(
+ λT O ) − (
+ λT O )E(W ).
dt
RT T
2
Jest to niejednorodne równanie autonomiczne ze względu na E[W ]. Niech A i B
będą odpowiednimi stałymi. Przekształcając i całkując to równanie otrzymujemy:
dE[W ]
= A − B ∗ E(W ),
dt
A
B
ln (
dE[W ]
= Bdt,
− E(W )
A
− E(W )) = −Bt − C,
B
E(W )(t) =
1
RT T
λT D
2
λT D
+ λT O
+ C 0 e−( 2 +λT O )t .
+ λT O
1.2. Równania różniczkowe cząstkowe
Równanie opisujące zależności między kilkoma zmiennymi niezależnymi,
wieloargumentową funkcją u tych zmiennych i jej pochodnymi cząstkowymi
3
nazywamy równaniem różniczkowym cząstkowym (ang. Partial Differential
Equation, PDE ). Rząd tego równania jest równy najwyższemu rzędowi pochodnej
cząstkowej występującej w równaniu. W pracy będziemy stosować nomenklaturę dla
.
pochodnych cząstkowych np. ux = ∂u
∂x
Niech u : U 7→ R będzie funkcją szukaną, a [x1 , . . . , xn ] = x ∈ U . Oznaczmy
przez Dj u zbiór pochodnych cząstkowych j-tego rzędu [7]. Ogólnie równanie k-tego
rzędu ma postać:
F (x, u, D1 u, . . . , Dk u) = 0.
(1.3)
Jeśli funkcja u będzie przyjmowała wartości w przestrzeni Rn , czyli u = [u1 , . . . , un ],
to zapis (1.3) będzie oznaczał układ równań funkcji składowych.
Analiza równań wyższych rzędów jest dużo bardziej skomplikowana.
Rozwiązywanie ich można jednak sprowadzić do rozwiązywania układu PDE
rzędu pierwszego poprzez odpowiednie zastąpienie pochodnych cząstkowych nowymi
funkcjami. Dlatego w dalszej części skupimy się głównie na równaniach drugiego i
pierwszego rzędu. Postać ogólna równania dwóch zmiennych drugiego rzędu jest
następująca:
∂u ∂u ∂ 2 u
) = 0.
F (x, y, u, , ,
∂x ∂y ∂x∂y
Dla PDE definiuje się analogicznie pojęcie rozwiązania równania i wiele innych
twierdzeń odnoszących się do równań różniczkowych zwyczajnych. Na przykład dla
równania pierwszego rzędu F (x, y, u, ux , uy ) = 0 zagadnienie Cauchy’ego definiujemy
podając warunek początkowy u(x0 , y) = f (y) lub u(x, y0 ) = g(x).
Równanie postaci:
aux + buy = c,
(1.4)
gdzie a, b i c są funkcjami x i y, nazywamy równaniem liniowym niejednorodnym.
Jeśli c ≡ 0, wówczas mówimy o równaniu jednorodnym. Natomiast, jeśli któraś z
funkcji a, b i c zależy od u, to mamy do czynienia z równaniem quasi-liniowym.
Zauważmy, że rozwiązanie równania quasi-liniowego można sprowadzić do problemu
rozwiązania równania liniowego.
1.2.1. Charakterystyki
Załóżmy, że mamy dane równanie pierwszego rzędu:
F (x, u, Du) = 0.
4
(1.5)
Tutaj x = [x1 , . . . , xn ]. Metoda charakterystyk pozwala nam na sprowadzenie
rozwiązania (1.5) wzdłuż pewnej krzywej w przestrzeni Rn do problemu rozwiązania
układu równań zwyczajnych. Szukaną krzywą x(s) : R 7→ Rn będziemy zapisywać
w postaci parametrycznej. Niech p(s) = [ux1 (x(s)), . . . , uxn (x(s))]. Zróżniczkujmy
(1.5) po zmiennej xi :
n
X
∂F
∂F
(p(s), u(x(s)), x(s))uxj xi +
(p(s), u(x(s)), x(s))uxi
∂u
j=1 ∂pj
+
∂F
(p(s), u(x(s)), x(s)) = 0.
∂xi
Przyjmując zatem
d
∂F
xj (s) =
(p(s), u(x(s)), x(s))
ds
∂xj
d
i zapisując sumę jako ds
pi pozbywamy się pochodnych cząstkowych drugiego rzędu
szukanej funkcji u. Wzdłuż krzywej x = x(s) spełnia ona równanie:
n
n
X
X
d
∂F
d
uxi (s) xi (s) =
pi
u(x(s)) =
(p(s), u(x(s)), x(s)).
ds
ds
∂xj
i=1
i=1
Otrzymujemy w ten sposób układ ODE, zwany układem charakterystyk [7]:





d
∂F
− ds
pi + ∂F
(p(s), u(x(s)), x(s))pi + ∂x
(p(s), u(x(s)), x(s)) = 0 (i = 1 . . . n),
∂u
i
P
∂F
d
(p(s), u(x(s)), x(s)),
u(x(s)) = ni=1 pi ∂x
ds
j



d
∂F

(i = 1 . . . n).
x (s) = ∂xi (p(s), u(x(s)), x(s))
ds i
Krzywe będące jego rozwiązaniem nazywamy charakterystykami.
Zatem jeśli dla (1.5) zdefiniujemy warunek początkowy wzdłuż krzywej, która
nie jest charakterystyką, będzie można wyznaczyć rozwiązanie w punktach, przez
które przechodzi jakaś charakterystyka.
W przypadku równania quasi-liniowego:
F (x, u, Du) =
n
X
ai ux1 + b = 0,
i=1
gdzie ai (i = 1 . . . n) i b są funkcjami x i u, mamy:

 d

u(x(s)) = −b,
= ai
(i = 1 . . . n).
ds
d
x (s)
ds i
Widzimy więc, że przy zastosowaniu metody charakterystyk ważne są również
metody stosowane do równań zwyczajnych.
5
1.2.2. Hiperboliczne równania różniczkowe
Zapiszmy równanie quasi-liniowe drugiego rzędu
auxx + buxy + cuyy + e = 0,
(1.6)
przyjmując p = ux i q = uy , wzdłuż krzywej określonej wzorami: x = x(s), y = y(s).
d
d
p i ds
q oraz wyznaczmy z nich pochodne cząstkowe [1]:
W tym celu obliczmy ds
uxx =
dp
dy
− uxy
dx
dx
uyy =
dy
dq
− uxy .
dy
dx
i symetrycznie:
Po podstawieniu ich do (1.6) otrzymamy:
−uxy [a(
dy 2
dy
dp dy
dq
dy
) − b + c] + a
+c +e
= 0.
dx
dx
dx dx
dx
dx
(1.7)
Określmy krzywą (x, y), tak aby zniknęła pochodna mieszana uxy :
dy
a
dx
!2
−b
dy
+ c = 0.
dx
(1.8)
Ze względu na symetrię postaci ogólnej (1.7) względem x i y, jeśli a ≡ 0, to równanie
kwadratowe (1.8) możemy pomnożyć przez ( dx
)2 . W zależności od wyróżnika ∆ =
dy
b2 − 4ac wprowadzamy podział na równania:
1. hiperboliczne, dla ∆ > 0,
2. paraboliczne, dla ∆ = 0,
3. eliptyczne, dla ∆ < 0.
W tej pracy skupimy się na równaniach rzędu pierwszego postaci:
qt + f (q)x = 0.
(1.9)
Tutaj q : R × R 7→ Rm jest szukaną funkcją, natomiast f : Rm 7→ Rm . Jeśli f jest
przekształceniem liniowym, to równanie (1.9) również nazywamy liniowym i możemy
je zapisać jako
qt + Aqx = 0,
(1.10)
gdzie A jest macierzą Jacobiego tego przekształcenia [3].
6
Definicja 2. Równanie (1.10) nazywamy hiperbolicznym, jeśli macierz A jest
diagonalizowalna i ma rzeczywiste wartości własne. Jeśli dodatkowo widmo A jest
proste, to mówimy, że równanie to jest ściśle hiperboliczne.
Warunek diagonalizowalności pozwala na zapisanie macierzy A = RA0 R−1 .
Tutaj A0 jest macierzą diagonalną z wartościami własnymi na przekątnej, R jest
macierzą przejścia, a jej kolumny są odpowiednimi wektorami własnymi macierzy
A. Podstawiając tą zależność do (1.10) i mnożąc otrzymane równanie lewostronnie
przez R−1 , otrzymamy:
R−1 qt + A0 R−1 qx = 0.
Teraz przyjmijmy p = R−1 q. Widzimy więc, że znalezienie rozwiązania sprowadza się
do rozwiązania m niezależnych równań - jak się przekonamy w następnym paragrafie,
są to równania adwekcji.
Funkcję q można wyrazić jako kombinację znalezionych funkcji (tzw. zmiennych
charakterystycznych) p1 , . . . , pm , które są składowymi p:
q(x, t) = Rp(x, t),
q(x, t) =
m
X
ri pi (x, t).
i=1
Tutaj ri są wektorami własnymi A, czyli kolumnami macierzy R. Wynik ten
sugeruje, że równania hiperboliczne opisują fale rozchodzące się ze skończoną
prędkością [4].
1.3. Równanie adwekcji
Z punktu widzenia zastosowań fizycznych ważną klasę PDE stanowią równania
uzyskane z praw zachowania [3]. Rozważmy pewien ograniczony obszar U ∈ Rn .
Niech wewnątrz tego obszaru znajduje się pewna substancja, której gęstość określa
funkcja q : U 7→ R. Ilość tej substancji możemy obliczyć poprzez scałkowanie q po
tym obszarze:
Z
MU = qdU .
U
Wielkość MU może się zmieniać jedynie wskutek przepływu substancji przez brzeg
∂U tego obszaru.
W tej pracy zajmiemy się przypadkiem jednowymiarowym (n = 1), ze względu
na jego prostotę przy analizie metod numerycznych. Tak więc U jest odcinkiem
(x1 , x2 ) ∈ R. Funkcję strumienia zwykle chcielibyśmy uzależnić od gęstości
substancji na końcach odcinka: f (q, t, x). Zatem zmianę MU w czasie wyraża
7
zależność:
Z x1
∂ Z x2
∂
f (q, t, x)dx.
q(t, x)dx = f (q, t, x1 ) − f (q, t, x2 ) =
∂t x1
x2 ∂x
(1.11)
Zależność to znana jest jako postać całkowa prawa zachowania. Zakładając
odpowiednią regularność funkcji podcałkowych możemy zapisać równoważnie prawo
zachowania w postaci różniczkowej:
∂
∂
q(t, x) +
f (q, t, x) = 0.
∂t
∂x
Adwekcja (łac. advectio - transport) jest zjawiskiem przenoszenia pewnej
substancji związanym z przepływem pewnej cieczy. W ogólności może być unoszona
pewna zachowywana własność jak masa, pęd, energia, zasolenie, czy wilgotność (w
przypadku gdy ośrodkiem jest powietrze) i możemy rozpatrywać kilka tych własności
(być może powiązanych ze sobą) jednocześnie: q : U 7→ Rm . Przenoszona substancja
nie powinna znacząco wpływać na ruch ośrodka. W naszym jednowymiarowym
przypadku możemy modelować np. transport zanieczyszczeń w wodzie w pewnej
rurce. W przypadku adwekcji funkcja strumienia zależy od prędkości cieczy:
f (x, t) = u(x, t)q. Najprostszy przypadek zachodzi, gdy u = const. Wtedy równanie
adwekcji można zapisać jako:
qt + uqx = 0.
(1.12)
Zauważmy, że nie uwzględnia ono takich zjawisk jak dyfuzja, czy zmiana ilości
substancji w wyniku reakcji oraz występowania źródeł i ujść.
Zapiszmy wzór na pochodną kierunkową q, w pewnym kierunku l określonym
przez kąty α, β między l i osiami współrzędnych:
∂
q = qt cos α + qx cos β.
∂l
Znormalizujmy wektor v = [1, u]:
ṽ =
1
u
v
√
= [√
,
].
kvk
1 + u2
1 + u2
Widzimy więc, że pochodna kierunkowa wzdłuż osi ṽ = [cos α, cos β] się zeruje [7].
To oznacza, że q jest stała na prostych o równaniu x = u(t − t0 ) + x0 . Stąd też
bierze się nazwa równania (1.12): profil funkcji jest „przenoszony” z czasem. Zwykle
warunek początkowy mamy dany dla t = 0: q(0, x) = g(x), x ∈ R. Jeśli g jest dana
na przedziale ograniczonym, to powinny zostać także określone warunki brzegowe.
Pozwala nam to na znalezienie rozwiązania równania (1.12).
8
Jeśli prędkość cieczy u(x, t) zmienia się wzdłuż osi x, to dla równania:
qt + uqx = −ux q
układ charakterystyk ma postać:

d


t(s)

 ds




= 1,
d
x(s) = u,
ds
d
q(s) = −ux q.
ds
Szczególnym przypadkiem tego równania jest nielepka postać równania Burgersa:
przyjmujemy, że prędkość u = 12 q [4]. Otrzymujemy w ten sposób równanie
nieliniowe:
qt + qqx = 0.
Krzywe charakterystyk spełniają zależność:
x0 (t) = q(x(t)).
Natomiast szukana funkcja:
d
∂
∂
q(x(t), t) = q(x(t), t) +
q(x(t), t)x0 (t) = 0
dt
∂t
∂x
jest stała wzdłuż tych charakterystyk, z czego wynika, że są one prostymi
o nachyleniu zależnym do wartości q w danym punkcie.
Znajomość dokładnych rozwiązań analitycznych równania adwekcji pozwala na
porównanie i analizę zachowania schematów numerycznych dla funkcji początkowych
o szczególnych własnościach.
9
Rozdział 2
Metody numeryczne
rozwiązywania równań
różniczkowych
Metody analityczne rozwiązywania równań różniczkowych prowadzą często do
rozwiązań bardzo skomplikowanych i trudnych do analizy, co utrudnia lub nawet
uniemożliwia poznanie istoty oraz specyficznych własności danego zagadnienia. Co
więcej, w wielu przypadkach może nie być możliwe przedstawienie rozwiązania
przy użyciu skończonej liczby funkcji elementarnych. Tutaj z pomocą przychodzą
metody numeryczne. Ich użycie pozwala przede wszystkim na symulację zjawiska.
Oczywiście podobnie jak w przypadku metod analitycznych nie istnieje jedna metoda
badania równań różniczkowych, tak też pewien algorytm numeryczny stosowany z
powodzeniem do problemów jednej klasy może dać dalekie od rzeczywistości wyniki
dla innego, nawet z pozoru podobnego równania.
Z wykorzystaniem schematów numerycznych wiąże się dyskretyzacja. Prowadzi
ona do błędów przybliżeń charakterystycznych dla danej metody. Błąd globalny
jest różnicą między rozwiązaniem dokładnym a przybliżonym. Natomiast jeśli dla
zadanych danych obliczymy błąd, jaki powstaje w pojedynczym kroku czasowym,
wówczas mamy do czynienia z błędem lokalnym. Z użyciem cyfrowych maszyn
liczących wiąże się też błąd zaokrąglenia [1].
Pewną intuicją przy dokonywaniu dyskretyzacji równania jest przybliżenie
pochodnych różnicami skończonymi. Rozwińmy szukaną funkcję f (x) w szereg
Taylora:
f (n−1) (x0 ) n−1
f 00 (x0 ) 2
h + ... +
h
+ O(hn ).
f (x0 + h) = f (x0 ) + f (x0 )h +
2!
(n − 1)!
0
10
Dla n = 2 mamy:
f (x0 + h) − f (x0 )
+ O(h).
(2.1)
h
Widzimy, że błąd jest rzędu O(h). Aby go zminimalizować, moglibyśmy na przykład
zmniejszyć h. Jednak ze względu na błędy zaokrągleń nie zawsze prowadzi to do
poprawy. Obliczona tą metodą pochodna cos0 (2) przy użyciu 64-bitowego typu
double wynosi dla danych wartości:
f 0 (x0 ) =
h = 2−8 : −0.90848232860788868947565788403153419494628906250000,
h = 2−20 : −0.90929722838336601853370666503906250000000000000000,
h = 2−47 : −0.90625000000000000000000000000000000000000000000000.
Widzimy więc, że dla małych h licznik i mianownik użytego przybliżenia mają mało
cyfr znaczących, przez co dokładność maleje wraz z h począwszy od pewnej wartości
granicznej [1].
Obliczmy teraz szereg Taylora dla n = 3 w punktach x0 − h i x0 + h oraz
odejmijmy je stronami:
f 0 (x0 ) =
f (x0 + h) − f (x0 − h)
+ O(h2 ).
2h
(2.2)
Jest to tzw. iloraz różnicowy centralny stosowany do oszacowania pochodnej f 0 (x0 ).
Jego błąd jest rzędu O(h2 ). Innym często używanym przybliżeniem pochodnej f 00 (x0 )
jest:
f (x0 + h) − 2f (x0 ) + f (x0 − h)
+ O(h2 ).
(2.3)
f 00 (x0 ) =
h2
Ważnym krokiem przy dokonywaniu dyskretyzacji jest określenie dla jakich
punktów będziemy dokonywać obliczeń. Zwykle mając zadany warunek początkowy
dla t0 = 0, będziemy aproksymować rozwiązania w tych punktach po upływie
czasu ∆t. Oczywiście punkty początkowe mogą być rozmieszczone nierównomiernie.
Można wtedy dokonać interpolacji. Rozrzedzenie siatki może być celowe, jeśli w
pewnych obszarach nie interesują nas dokładne wyniki. Zajmiemy się przypadkiem
jednorodnym. Punkty będą znajdować się na n-wymiarowej kracie wyznaczonej
przez wektory postaci ki = [0, . . . , ki , . . . , 0]. Dodatkowym wymiarem, który
możemy uwzględniać jest czas. Ograniczając się do przypadku jednowymiarowego
współrzędne punktów kraty numerycznej mają postać:
(xp + i∆x, n∆t) :
n = 0, 1, . . . ;
11
i = 0, 1, . . . , ie .
Przy analizie metody numerycznej istotna jest stabilność. Oznacza ona, że błędy
obliczeń nie wpłyną znacząco na rozwiązanie i nie będzie ono się zasadniczo różniło
od rozwiązania dokładnego. Widzieliśmy, że rozwiązanie hiperbolicznego PDE (1.10)
jest kombinacją liniową funkcji, które są rozwiązaniami równań adwekcji. Dla
każdego z nich prędkością unoszenia jest odpowiednia wartość własna λi macierzy
A. Prędkości te wyznaczają zbiór punktów dla tp < t, od których zależy rozwiązanie
w danym punkcie. W ten sposób definiuje się dziedzinę zależności rozwiązania
analitycznego
Dtp (x, t) = {xd : |x − xd | < max (λi )(t − td )}.
Dla skalarnego równania adwekcji należy do niej 1 punkt:
Dtp (x, t) = {x − u(t − tp )}.
Jednak w przypadku równania przewodnictwa cieplnego jest to cała przestrzeń.
Analogicznie definiuje się dziedzinę zależności dla metody numerycznej jako zbiór
punktów z poprzednich kroków, mających wpływ na obliczenia dla danego punktu.
Wiąże się z tym warunek konieczny stabilności metody (znany jako warunek CFL):
dziedzina zależności rozwiązania analitycznego powinna zawierać się w dziedzinie
zależności metody numerycznej [3]. Wpływa to na dobór siatki i ogranicza w pewien
sposób iloraz:
u∆t
(2.4)
ζ=
∆x
zwany liczbą Couranta.
O schematach dla równań zwyczajnych zapisanych w postaci ogólnej:
xn + αk−1 xn−1 + . . . + α0 xn−k = h(βk fn + . . . + β0 fn−k )
mówimy, że są wielokrokowe, jeśli k > 1 [5]. W przypadku, gdy βk = 0,
schemat nazywamy jawnym, w przeciwnym razie - niejawnym. Podobnie możemy
scharakteryzować schematy dla PDE: jeśli do obliczenia wartości w punkcie siatki
(xj , tk ) wykorzystujemy wyniki z k > 1 poprzednich kroków, to schemat jest
wielokrokowy. Schemat będzie niejawny, jeśli wyznaczenie wartości dla czasu tk
wymaga rozwiązania równania wiążącego nieobliczone dotąd wartości z tego kroku.
2.1. Metody różnic skończonych
Metody różnic skończonych (ang. finite-difference methods) polegają na
zastąpieniu pochodnych występujących we wzorze analitycznym ilorazami
12
różnicowymi i przybliżeniami wyznaczonymi ze wzoru Taylora. W związku z tym
ważne jest założenie o istnieniu pochodnych odpowiedniego rzędu poszukiwanej
funkcji. W przypadku równania adwekcji można skorzystać z faktu, że:
k
∂kq
∂kq
k∂ q
=
−u
=
.
.
.
=
(−u)
.
∂tk
∂tk−1 ∂x1
∂xk
Związek ten pozwala zastąpić pochodne czasowe pochodnymi przestrzennymi.
Podejście to sprowadza się do poszukiwania rozwiązań w punktach qin = q(xn , ti )
siatki. Zwykle pomijamy przy tym analizę zachowania funkcji pomiędzy tymi
punktami.
Nasuwa się pomysł zastąpienia w równaniu adwekcji (1.12) pochodnych:
czasowej - ilorazem różnicowym wprzód i przestrzennej - ilorazem centrowanym
(nie chcielibyśmy wyróżniać któregoś kierunku). Prowadzi to do schematu FTCS
(Forward-Time Central-Space):
n
n
qi+1
− qi−1
qin+1 − qin
+u
= 0.
∆t
2∆x
(2.5)
Niestety otrzymany w ten sposób schemat jest niestabilny dla równań
hiperbolicznych [3].
2.1.1. Metoda pod wiatr
Innym podobnym pomysłem rozwiązania równania adwekcji (1.12) jest użycie
przybliżeń pierwszego rzędu. Jeśli substancja o gęstości q porusza się w kierunku
zgodnym ze wzrostem współrzędnej przestrzennej (u > 0), wtedy przy obliczaniu
ilorazu dla qx (xi , tn ) uwzględnimy wartości z „lewej” strony (od tej strony substancja
napływa):
n
q n − qi−1
qin+1 − qin
+u i
= 0, u > 0.
(2.6)
∆t
∆x
n
W przeciwnym razie wykorzystamy qi+1
. Niesymetryczność tych oszacowań jest
zgodna z sensem fizycznym adwekcji. Z tego też względu schemat ten jest określany
jako dyskretyzacja pod wiatr (ang. upwind ). Uwzględnienie innych punktów jest
zbędne i wprowadziłoby „wygładzanie” funkcji. Schemat ten jest stabilny dla 0 ¬
| u∆t
| ¬ 1. Wzór (2.6) możemy zapisać w sposób ogólny:
∆x
qin+1 = qin − ∆t(min (u, 0)qx+ + max (u, 0)qx− ),
13
gdzie:
n
n
− qin
qi+1
qin − qi−1
−
=
, qx =
.
∆x
∆x
Możliwe jest też użycie lepszych przybliżeń (np. drugiego rzędu dokładnych):
qx+
qx+ =
n
n
− 3qin
+ 4qi+1
−qi+2
,
2∆x
(2.7)
n
n
3qin − 4qi−1
+ qi−2
.
2∆x
(2.8)
qx− =
2.1.2. Schemat skoku żaby
Jeśli wykorzystamy przybliżenie pochodnymi centrowanymi zarówno w czasie,
jak i w przestrzeni, otrzymamy schemat skoku żaby (ang. leap-frog):
qin+1 = qin−1 −
u∆t n
n
(q − qi−1
).
∆x i+1
(2.9)
2.2. Metoda Laxa-Friedrichsa
Jeśli do schematu Eulera (2.5) dodamy czynnik dyspersyjny, to otrzymamy
metodę Laxa-Friedrichsa [4]. Modyfikacja sprowadza się do zastąpienia qin przez
średnią sąsiednich punktów:
n
q n + qi+1
.
qin ≈ i−1
2
Uzyskujemy w ten sposób:
qin+1 =
n
n
n
qi+1
+ qi−1
q n − qi−1
− u∆t i+1
.
2
2∆x
Zauważmy jeszcze, że dyskretyzując równanie adwekcji z dyfuzją:
qt + uqx = qxx
w sposób następujący:
n
n
q n − qi−1
q n − 2qin + qi+1
qin+1 − qin
+ u i+1
= i−1
∆t
2∆x
(∆x)2
otrzymamy (2.10), jeśli przyjmiemy:
=
(∆x)2
.
2∆t
14
(2.10)
Dzięki wprowadzeniu członu dyfuzyjnego otrzymujemy metodę stabilną dla:
u∆t ∆x ¬ 1.
2.3. Metoda Laxa-Wendroffa
Zapiszmy rozwinięcie Taylora dla qin+1 uwzględniając 3 pierwsze wyrazy oraz
zastępując pochodne czasowe przestrzennymi:
q(x, t + ∆t) = q − u∆tqx +
1
(u∆t)2 qxx .
2
Używając pochodnych centralnych otrzymujemy schemat Laxa-Wendroffa [3]:
qin+1
=
qin
1 u∆t n
1
n
−
(qi+1 − qi−1
)+
2 ∆x
2
u∆t
∆x
!2
n
n
(qi+1
− 2qin + qi−1
).
(2.11)
Innym sposobem uzyskania tego schematu jest wyznaczenie ze schematu Laxan+1/2
n+1/2
Friedrichsa wartości qi−1/2 oraz qi+1/2 przyjmując o połowę mniejsze ∆x i ∆t. Dla
drugiego z szukanych przybliżeń otrzymamy wyrażenie:
n+1/2
qi+1/2 =
n
q n − qin
+ qin
qi+1
− u∆t i+1
.
2
2∆x
Drugim krokiem jest użycie wyników do obliczenia qin+1 :
n+1/2
n+1/2
qi+1/2 − qi−1/2
qin+1 − qin
= −u
.
∆t
∆x
Po uproszczeniu dostaniemy (2.11). To podejście jest jednak ogólniejsze i można je
zastosować dla innej funkcji strumienia.
2.4. Metoda niejawna Wendroffa
Zapiszmy ilorazy pochodnych czasowych w punktach (i, n + 0.5) i (i + 1, n + 0.5)
[1]. Jeśli funkcja jest regularna, to uśrednienie ich przybliża pochodną w punkcie
(i+0.5, n+0.5). Podobnie postępujemy z pochodnymi przestrzennymi. Podstawiając
wyniki do (1.12) otrzymujemy schemat niejawny (Rys. 2.1):
1
2
n+1
n
− qi+1
qin+1 − qin qi+1
+
∆t
∆t
!
u
+
2
15
n+1
n
qi+1
− qin qi+1
− qin+1
+
∆x
∆x
!
= 0.
Błąd metody Wendroffa wynosi O((∆x)2 + (∆t)2 ).
(i,n+1)
(i+1,n+1)
(i+0.5,n+0.5)
Rysunek 2.1: Wykorzystywane węzły w niejawnej metodzie Wendroffa.
2.5. Metoda Beama-Warminga
Metodę Beama-Warminga otrzymujemy w podobny sposób jak metodę LaxaWendroffa [8]. Modyfikacja polega za zastąpieniu pierwszej pochodnej przestrzennej
wyrażeniem (2.7) lub (2.8), np.:
qin+1
=
qin
n
n
+ qi−2
3q n − 4qi−1
1
+
− u∆t i
2∆x
2
u∆t
∆x
!2
n
n
(qin − 2qi−1
+ qi−2
).
(2.12)
2.6. Metoda MacCormacka
Metoda ta dotyczy w ogólności wyrażenia (1.9), ale dla zagadnienia liniowego jest
równoważna metodzie Laxa-Wendroffa [8]. Można wyodrębnić następujące kroki:
• etap przewidywania (ang. predictor step) - proste przybliżenie:
q̃in+1 = qin − ∆t
n
fi+1
− fin
.
∆x
• etap korekcji (ang. corrector step)
n+1/2
qin+1 − qi
∆t/2
=
n+1
f˜in+1 − f˜i−1
,
∆x
gdzie f˜in+1 = f (q̃in+1 ).
• postać końcowa otrzymana po zastosowaniu przybliżenia
n+1/2
qi
≈
16
q̃in+1 − qin
2
w rezultacie wynosi:
qin+1 = (qin + q̃in+1 −
∆t ˜n+1 ˜n+1
(f
− fi−1 ))/2.
∆x i
2.7. Metody objętości skończonych
Zamiast przybliżać rozwiązanie szukanej funkcji w punktach możemy przestrzeń
X, T podzielić na komórki, dla których będziemy obliczać średnią wartość q w
przedziale:
Ii = [xi−1/2 , xi+1/2 ].
Będziemy ją zapisywać następująco:
Qni
1 Z
=
q(x, tn )dx,
∆x Ii
gdzie ∆x = xi+1/2 − xi−1/2 jest rozmiarem i-tej komórki numerycznej.
Całkując (1.11) względem czasu otrzymujemy:
Qn+1
i
=
Qni
1
+
∆x
Z tn+1
tn
f (xi−1/2 , t)dt −
Z tn+1
tn
f (xi+1/2 , t)dt .
Będziemy rozpatrywać zmianę Qni w wyniku przepływów przez brzegi komórki [3].
Ponieważ nie wiemy jak zmienia się q(xi , t ∈ (tn , tn+1 )), nie możemy wyznaczyć
dokładnych całek ze strumienia, występujących w powyższym wyrażeniu. Metody
objętości skończonych (ang. Finite Volume Methods) sprowadzają się zatem do
znalezienia dla nich przybliżeń Fin . Otrzymane schematy mają postać ogólną:
Qn+1
= Qni −
i
∆t n
n
(F
− Fi−1/2
).
∆x i+1/2
(2.13)
Takie podejście pozwala na uwzględnienie własności zachowawczych przy
konstrukcji metod numerycznych oraz umożliwia poszerzenie klasy rozwiązań
o rozwiązania nieróżniczkowalne, zwane rozwiązaniami słabymi [3].
Ponieważ (2.13) można zapisać w równoważnej postaci:
n
n
Fi+1/2
− Fi−1/2
Qn+1
− Qni
i
=−
,
∆t
∆x
metody objętości skończonych można traktować jako metody różnic skończonych.
17
Dla przykładu metodę Laxa-Friedrichsa możemy uzyskać przyjmując:
"
n
Fi+1/2
#
∆t
1
=
f (Qni ) + f (Qni+1 ) −
(f (Qni+1 ) − f (Qni )) .
2
∆x
2.8. Metoda Godunowa
W przypadku metod objętości skończonych zdyskretyzowana funkcja q w
kroku ti , była przedziałami stała. Nieciągłości mogły się pojawić jedynie na
brzegach komórek numerycznych. Idea zaproponowana przez Godunowa polega
na obserwacji, że funkcję przepływu numerycznego można wyznaczyć rozwiązując
problem Riemanna dla nieciągłości między komórkami [4].
Problem Riemanna. Zagadnienie znalezienia rozwiązania (1.9), mając zadany
problem początkowy z pojedynczą nieciągłością postaci:


q(x, 0) = 
ql : x < 0,
qr : x > 0
nazywamy problemem Riemanna.
Wektory ql i qr możemy zapisać jako kombinację wektorów własnych:
ql =
m
X
vil ri ,
qr =
m
X
vir ri ,
i=1
i=1
gdzie:


vil (x, t) : x − λi t < 0,
vi (x, t) =  r
vi (x, t) : x − λi t > 0.
Korzystając z konwencji Iversona rozwiązanie możemy zapisać następująco:
q(x, t) =
m
X
(vil + (vir − vil )[x − λi t > 0])ri .
i=1
Oznacza to, iż rozwiązanie sprowadza się do przedstawienia skoku qr − ql w postaci
kombinacji liniowej wektorów własnych A. Dla problemu adwekcji poszczególne
„składowe” przemieszczają się z prędkościami charakterystycznymi λi .
Metoda Godunowa polega na wyrażeniu przepływu w punkcie xi+1/2 poprzez
rozwiązanie problemu Riemanna. Dla najprostszego przypadku skalarnego równania
adwekcji mamy:
n
Fi+1/2
= [u > 0]uQni + [u < 0]uQni+1 .
18
Jest to jeszcze jeden sposób na uzyskanie metody pod wiatr. Z opisanym schematem
postępowania wiąże się ograniczenie na rozmiar komórki: nieciągłości niesione przez
fale z jednego brzegu xi+1/2 nie mogą dotrzeć do sąsiednich w czasie ∆t. Ze względu
na warunek stabilności schematu numerycznego liczba Couranta ζ jest ograniczona
następująco:
u∆t
ζ=
¬ 1.
∆x
2.9. Metody wyższych rzędów
Metoda Godunowa zakłada rekonstrukcję q w komórce funkcjami stałymi. Aby
osiągnąć lepszą dokładność, należy skonstruować wielomiany wyższego stopnia
na postawie wartości w sąsiednich komórkach. Następnymi krokami dla adwekcji
będzie translacja otrzymanej funkcji oraz jej uśrednienie. Częstą praktyką jest
wykorzystanie funkcji liniowych:
q̃ n (x) = Qni + σin (x − xi ),
x ∈ Ii .
(2.14)
Tutaj współczynnik kierunkowy σin jest funkcją nachylenia. Otrzymujemy schemat
ogólny postaci [3]:
Qn+1
= Qni −
i
u∆t
u∆t n
n
(Qi − Qni−1 ) −
(∆x − u∆t)(σin − σi−1
).
∆x
2∆x
(2.15)
W zależności od doboru funkcji nachylenia uzyskujemy różne metody. Przedstawia
to Tabela 2.1.
Tabela 2.1: Sposoby doboru nachylenia σin .
σin
0
n
Qn
i+1 −Qi−1
2∆xn
Qn
i −Qi−1
∆x n
Qn
i+1 −Qi
∆x n
Qn
Qn −Qn
i+1 −Qi
minmod( ∆x , i ∆xi−1 )
19
metoda
metoda Godunowa
metoda Fromma
metoda Beama-Warminga
metoda Laxa-Wendroffa
metoda minmod
Funkcja minmod zdefiniowana jest następująco:






min (xi ) :
xi > 0,
i
minmod(x1 , . . . , xn ) =  max (xi ) :




V
V
xi < 0,
i
wpp.
0:
Metody drugiego rzędu mogą prowadzić do powstania oscylacji w pobliżu
nieciągłości [3]. Z tego względu chcielibyśmy tak połączyć metody pierwszego i
drugiego rzędu, aby wykorzystać zalety obu metod. Aby zapewnić, że schemat nie
wprowadza oscylacji, trzeba nałożyć pewne ograniczenia. Korzysta się w tym celu z
pojęcia całkowitej wariancji, która jest zdefiniowana następująco [9]:
T V (Q) =
X
|Qi − Qi−1 |.
i
Jeśli wartość ta w kolejnych krokach nie rośnie, to można pokazać, że oscylacje nie
powstaną.
Strumień F możemy otrzymać całkując q̃ n (x) po czasie na brzegu komórki. Dla
równania adwekcji mamy [3]:
n
Fi−1/2
= [u >
0]uQni−1
+ [u <
0]uQni
!
u∆t |u|
σin ∆x.
1−
+
∆x 2
Zapisując ogranicznik nachylenia jako:
σin
n
qi+1
− qin
φ(θin ),
=
∆x
gdzie θin jest pewną miarą gładkości, używamy funkcji ogranicznika strumienia
(zwanej też filtratorem) φ. Zwykle przyjmuje się
θin =
qn − qn−1
.
qn+1 − qn
Tabela 2.2 przedstawia kilka wybranych ograniczników. Szary obszar na
wykresach został zdefiniowany przez Sweby - zawarte w nim funkcje ograniczników
zachowują warunek zmniejszania ogólnej wariancji (TVD) oraz są dokładne drugiego
rzędu.
20
Tabela 2.2: Ograniczniki strumienia.
Ogranicznik van Leera
Ogranicznik van Albada (1)
2
2
1
1
1
φ=
2
1
r+|r|
1+|r|
φ=
2
r2 +r
r2 +1
Ogranicznik van Albada (2)
Ogranicznik UMIST
2
2
1
1
1
φ=
2
1
2r
1+|r|
2
φ = max(0, min(2r, 0.25 + 0.75r, 0.75 +
0.25r, 2))
Ogranicznik Sweby
Ogranicznik superbee
2
2
1
1
1
2
1
φ = max(0, min(βr, 1), min(r, β))
2
φ = max(0, min(2r, 1), min(r, 2))
Ogranicznik smart
Ogranicznik ospre
2
2
1
1
1
2
1
2
φ = 1.5(r2 + r)/(r2 + r + 1)
φ = max(0, min(2r, 0.25 + 0.75r, 4))
21
Tabela 2.2: Ograniczniki strumienia.
Ogranicznik Osher
Ogranicznik MC
2
2
1
1
1
2
1
φ = max(0, min(r, β))
φ = max(0, min(2r, 0.5(1 + r), 2))
Ogranicznik minmod
Ogranicznik Koren
2
2
1
1
1
2
2
1
2
φ = max(0, min(1, r))
φ = max(0, min(2r, (1 + 2r)/3, 2))
Ogranicznik HQUICK
Ogranicznik HCUS
2
2
1
1
1
φ=
2
1
2(r+|r|)
r+3
φ=
22
1.5(r+|r|)
r+2
2
Rozdział 3
Projekt własny - program
komputerowy rozwiązujący
równanie adwekcji
Przedstawione w poprzednim rozdziale metody rozwiązywania równania
adwekcji zostały zaimplementowane przez autora pracy w języku C++. Do
stworzenia interfejsu użytkownika został wykorzystany framework Qt. Dzięki temu
aplikacja jest przenośna. Program został przetestowany na systemach Mac OS X i
GNU/Linux. Jednak możliwe jest uruchomienie go również w innych środowiskach prawdopodobnie bez konieczności wprowadzenia zmian w kodzie. Jednym z ważnych
założeń projektowych Qt jest użycie mechanizmu slotów i sygnałów. Wprowadza to
pewną dynamikę w komunikacji między obiektami oraz znacznie upraszcza tworzenie
interfejsu użytkownika.
W dalszej części pracy zostanie omówiony interfejs graficzny oraz aspekty
implementacyjne. Następnie zostaną opisane wyniki zastosowania wybranych metod
do rozwiązania równania adwekcji (1.12).
3.1. Interfejs użytkownika
Oprócz głównego okna, na którym rysowany jest wykres funkcji, do sterowania
obliczeniami służą osobne palety.
Do zadania warunku początkowego służy paleta Initial Problem (Rys. 3.1a).
Można w niej wybrać funkcję (sin, sinc, Gaussa, impuls trójkątny oraz prostokątny)
oraz ustawić jej parametry takie jak amplituda i okres. Następnym krokiem jest
określenie, w ilu punktach funkcja ma zostać spróbkowana oraz podanie innych
23
parametrów siatki numerycznej. Ponieważ niektóre wielkości są ze sobą powiązane,
zmiana jednej z nich powoduje automatyczne dostosowanie innych wartości.
(a) Zadanie problemu początkowego.
(b) Sterowanie rozwiązaniem.
Rysunek 3.1: Palety programu.
Paleta Solver (Rys. 3.1b) pozwala na wybranie schematu numerycznego oraz na
uruchomienie i zatrzymanie obliczeń. Aby rozpocząć obliczenia od początku, należy
najpierw kliknąć w przycisk stop. Możliwe jest też przyspieszenie obliczeń przy
użyciu suwaka, przy czym minimalny odstęp pomiędzy kolejnymi krokami wynosi 1
ms.
3.2. Szczegóły implementacyjne
Do najważniejszych klas w programie należą:
• GraphWidget
Ta klasa dziedziczy po klasie QWidget i jest odpowiedzialna za rysowanie
wykresu, co jest zrealizowane w metodzie paintEvent. Do tego celu jest
wykorzystywany silnik graficzny Qt.
• InitialProblem
Obiekt tej klasy przechowuje parametry problemu początkowego, które są
wykorzystywane do generowania funkcji początkowej oraz do inicjacji obiektów
rozwiązujących równanie.
• FunctionVector
Przechowuje wartości w punktach siatki, które są wykorzystywane do
24
rysowania wykresu i do obliczeń. Może przechowywać k wektorów z wynikami
obliczeń z k ostatnich kroków czasowych.
• AdvectionSolverThread
Jest klasą wątku, który steruje obliczeniami. Po wykonaniu każdego kroku
czasowego wysyła on komunikat do obiektu klasy GraphWidget o konieczności
odświeżenia wykresu.
• ThreadTimer
Stanowi realizację licznika czasu (ang. timer ) przy użyciu wątku. Takie
rozwiązanie pozwala uniezależnić sterowanie wątkiem obliczeń AdvectionSolverThread od wątku związanego z interfejsem użytkownika.
• AdvectionSolver
Jest to klasa abstrakcyjna. Dziedziczą po niej inne klasy implementujące
konkretny schemat numeryczny.
Wszystkie zaimplementowane metody są jednokrokowe z wyjątkiem schematu
leap-frog. Przy jego inicjacji została wykorzystana metoda upwind do wykonania
obliczeń w pierwszym kroku.
Ze względu na symetrię zagadnienia zakłada się dodatnią prędkość u w równaniu
adwekcji (1.12). Również aby obserwować zachowanie się rozwiązania w większym
przedziale czasu, zostały przyjęte okresowe warunki brzegowe, tzn. wartości z prawej
strony wektora (. . . , xn−1 , xn ) są traktowane jako (. . . , x−2 , x−1 ) i wykorzystywane
(w zależności od metody) do obliczeń w punktach z lewej strony (x0 ,x1 ,. . . ).
Na systemach wieloprocesorowych możemy uzyskać przyspieszenie w naturalny
sposób poprzez uruchomienie obliczeń w oddzielnym wątku. W szczególności
przedstawione w pracy schematy można w bardzo prosty sposób zaimplementować
tak, aby obliczenia były wykonywane w kilku wątkach. Mimo, iż w programie
jest użyty tylko jeden wątek do obliczeń, wszystkie metody można z łatwością
uogólnić na większą ich liczbę. Przy czym można się sugerować wartością funkcji
QThread::idealThreadCount(), której zwracana (zgodnie z dokumentacją) wartość
jest związana z liczbą rdzeni w systemie. Alternatywnym rozwiązaniem, które
zostało użyte przy implementacji, jest wykorzystanie biblioteki OpenMP. Pozwoliło
to w prosty sposób na zrównoleglenie obliczeń bez wprowadzania jednocześnie
dodatkowych konstrukcji związanych z zarządzaniem wątkami.
Jednym z założeń projektowych było zapobieżenie modyfikacji danych przez
wątek liczący podczas rysowania wykresu. Do synchronizacji jest stosowana
blokada klasy QMutex. Algorytmy synchronizacyjne (zaimplementowane w klasie
25
FunctionVector ) sprowadzają się do pomijania wektora „odczytywanego” podczas
wyboru wektora do zapisu. Pole składowe readVector wskazuje na wektor aktualnie
odczytywany, a zmiany tego pola dokonywane są w sekcjach krytycznych.
Synchronizacja realizowana jest w czasie jednostkowym. Mimo to moglibyśmy chcieć
nie dopuścić do sytuacji, w której wątek liczący czeka na uzyskanie blokady w
funkcji updateReadableVector(). Rozważmy następującą realizację synchronizacji dla
schematów jednokrokowych:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
double *FunctionVector::getReadersVector(){
// metoda pozwalająca na uzyskanie wektora do odczytu
// wywoływana na początku rysowania wykresu
if (readVectorDirty) return freeVector;
readersVectorLock.lock();
return readVector;
}
void FunctionVector::finishReading(){
// metoda wywoływana po zakończeniu odczytu przez wątek rysujący
readersVectorLock.unlock();
}
void FunctionVector::updateReadableVector(){
// metoda wywoływana przez wątek sterujący obliczeniami
// w celu ustawienia nowego wektora ’’do odczytu’’
double *swapVector=writeVector;
16
readVectorDirty=false;
if (readersVectorLock.tryLock()){
writeVector=readVector;
readVector=swapVector;
readersVectorLock.unlock();
} else {
writeVector=freeVector;
freeVector=swapVector;
readVectorDirty=true;
}
17
18
19
20
21
22
23
24
25
26
27
}
Wątek rysujący działa następująco:
1
2
3
functionVector->getReadersVector();
// rysuj
functionVector->finishReading();
Wątek obliczeń wykonuje następujące operacje:
26
1
2
3
4
pobierz
pobierz
wykonaj
wywołaj
wektor do odczytu bez blokowania
wektor do zapisu
obliczenia
functionVector->finishReading(), aby uaktualnić wskazania na wektory
Zmienna readVectorDirty określa, czy wektor wskazywany przez readVector
zawiera wyniki obliczeń z ostatniego kroku. Jeśli tak nie jest, to wskazuje
na nie zmienna freeVector. Aby wykazać poprawność powyższych algorytmów,
wystarczy pokazać, że wektor uzyskany poprzez wywołanie getReadersVector()
nie jest modyfikowany przez wątek obliczeń. Istotnie, jeśli został zwrócony
freeVector, to powiedzie się uzyskanie blokady w updateReadableVector i nie
będzie on modyfikowany. Natomiast jeśli został zwrócony readVector, to
readersVectorLock.tryLock() zwróci false i nie będzie on również modyfikowany.
Ustawienie readVectorDirty=false przed próbą uzyskania blokady zabezpiecza przed
sytuacją, kiedy readVectorDirty=true, tryLock() zwróci false, wątek rysujący zwolni
blokadę i wywoła getReadersVector() (otrzymując freeVector ) i dopiero teraz nastąpi
wymiana wskaźników writeVector i freeVector. Łatwo się przekonać, że nie może
do tego dojść, jeśli zapewnimy, że readVectorDirty=false przed próbą uzyskania
blokady. Niestety teraz wątek rysujący może uzyskać nieaktualny wektor do odczytu.
Można temu zapobiec stosując np. dodatkowy semafor.
Możemy z łatwością uogólnić powyższy algorytm na przypadek metod
wielokrokowych.
Istotną kwestią konieczną do poprawności powyższego rozumowania jest fakt, że
Qt (podobnie jak niektóre inne biblioteki do konstrukcji GUI) wykonuje procedury
odświeżające w sposób sekwencyjny w jednym wątku. Dzięki temu bez wprowadzania
modyfikacji możemy użyć np. kilku instancji GraphWidget do wyświetlania tego
samego wektora. Ważne jest również, że mamy tylko jednego „pisarza” (nie
potrzebujemy więcej).
Powszechnie spotykanym rozwiązaniem jest użycie licznika czasu zaimplementowanego przy użyciu wątków. Oczywiście ze zbyt dużą liczbą wątków wiążą
się dodatkowe koszty związane z zarządzaniem nimi. Klasa QTimer jest jednak
związana z pętlą zdarzeń (ang. event loop) i podobnie jak w przypadku wielu
klas frameworku Qt nie jest bezpiecznym używanie jej w kilku wątkach. Z
tego względu została zaimplementowana klasa ThreadTimer. Steruje ona wątkiem
obliczeń klasy AdvectionSolverThread poprzez wykonywanie operacji release() na
semaforze. Natomiast wątek liczący po wykonaniu kolejnego etapu wywołuje metodę
acquire(). Metoda release() nie jest wykonywana częściej niż co 1 ms.
27
3.3. Symulacje numeryczne
Wizualizacja wyników obliczeń pozwala na porównanie zachowania się konkretnych schematów dla specyficznych funkcji początkowych. W przeprowadzonych
symulacjach funkcje początkowe były określone na przedziale (0, 10), miały
amplitudę równą 2, okres (w przypadku funkcji Gaussa jest to współczynnik
skali osi X) tak dobrany, aby widoczne było charakterystyczne zachowanie dla
poszczególnych metod. Liczba Couranta wynosiła 0.9, prędkość u = 1, a liczba
punktów siatki została ustawiona na 1000.
Należy podkreślić, iż już podczas generowania funkcji początkowej pojawiają się
błędy związane z dyskretyzacją, arytmetyką komputera i skończoną reprezentacją
funkcji.
Szara linia na wykresach odpowiada amplitudzie funkcji początkowych.
3.3.1. Schemat skoku żaby
Schemat skoku żaby (2.9) dawał stosunkowo dobre wyniki dla funkcji gładkich
(Rys. 3.2 (a) i (b)). W przypadku punktów nieróżniczkowalnych (np. dla impulsu
trójkątnego) pojawiły się delikatne oscylacje po stronie lewej (Rys. 3.2 (c)).
Natomiast w punktach nieciągłości pojawiają się znaczne oscylacje, zmieniające
całkowicie kształt funkcji (nie pokazano).
(a)
(b)
(c)
Rysunek 3.2: Wyniki symulacji wykonanych za pomocą schematu skoku żaby:
dla funkcji Gaussa (a), impulsu trójkątnego (b) i zaburzenia typu zęby piły (c).
W przypadku impuls trójkątnego widoczna jest dyfuzja numeryczna prowadząca do
obniżenia amplitudy.
3.3.2. Schematy pod wiatr i Laxa-Friedrichsa
Schematy pod wiatr (2.6) i Laxa-Friedrichsa (2.10) dawały podobne rezultaty w ekstremach funkcje zostały istotnie rozmyte (Rys. 3.3).
28
(a)
(b)
Rysunek 3.3: Wyniki symulacji dla schematów Laxa-Friedrichsa (a) i pod wiatr (b)
dla impulsu typu zęby piły.
3.3.3. Oscylacje w punktach nieciągłości
Zastosowanie metod Beama-Warminga (2.12), Laxa-Wendroffa (2.11) i Fromma
prowadzi do powstania oscylacji w punktach nieciągłości (Rys. 3.4 i 3.5). Przy tym
schemat Beama-Warminga prowadzi do oscylacji przed nieciągłością, a schematy
Laxa-Wendroffa i Fromma generują oscylacje po przeciwnej stronie. Oscylacje te są
wynikiem dyspersyjnych błędów numerycznych. Dyspersja numeryczna powoduje,
że krótkie fale poruszają się szybciej (wolniej) w przypadku schematu BeamaWarminga (Laxa-Wendroffa i Fromma).
(a) Beam-Warming
(b) Lax-Wendroff
(c) Fromm
Rysunek 3.4: Oscylacje w punktach nieciągłości dla impulsu prostokątnego.
(a) Beam-Warming
(b) Lax-Wendroff
Rysunek 3.5: Oscylacje w punktach nieciągłości dla impulsu typu zęby piły.
29
3.3.4. Metody wyższych rzędów
Zgodnie z opisem analitycznym przedstawionym w rozdziale 2.9 metody
wyższych rzędów są tak skonstruowane, aby nie tworzyły się błędne oscylacje nie
mające interpretacji fizycznej (Rys. 3.4 i 3.5). Z rysunków 3.6 i 3.7 wynika, że bardzo
dobre rezultaty otrzymamy stosując ogranicznik superbee. Jednak w przypadku tego
ogranicznika zauważalne jest „spłaszczenie” funkcji w ekstremach. Dość znaczne
wygładzanie występuje przy stosowaniu ogranicznika minmod.
(a) minmod
(b) superbee
(c) van Leer
Rysunek 3.6: Działanie wybranych ograniczników zastosowanych dla impulsu
prostokątnego.
(a) monotonized central
(b) minmod
(c) smart
(d) superbee
Rysunek 3.7: Działanie wybranych ograniczników zastosowanych dla impulsu typu
zęby piły.
Większość przedstawionych ograniczników bardzo dobrze się sprawdza dla
gładkich funkcji początkowych.
30
Podsumowanie
W tej pracy zostały zaprezentowane dwa główne podejścia do konstruowania
metod numerycznych dla równia adwekcji: metoda różnic skończonych oraz metoda
objętości skończonych. Omówiliśmy również krótko niezbędne podstawy analityczne.
Należy podkreślić, że mimo swojej prostoty równanie adwekcji ma zasadnicze
znaczenie dla zagadnień hiperbolicznych. Również wiele technik i spostrzeżeń
związanych z wyprowadzeniem schematów numerycznych ma charakter uniwersalny.
Ważną częścią pracy jest napisany przez autora pracy program, który pozwala
na sprawdzenie przedstawionych zagadnień w praktyce. Z przeprowadzonych
obserwacji wynika, że zwykle najlepsze rezultaty przy tworzeniu metody otrzymamy,
jeśli uwzględnimy zarówno charakter modelowanego zjawiska jak i konkretny
problem, który chcemy rozwiązać. W symulacjach przeprowadzonych w rozdziale
3.3 szczególnie dobrze sprawdził się ogranicznik superbee, również w punktach
nieciągłości.
31
Bibliografia
[1] D. Kincaid, W. Cheney, Analiza numeryczna, Wydawnictwa Naukowo-Techniczne,
Warszawa 2006.
[2] J. Ombach, Wykłady z równań różniczkowych wspomagane komputerowo – Maple,
Wydawnictwo Uniwersytetu Jagiellońskiego, Kraków 1999.
[3] R. J. LeVeque, Finite-Volume Methods for Hiperbolic Problems, Cambridge University
Press, Cambridge 2002.
[4] R. J. LeVeque, Computational Methods for Astrophysical Fluid Flow, Springer-Verlag,
1998.
[5] A. Palczewski, Równania różniczkowe zwyczajne, Wydawnictwa Naukowo-Techniczne,
Warszawa 2004.
[6] S. Łanowy, F. Przybylak, B. Szlęk, Równania różniczkowe, Wydawnictwo Politechniki
Śląskiej, Gliwice 2002.
[7] L. C. Evans, Równania różniczkowe cząstkowe, PWN, Warszawa 2008.
[8] K. Murawski, Analytical and numerical methods for wave propagation in fluids, World
Scientific, 2002.
[9] E. F. Toro, Riemann Solvers and Numerical Methods for Fluid Dynamics: A practical
Introduction, Springer-Verlag, 1999
[10] V. Misra, W. Gong, D. Towsley, Stochastic Differential Equation Modeling and
Analysis of TCP-Windowsize Behavior.
[11] http://wazniak.mimuw.edu.pl/index.php?title=Analiza matematyczna 2
[12] Dokumentacja Qt, http://doc.qtsoftware.com/
32