This demo example shows ...
In [3]:
%pylab inline
Vi ønsker å løse varmelikningen eksplisitt
Varmelikningen er
$\frac{\delta u}{\delta t} = \kappa \frac{\delta^2u}{\delta x^2}$
Diskretisert explisitt med hensyn på tid får vi
$\frac{1}{\Delta t}\left(u_i^{k+1} - u_i^{k}\right) = \frac{\kappa}{\Delta x^2} \left(u^k_{i-1} - 2u_i^k + u_{i+1}^k \right)$
og vår stensil
$u_i^{k+1} = su^k_{i-1} +(1-2s)u_i^k + su_{i+1}^k , \quad s=\frac{\kappa\Delta t}{\Delta x^2}$
Vi ønsker ikke å anta at vi har kartesiske grid, og vil derfor ha en stensil som beskriver fluxen over en face. Dette kan gjøres som følger:
$ \begin{eqnarray} \Delta u_i^k &=& u_i^{k+1} - u_i^k\\\ &=& su_{i-1}^k - 2su_i^k + s_{i+1}^k\\\ &=& s(u_{i-1}^k - u_i^k) - s(u_i^k - u_{i+1}^k)\\\ &=& F(u)^k_{i-1/2} - F(u)^k_{i+1/2} \end{eqnarray} $
$u_i^{k+1} = u_i^k + F(u)^k_{i-1/2} - F(u)^k_{i+1/2}$
Vi kan nå splitte beregningen opp i to deler:
Løsningen blir ustabil hvis vi ikke oppfyller CFL-kravet
$\frac{1}{2} \lt \frac{\kappa \Delta t}{\Delta x^2}$
eller med andre ord
$\Delta t \lt \frac{\Delta x^2}{2\kappa}$
Her er $u_i^k$ temperaturen i punktet $i\cdot\Delta x$ ved tid $k\cdot\Delta t$.
Vi trenger i tillegg randkrav. I vårt tilfelle benytter vi fixed randkrav, hvor
$u_0^k = r_0, u_n^k = r_1 \forall k$
In [11]:
import numpy as np
import time
import matplotlib.pyplot as plt
from IPython.display import clear_output
# Grid spacing
dx = 0.5
# Heat diffusion constant
kappa = 0.3
# Maximum time step size (constrained by CFL)
dt = dx*dx/(2*kappa)
# Number of grid cells
n = 10
# Boundary conditions
r0 = 0.5
r1 = 1.5
# Initial temperatures
u = np.linspace(0.0, 0.0, n)
u[0] = r0
u[n-1] = r1
def F(u_l, u_r):
return kappa*(u_l - u_r)
fig, ax = plt.subplots()
f = np.linspace(0.0, 0.0, int(n+1)) #n+1 interfaces for n cells
#Perform one timestep
for k in range(0, 50):
# Loop over all faces and calculate the flux
for i in range(1, n):
f[i] = F(u[i-1], u[i]) #f[i] corresponds to the flux between cell i and i-1 (F_{i-1/2})
# For each cell, loop over all faces for that cell, and sum the fluxes
for i in range(0, n):
u[i] = u[i] + (f[i] - f[i+1]) * dt / (dx*dx)
# Apply boundary conditions
u[0] = r0
u[n-1] = r1
# Plot the solution
x = np.linspace(0.0, n-1, n) + 0.5
plot(x, u, 'r.-', label='$u^{k+1}$')
plot(f, 'b.--', label='$f^{k}$')
pylab.ylim([r0-0.5,r1+0.5])
time.sleep(0.2)
clear_output()
display(fig)
ax.cla()
title("Time = " + str(dt*k))
legend()
plt.close()
In [ ]: