Introduction to the problem
1-D 2nd order Convection-Diffusion equation
Three parts namely: transient term, convection term and diffusion term.
Initial condition:
where
(The IC is chosen for convenience to calculate the analytical solution)
Boundary condition: periodic BC
Analytical solution
Click here to see the further illustration of Analytical solution
Design Algorithm to Solve Problem
Discrete equation:
Forward Difference in time
Backward Difference in convection
Central difference in diffusion
Code
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from math import pi as PI
from math import exp as exp
def analytical_solution(NT, NX, TMAX, XMAX, NU):
DT = TMAX/(NT-1)
DX = XMAX/(NX-1)
u_analytical = np.zeros((NX,NT))
x = np.zeros(NX)
t = np.zeros(NT)
for i in range(0,NX):
x[i] = i*DX
for n in range(0,NT):
t = n*DT
for i in range(0,NX):
phi = exp( -(x[i]-4*t)**2/(4*NU*(t+1)) ) + exp( -(x[i]-4*t-2*PI)**2/(4*NU*(t+1)) )
dphi = ( -0.5*(x[i]-4*t)/(NU*(t+1))*exp( -(x[i]-4*t)**2/(4*NU*(t+1)) )
-0.5*(x[i]-4*t-2*PI)/(NU*(t+1))*exp( -(x[i]-4*t-2*PI)**2/(4*NU*(t+1)) ) )
u_analytical[i,n] = -2*NU*(dphi/phi) + 4
return u_analytical, x
def convection_diffusion(NT, NX, TMAX, XMAX, NU):
DT = TMAX/(NT-1)
DX = XMAX/(NX-1)
x = np.zeros(NX)
t = np.zeros(NT)
ipos = np.zeros(NX, dtype=int)
ineg = np.zeros(NX, dtype=int)
u = np.zeros((NX,NT))
# BC:
for i in range(0,NX):
x[i] = i*DX
ipos[i] = i+1
ineg[i] = i-1
ipos[NX-1] = 0
ineg[0] = NX-1
# IC
for i in range(0,NX):
phi = exp( -(x[i]**2)/(4*NU) ) + exp( -(x[i]-2*PI)**2 / (4*NU) )
dphi = -(0.5*x[i]/NU)*exp( -(x[i]**2) / (4*NU) ) - (0.5*(x[i]-2*PI) / NU )*exp(-(x[i]-2*PI)**2 / (4*NU) )
u[i,0] = -2*NU*(dphi/phi) + 4
for n in range(0,NT-1):
for i in range(0,NX):
u[i,n+1] = (u[i,n]-u[i,n]*(DT/DX)*(u[i,n]-u[ineg[i],n]) + NU*(DT/DX**2)*(u[ipos[i],n]-2*u[i,n]+u[ineg[i],n]))
return u, x
def plot_diffusion(u_analytical,u,x,NT,TITLE):
plt.figure()
ax=plt.subplot(111)
colour=iter(cm.rainbow(np.linspace(0,20,NT)))
for n in range(0,NT,20):
c=next(colour)
ax.plot(x,u[:,n],'ko', markerfacecolor='none', alpha=0.5, label='i='+str(n)+' numerical')
ax.plot(x,u_analytical[:,n],linestyle='-',c=c,label='i='+str(n)+' analytical')
box=ax.get_position()
ax.set_position([box.x0, box.y0, box.width*0.7,box.height])
ax.legend( bbox_to_anchor=(1.02,1), loc=2)
plt.xlabel('x (radians)')
plt.ylabel('u (m/s)')
plt.ylim([0,8.0])
plt.xlim([0,2.0*PI])
plt.title(TITLE)
plt.show()
Note
Why doesn’t the numerical simulation agree with the analytical solution exactly?
- The numerical solution shows more dissipation through time and space than the analytical solution, despite the fact that the viscosity is the same in both cases (a lot in time, perhaps less in space)
- It is likely that numerical dissipation is the cause of the difference between the analytic and numerical solutions
- When physical viscosity is reduced, so reducing physical dissipation, the effect of numerical dissipation is seen more clearly (compare Figure 1 and Figure 2)
- This is caused by the truncation error in the discretion of the governing equations
- The first order approximations for the transient and convection terms contain numerical diffusion in time and space respectively - probably need to use a higher than first order method for the transient term at least.