Nechť $a \in \mathbb R$ a $u_0 \in \mathbb C^1(\mathbb R \to \mathbb R)$. Počáteční úlohou pro rovnici advekce pak rozumíme nalézt funkci $u \in \mathbb C^1( \mathbb R\times [0,+\infty) \to \mathbb R)$ takovou, že $\forall x \in \mathbb R, \forall t>0$ je splněna rovnice \begin{equation} \frac{\partial u(x,t)}{\partial t} + a \frac{\partial u(x,t)}{\partial x} = 0 \end{equation} a navíc je $u(x,0)=u_0(x)$.
Analytické řešení je možné získat například pomocí metody charakteristik. Uvažujme v rovině $x-t$ nějakou křivku $x = \xi(t)$. Potom $$ \frac{d u(\xi(t),t)}{t} = \frac{\partial u}{\partial x} \frac{d\xi}{dt} + \frac{\partial u}{\partial t} $$ a tedy pokud $d\xi/dt = a$, je $du(\xi(t),t)/dt=0$ a $u$ je na této křivce konstantní. Křivky splňující rovnici $d\xi/dt=a$ nazýváme charakteristikami rovnice advekce. Charakteristiky jsou polopřímky $x = x_0 + a t$ a analytické řešení počáteční úlohy je $$ u(x,t) = u_0(x-at). $$
In [1]:
using PyPlot
In [2]:
Nx = 26; # Pocet bodu site na intervalu [0,1]
x = range(0, stop=1, length=Nx); # Souradnice bodu site
function u0(x) # Definice pocatecni podminky"""
if x<0.25 || x>0.75
return 0
else
return cos( 2*(2*x-1.0) * π ) + 1
end
end;
In [3]:
plot(x,[u0(xi) for xi in x], label="u0");
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u");
legend(loc="upper left");
Protiproudové (upwind) schéma
In [4]:
a = 1; # Rychlost advekce
dx = 1.0 / (Nx-1); # Velikost prostoroveho
dt = 0.5 * dx / abs(a) # Velikost casoveho kroku
u = [u0(xi) for xi in x]
uNew = copy(u)
t = 0
pocet_iteraci = round(Int, 0.2 / dt) # Vypocet provedeme do casu priblizne 0.2
for n = 1:pocet_iteraci
global t += dt
for i=2:Nx
uNew[i] = u[i] - a * dt / dx * (u[i] - u[i-1])
end
for i=2:Nx
u[i] = uNew[i]
end
end
u_upwind = copy(u);
In [5]:
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
Laxovo-Friedrichsovo (Rusanovovo) schéma
In [6]:
u = [u0(xi) for xi in x]
uNew = copy(u)
t = 0
for n = 1:pocet_iteraci
global t += dt
for i = 2:Nx-1
uNew[i] = (u[i+1]+u[i-1])/2.0 - a * dt / (2*dx) * (u[i+1] - u[i-1])
end
for i = 2:Nx-1
u[i] = uNew[i]
end
end
u_lf = copy(u);
In [7]:
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u_lf, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
Laxovo-Wendroffovo schéma
In [8]:
u = [u0(xi) for xi in x]
uNew = copy(u)
t = 0
pocet_iteraci = round(Int, 0.2 / dt) # Vypocet provedeme do casu priblizne 0.2
for n = 1:pocet_iteraci
global t += dt
for i = 2:Nx-1
uNew[i] = u[i] - a * dt / (2*dx) * (u[i+1] - u[i-1]) + (a*dt/dx)^2/2 * (u[i+1]-2*u[i]+u[i-1])
end
for i = 2:Nx-1
u[i] = uNew[i]
end
end
u_lw = copy(u);
In [9]:
plot(x, [u0(xi) for xi in x], label="u0")
plot(x,u, "o", label="u[i]");
plot(x, [u0(xi-a*t) for xi in x], "-r", label="presne")
ylim(-0.5,2.5); grid(true); xlabel("x"); ylabel("u"); legend(loc="upper left");
In [ ]: