Open In Colab

Finite Difference Method#

John S Butler john.s.butler@tudublin.ie#

Course Notes
Github

Overview#

This notebook illustrates the finite different method for a linear Boundary Value Problem. The video below walks through the code.

from IPython.display import HTML
HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/DMtnJ7vrb8s" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>')
/Users/johnbutler/opt/anaconda3/lib/python3.8/site-packages/IPython/core/display.py:724: UserWarning: Consider using IPython.display.IFrame instead
  warnings.warn("Consider using IPython.display.IFrame instead")

Introduction#

To numerically approximate a linear Boundary Value Problem

(502)#y=f(x,y,y),   a<x<b,

with the boundary conditions

(503)#y(a)=α,
(504)#y(b)=β,

is dicretised to a system of difference equations. the first derivative can be approximated by the difference operators:

(505)#D+Ui=Ui+1Uihi+1    Forward,
(506)#DUi=UiUi1hi    Backward,

or

(507)#D0Ui=Ui+1Ui1xi+1xi1=Ui+1Ui12h    Centered.

The second derivative can be approximated by:

(508)#δx2Ui=2xi+1xi1(Ui+1Uixi+1xiUiUi1xixi1)=Ui+12U2+Ui1h2    Centered in x direction.

Example Boundary Value Problem#

To illustrate the method we will apply the finite difference method to the this boundary value problem

(509)#d2ydx2=4y,

with the boundary conditions

(510)#y(0)=1.1752,y(1)=10.0179.
import numpy as np
import math
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")

Discrete Axis#

The stepsize is defined as

(511)#h=baN

here it is

(512)#h=1010

giving

(513)#xi=0+0.1i

for i=0,1,...10.

## BVP
N=10
h=1/N
x=np.linspace(0,1,N+1)
fig = plt.figure(figsize=(10,4))
plt.plot(x,0*x,'o:',color='red')
plt.plot(x[0],0,'o:',color='green')
plt.plot(x[10],0,'o:',color='green')


plt.xlim((0,1))
plt.xlabel('x',fontsize=16)
plt.title('Illustration of discrete time points for h=%s'%(h),fontsize=32)
plt.show()
../_images/61b86d25cfa6bc75e644f827573dc58a82d75b9e7b1916f3f74c88b5e15954fd.png

The Difference Equation#

To convert the boundary problem into a difference equation we use 1st and 2nd order difference operators. The general difference equation is

(514)#1h2(yi12yi+yi+1)=4yi   i=1,..,N1.

Rearranging the equation we have the system of N-1 equations

(515)#i=1:10.12y0(20.12+4)y1+10.12y2=0
(516)#i=2:10.12y1(20.12+4)y2+10.12y3=0
(517)#...
(518)#i=8:10.12y7(20.12+4)y8+10.12y9=0
(519)#i=9:10.12y8(20.12+4)y9+10.12y10=0

where the green terms are the known boundary conditions.

Rearranging the equation we have the system of 9 equations

(520)#i=1:(20.12+4)y1+10.12y2=10.12y0
(521)#i=2:10.12y1(20.12+4)y2+10.12y3=0
(522)#...
(523)#i=8:10.12y7(20.12+4)y8+10.12y9=0
(524)#i=9:10.12y8(20.12+4)y9=10.12y10

where the green terms are the known boundary conditions. This is system can be put into matrix form

(525)#Ay=b

Where A is a 9×9 matrix of the form

(526)#A=(2041000000000100204100000000010020410000000..................0000001002041000000000100204)

which can be represented graphically as:

A=np.zeros((N-1,N-1))
# Diagonal
for i in range (0,N-1):
    A[i,i]=-(2/(h*h)+4)

for i in range (0,N-2):           
    A[i+1,i]=1/(h*h)
    A[i,i+1]=1/(h*h)
    
plt.imshow(A)
plt.xlabel('i',fontsize=16)
plt.ylabel('j',fontsize=16)
plt.yticks(np.arange(N-1), np.arange(1,N-0.9,1))
plt.xticks(np.arange(N-1), np.arange(1,N-0.9,1))
clb=plt.colorbar()
clb.set_label('Matrix value')
plt.title('Matrix A',fontsize=32)
plt.tight_layout()
plt.subplots_adjust()
plt.show()
../_images/24ebd7a24e972863204878f521a92da14a144c43eb74993b4558141dab0b5444.png

y is the unknown vector which is contains the numerical approximations of the y. $$ \color{red}{\mathbf{y}}=\color{red}{ \left(\begin{array}{c} y_1\ y_2\ y_3\ .\ .\ y_8\ y_9 \end{array}\right).} \end{equation}

y=np.zeros((N+1))
# Boundary Condition
y[0]=1.1752
y[N]=10.0179

and the known right hand side is a known 9×1 vector with the boundary conditions

(527)#b=(117.5200..01001.79)
b=np.zeros(N-1)

# Boundary Condition
b[0]=-y[0]/(h*h)
b[N-2]=-y[N]/(h*h)

Solving the system#

To solve invert the matrix A such that

(528)#A1Ay=A1b
(529)#y=A1b

The plot below shows the graphical representation of A1.

invA=np.linalg.inv(A)

plt.imshow(invA)
plt.xlabel('i',fontsize=16)
plt.ylabel('j',fontsize=16)
plt.yticks(np.arange(N-1), np.arange(1,N-0.9,1))
plt.xticks(np.arange(N-1), np.arange(1,N-0.9,1))
clb=plt.colorbar()
clb.set_label('Matrix value')
plt.title(r'Matrix $A^{-1}$',fontsize=32)
plt.tight_layout()
plt.subplots_adjust()
plt.show()


y[1:N]=np.dot(invA,b)
../_images/544184cb017ac5e6b2fd82cae573eaf9677d723094a07c99be83c5122771b317.png

Result#

The plot below shows the approximate solution of the Boundary Value Problem (blue v) and the exact solution (black dashed line).

fig = plt.figure(figsize=(8,4))

plt.plot(x,y,'v',label='Finite Difference')
plt.plot(x,np.sinh(2*x+1),'k:',label='exact')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.show()
../_images/6ac98b02d6166032e56334cca2831a01a8efeffb4b53d407c05424fdd79b6d7d.png