'''
Solution of the advection equation by the Crank-Nicolson scheme with
and without added artificial diffusion (dissipation)
by Shelvean Kapita, 2022
'''
import numpy as np
import matplotlib.pyplot as plt
from scipy.sparse import diags
from scipy.sparse.linalg import spsolve
def u_0(x):
# val = np.exp(-x**2)
val = np.where(np.abs(x)<0.5, 1 -2*np.abs(x),0)
return val
mu = 0.5
eps = 1.0
J = 301
L = 10
h = L/(J-1)
k = mu*h
tfinal = 3
a = -eps/16
tsteps = int(np.round(tfinal/k))
x = np.linspace(-2,8,J)
v_0 = u_0(x)
u_ex = u_0(x-tfinal)
d1 = 0.25*mu*np.ones((v_0.size-5,))
d2 = np.ones((v_0.size-4,))
d3 = -d1
diagonals = [d2,d1,d3]
A = diags(diagonals, [0,1,-1]).tocsr()
diagonals1 = [d2,d3,d1]
B = diags(diagonals1,[0,1,-1]).tocsr()
b = B@v_0[2:J-2]
v = np.zeros((v_0.shape))
u = np.copy(v)
w_0 = np.copy(v_0)
d = a*(w_0[4:J]-4*w_0[3:J-1]+6*w_0[2:J-2]-4*w_0[1:J-3]+w_0[0:J-4])
f = b+d
for j in range(tsteps):
w = spsolve(A,b)
z = spsolve(A,f)
v[2:J-2] = w
u[2:J-2] = z
v[0],v[1],v[J-1],v[J-2] = 0, 0, 0, 0
u[0],u[1],u[J-1],u[J-2] = 0, 0, 0, 0
b = B@w
d = a*(u[4:J]-4*u[3:J-1]+6*u[2:J-2]-4*u[1:J-3]+u[0:J-4])
f = (B@z)+d
plt.plot(x,v,linewidth='1.5',label='CN',color='blue')
plt.plot(x,u,linewidth='1.5',label='CN+dissipation',color='red')
plt.plot(x,u_ex, linewidth='0.5',color='green',label='Exact')
plt.ylim(-0.5, 2.1)
plt.legend()
plt.show()
Crank Nicolson