Challenge

Week 6 - Multivariate Newton Rhapson Solver

Aim: To solve a coupled non-linear system of ODE's using the Multivariate Newton-Raphson Method in Python.

ODE's:

`(dy_1)/(dt) = -0.04y_1+10^4y_2y_3`

`(dy_2)/(dt) = -0.04y_1+10^4y_2y_3-3*10^7y_2^2`

`(dy_3)/(dt) = 3*10^7y_2^2`

Theory:

Multivariate Newton-Raphson Method:-
The Newton-Raphson method is root finding iterative solution, which is use to calculate the best approximation from the guess value for the function. The Newton-Raphson method is used when there is only one independet variable whereas, the Multivariate Newton-Raphson method is used when the function has two or more independent variables.

The Newton-Raphson method is calculated using the given formula:

`y_(text(new)) = y_(old) - alphaJ^(-1)F`

where α is the Relaxation Factor, J is the Jacobian Matrix, F is column matrix of functions,

`y_(text(new)) = [[y_1], [y_2], [y_3]]`

`y_(old) = [[y_(1old)], [y_(2old)], [y_(3old)]]`

The Jacobian Matrix contains all first order partial derivative of the function. It shows how output of vector valued function changes with input.

J = `[[(df_1)/(dy_1) (df_1)/(dy_2) (df_1)/(dy_3)], [(df_2)/(dy_1) (df_2)/(dy_2) (df_2)/(dy_3)] ,[(df_3)/(dy_1) (df_3)/(dy_2) (df_3)/(dy_3)]]`

F = `[[f_1],[f_2],[f_3]]`

This formula is executed untill the program reaches a better approximation for the values of y1, y2 and y3.

Program:

For our code we have some initial data:

α = 1.0

total time = 10*60 = 600s

For selection of the time-step size, if the program has to be executed with Explicit Euler method than the dt has to be small for a smooth execution of the code. But we are solving with Backward Differencing Methods/ Implicit Euler Method so the dt can be large without compromising the computation efficiency.
Therefore the choice of dt = 0.05, then the number of time-steps is given by: 600/0.05 = 12000

Also for computing the Jacobian numerically, we used the forward differencing so for calcuation for f1

`(df_1)/(dy_1) = (f1(y1+h) - f1(y1))/h`

'h' selection is very small like 1e-6

"""
Solving coupled non-linear ODE's using multivariate Newton-Raphson method

    Equations:
                dy1/dt  = -0.04*y1 + pow(10,4)*y2*y3
                dy2/dt  = -0.04*y1 + pow(10,4)*y2*y3 - 3*pow(10,7)*pow(y2,2)
                dy3/dt  = 3*pow(10,7)*pow(y2,2)

The simulation is run for 600s with dt is 0.05
"""

import matplotlib.pyplot as plt
from numpy.linalg import inv
import numpy as np
def f1(y10,y1,y2,y3,dt):

	return (y10 + dt*(-0.04*y1 + y2*y3*1e4) - y1) 
	
def f2(y20,y1,y2,y3,dt):

	return (y20 + dt*(0.04*y1 - (1e4*y2*y3) -(3e7*y2*y2)) -y2)
		 
def f3(y30,y1,y2,y3,dt):

	return (y30 + dt*(3e7*y2*y2) - y3)
		  
def jacobian(y10,y20,y30,y1,y2,y3,dt): 
	J = np.ones((3,3)) 
# Jacobian solved by numerical derivative. 
	h = 1e-6 # Step size 

	J[0,0] = (f1(y10,y1+h,y2,y3,dt)-f1(y10,y1,y2,y3,dt))/h 
	J[0,1] = (f1(y10,y1,y2+h,y3,dt) -f1(y10,y1,y2,y3,dt))/h 
	J[0,2] = (f1(y10,y1,y2,y3+h,dt) -f1(y10,y1,y2,y3,dt))/h 

	#Row 2 
	J[1,0] = (f2(y20,y1+h,y2,y3,dt) -f2(y20,y1,y2,y3,dt))/h
	J[1,1] = (f2(y20,y1,y2+h,y3,dt) -f2(y20,y1,y2,y3,dt))/h 
	J[1,2] = (f2(y20,y1,y2,y3+h,dt)-f2(y20,y1,y2,y3,dt))/h 
# Row 3 
	J[2,0] = (f3(y30,y1+h,y2,y3,dt)-f3(y30,y1,y2,y3,dt))/h 
	J[2,1] = (f3(y30,y1,y2+h,y3,dt)-f3(y30,y1,y2,y3,dt))/h 
	J[2,2] = (f3(y30,y1,y2,y3+h,dt)-f3(y30,y1,y2,y3,dt))/h 
	return J
# Defining initial guess value 
y10 = 1
y20 = 0 
y30 = 0 
# Initial error 
error = 9e9 
#Column Vector 
Y_old = np.ones((3,1)) 
Y_old[0] = y10 
Y_old[1] = y20 
Y_old[2] = y30 
# Column Vectors for F 
F = np.copy(Y_old) 
#Parameters for newton rapson method 
alpha = 1 
tol = 1e-6 
t = 600 
dt = 0.05
n = int(t/dt) 
y1 = [] 
y2 = []
y3 = []
iteration = []

iter = 1
for i in range(0,n):
	while error>tol: 
		J = jacobian(y10,y20,y30,Y_old[0],Y_old[1],Y_old[2],dt) 
# Computing the F vector
		F[0] = f1(y10,Y_old[0],Y_old[1],Y_old[2],dt) 
		F[1] = f2(y20,Y_old[0],Y_old[1],Y_old[2],dt) 
		F[2] = f3(y30,Y_old[0],Y_old[1],Y_old[2],dt) 
# Computing the new values
		Y_new = Y_old - alpha*np.matmul(inv(J), F)
		error = max(abs(Y_new-Y_old)) 
		print(error) #Updating the old values 
		Y_old = Y_new #log message 
# Storing the values for plotting 
		y1.append(Y_new[0]) 
		y2.append(Y_new[1]) 
		y3.append(Y_new[2]) 
		iter = iter + 1
		iteration.append(iter)
		Y_old = Y_new
		y10 = Y_new[0]
		y20 = Y_new[1]
		y30 = Y_new[2]

plt.plot(iteration,y1, color = 'green')
plt.plot(iteration,y2, color = 'red')
plt.plot(iteration,y3, color = 'black')
plt.xlabel('Number of Iterations')
plt.ylabel('Variables')
plt.legend(['y1','y2','y3'])
plt.title('Solution for ODE System')
plt.grid()
plt.show()

Conclusion: Hence, the Newton-Raphson method solver is programmed in Python and the set of coupled non-linear three ODE's and the graph for y1, y2 and y3 against iteration for convergence.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.