Finite Difference Method

Finite Difference Method#

import numpy as np
import scipy.linalg as la
import matplotlib.pyplot as plt

Consider a second order linear differential equation with boundary conditions

y+p(t)y+q(t)y=r(t)  ,  y(t0)=α  ,  y(tf)=β

The finite difference method is:

  1. Discretize the domain: choose N, let h=(tft0)/(N+1) and define tk=t0+kh.

  2. Let yky(tk) denote the approximation of the solution at tk.

  3. Substitute finite difference formulas into the equation to define an equation at each tk.

  4. Rearrange the system of equations into a linear system Ay=b and solve for $y=[y1y2yN]T$

For example, consider an equation of the form

y=r(t)  ,  y(t0)=α ,  y(tf)=β

Choose N, let h=(tft0)/(N+1) and Llet rk=r(tk). The finite difference method yields the linear system Ay=b where

A=[2112112112]b=[h2r1αh2r2h2rN1h2rNβ]

Example 1#

Plot the approximation for the equation

y=2  ,  y(0)=0 ,  y(1)=0

and compare to the exact solution

y(t)=tt2
t0 = 0; tf = 1; alpha = 0; beta = 0;
N = 4; h = (tf - t0)/(N + 1)

t = np.linspace(t0,tf,N+2)
r = -2*np.ones(t.size)

A = np.diag(np.repeat(-2,N)) + np.diag(np.repeat(1,N-1),1) + np.diag(np.repeat(1,N-1),-1)
b = h**2*r[1:N+1] - np.concatenate([alpha,np.zeros(N-2),beta],axis=None)
y = la.solve(A,b)

y = np.concatenate([alpha,y,beta],axis=None)
plt.plot(t,y,'b.-')

T = np.linspace(t0,tf,100)
Y = T*(1 - T)
plt.plot(T,Y,'r')
plt.grid(True)
plt.show()
../_images/3dcf03d858448052a01a6edeebd6ee8d0d4ac84ca8dfc905ec78bd9ae049bc08.png

Example 2#

Plot the approximation for the equation

y=cos(t)  ,  y(0)=0 ,  y(2π)=1

and compare to the exact solution

y(t)=1cos(t)+t2π
t0 = 0; tf = 2*np.pi; alpha = 0; beta = 1;
N = 5; h = (tf - t0)/(N + 1);

t = np.linspace(t0,tf,N+2)
r = np.cos(t)

A = np.diag(np.repeat(-2,N)) + np.diag(np.repeat(1,N-1),1) + np.diag(np.repeat(1,N-1),-1)
b = h**2*r[1:N+1] - np.concatenate([alpha,np.zeros(N-2),beta],axis=None)
y = la.solve(A,b)

y = np.concatenate([alpha,y,beta],axis=None)
plt.plot(t,y,'b.-')

T = np.linspace(t0,tf,100)
Y = 1-np.cos(T) + T/2/np.pi
plt.plot(T,Y,'r')
plt.grid(True)
plt.show()
../_images/c25bd78c862bdb0d63f8aa8326a35b381adf1c84b6769ded5b3c265e1df39f1c.png

Example 3#

Consider a general second order linear ordinary differential equation with boundary conditions

y+p(t)y+q(t)y=r(t)  ,  y(t0)=α ,  y(tf)=β

Introduce the notation

ak=1hpk2bk=h2qk2ck=1+hpk2

The finite difference method yields the linear system Ay=b where

A=[b1c1a2b2c2aN1bN1cN1aNbN]b=[h2r1(1hp1/2)αh2r2h2rN1h2rN(1+hpN/2)β]

Plot the approximation for the equation

y+t2y+y=cos(t)  ,  y(0)=0 ,  y(3)=0
alpha = 0; beta = 0; N = 19;
t0 = 0; tf = 3; h = (tf - t0)/(N + 1);
t = np.linspace(t0,tf,N+2)

p = t**2
q = np.ones(t.size)
r = np.cos(t)

a = 1 - h*p/2
b = h**2*q - 2
c = 1 + h*p/2
A = np.diag(b[1:N+1]) + np.diag(c[1:N],1) + np.diag(a[2:N+1],-1)

b = h**2*r[1:N+1] - np.concatenate([a[1]*alpha,np.zeros(N-2),c[N]*beta],axis=None)
y = la.solve(A,b)

y = np.concatenate([alpha,y,beta],axis=None)
plt.plot(t,y,'b.-')
plt.grid(True)
plt.show()
../_images/8f80301c48aa26eb5ece751e45555cc8c7fb16eb957a8ebdc7c28cf90806ee86.png