Post

FiniteDiffrence

FiniteDiffrence

Open In Colab

Shyam Sunder

1
2
3
4
import numpy as np
import matplotlib.pyplot as plt
import math
from scipy.sparse import diags

Let $y = y(x)$ be a function of x.
Then we know from taylor’s series:

\begin{equation} y(x+h) = y(x) + hy’(x) + h^2y’‘(x) + \cdots
y(x-h) = y(x) - hy’(x) + h^2y’‘(x) - \cdots \end{equation}

Substracting these two we get: \(y(x+h)-y(x-h)=2hy'(x) + \mathcal{O}(h^3)\) \(y'(x) = \frac{y(x+h)-y(x-h)}{2h} + \mathcal{O}(h^3)\)

This is called Central Difference Formula for diffrentiation.

By adding these two, we get \(y"(x) = \frac{y(x+h)+y(x-h)-2y(x)}{h^2} + \mathcal{O}(h^4)\)
In context of any diffrential equation, We are given boundries $x_0$ to $X_n$.
So we can simply devide it into N equal parts deffering by h. Let $x_i = x_0 + ih$ represent a point in this intevel. So $y_i = y(x_i)$. We can write the equation

\(y"(x) = \frac{y_{i+1} + y_{i-1} - 2y_{i}}{h^2}\)
and also \(y'(x) = \frac{y_{i+1}-y_i}{h}\)

We want to solve the boundry value problem

\[\frac{d^2 y}{dx^2} -\frac{dy}{dx} - 2y = cos(x)\] \[y(0) = -0.3 \quad y(\pi/2)= -0.1\]

\(0 \leq x \leq \frac{\pi}{2}\) We can break the interval $[0, \frac{\pi}{2}]$ into $n$ parts and label them with is where $x_i = 0 + ih$ and $h$ is the diffrence bewteen two terms.

We can write the \autoref{pro} as \(y" - y' - 2y = \cos(x)\) When we apply the finite diffrence method we get \begin{equation} \frac{y_{i+1} + y_{i-1} - 2y_{i}}{h^2} - \frac{y_{i+1}-y_i}{h} - 2y_i = \cos(x_i) \end{equation}

Now we will put some values of i \(y_0 = -0.3 \quad \quad i =0\) \(\frac{1}{h^2}\left( 1.y_{0} + (-2h^2+h-2)y_1 + (1-h)y_{2}\right) = \cos(x_1) \quad i = 1\) \(\frac{1}{h^2}\left( 1.y_{1} + (-2h^2+h-2)y_2 + (1-h)y_{3}\right) = \cos(x_2) \quad i = 2\) \vdots \(\frac{1}{h^2}\left( 1.y_{i-1} + (-2h^2+h-2)y_{i} + (1-h)y_{i+1}\right) = \cos(x_i) \quad i = i\) \vdots \(\frac{1}{h^2}\left( 1.y_{n-2} + (-2h^2+h-2)y_{n-1} + (1-h)y_{n}\right) = \cos(x_{n-1}) \quad i = n-1\) \(y_n = -0.1\)

We can Represent this in the Matrix forms as

\begin{equation} \frac{1}{h^2} \begin{bmatrix} h^2 & 0 & 0 & \cdots & 0 & 0
1 & -2+h-2h^2 & 1-h &\cdots & 0 & 0
0 & 1 & -2+h-2h^2 &\cdots & 0 & 0
\vdots & \vdots & & & & \vdots
0 & 0 & 0 & \cdots & -2+h-2h^2 & 1-h
0 & 0 & 0 & \cdots & 0 & h^2 \end{bmatrix} \begin{bmatrix} y_0
y_1
y_2 \ \vdots
y_{n-1}
y_n \end{bmatrix} = \begin{bmatrix} -0.3
cos(x_1)
cos(x_2)
\vdots
cos(x_{n-1})
-0.1 \end{bmatrix} \end{equation}

\begin{equation} MY = b \end{equation}

1
2
3
4
pi = math.pi
xs = np.linspace(0, math.pi/2,100)
h = np.diff(xs)[0] #size of each step
N = xs.size #number of steps

To desging the M matrix we would take a different approach. I will design the diagoals of the matrix sperately and then I will put them into a empty matrix using diag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#desging the diagonals of the matrix
d1 = np.ones(N-1)
d0 = (-2+h-2*h**2)*np.ones(N)
d3 = (1-h)*np.ones(N-1)

# d1 = np.ones(N-1)
# d0 = -2*np.ones(N)
# d3 = d1

#Putting the dignoals into a empty matrix
M = diags([d1,d0,d3],[-1,0,1]).toarray()

#multiplying by 1/h^2 fector
M = (1/h**2)*M

#putting in the boundry Coditions
M[0][0]=1
M[0][1]=0
M[-1][-1]=1
M[-1][-2] = 0
1
2
3
4
5
6
#desing the left matrix
b = np.zeros(N)
for i in range(len(b)):
    b[i] = math.cos(xs[i])
b[0]=-0.3
b[-1]=-0.1

We will use the gaussian elimination method to solve the equation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def gaussianElimination(A, B):
    n = len(A)
    A = np.c_[A, B]
    
    #getting echilion matrix:
    for i in range(n):
        for j in range(i+1,n):
            fector = A[j][i]/A[i][i]
            for k in range(i, n+1):
                A[j][k] -= A[i][k]*fector

    c = [0 for _ in B]        
    #backSubstitution
    string = ''
    for i in range(n-1,-1,-1):
        sum = 0
        for j in range(i,n):
            sum += A[i][j]*c[j]
        c[i] = (A[i][-1] -sum)/A[i][i]
        
    return c
1
ys = gaussianElimination(M,b)
1
2
3
4
plt.plot(xs, ys, label='From fintie Difference Method')
plt.plot((0,pi/2),(-.3,-.1), '*')
plt.legend()
plt.show()

png

The Theoritical solution for this problem is: \(y(x) = \frac{1}{10}(-sin(x)-3(cos(x))\)

1
2
def theory(x):
    return (1/10)*(-math.sin(x)-3*math.cos(x))
1
y_th = [theory(x) for x in xs]
1
2
3
4
5
plt.plot(xs, ys, label='From fintie Difference Method')
plt.plot(xs, y_th, label='From Theory')
plt.plot((0,pi/2),(-.3,-.1), '*')
plt.legend()
plt.show()

png

So as we can see that our solution exactly matches with the theorictical value

This post is licensed under CC BY 4.0 by the author.