Challenge

Week 6 - Multivariate Newton Rhapson Solver

In the project, we are going to learn the idea of how the rate of change of production of different species which are in ODE  form for each reaction. These ODE's are set of coupled equation ie the rate of one specie is dependent on the on its concentration as well on others. In order to solve these ODE, we use one of the numerical method called Multivariate Newton Raphston methods. The Multivariate Newton Raphston method finds the roots of the function iteratively.

`Y_n =Y_o - (Inv(J) f)`

Here instead of species, we will use coupled variables 

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

`dy_2/dt = 0.04y_1-10^4y2y_3 -3.10^7y_2`

`dy_3/dt=3.10^7y_2^2`

The above are the given ODE's

The RHS side which is time differential is discretized using backward differencing scheme along with the implicit method is implemented and then further the system of ODE's are rearranged that is according to Multivariate Newton Raphston method to find the roots

Discretization of Time differentials

`(dy_1^n-dy_1^(n-1))/(dt)=-0.04y_1+10^4y_2y_4`

`(dy_2^n-dy_2^(n-1))/dt = 0.04y_1-10^4y2y_3 -3.10^7y_2^2`

`(dy_3^n-dy_3^(n-1))/dt=3.10^7y_2^2`

Rearrangement

`f_1=y_1^n+h(0.04(y_1)^n-10^4(y_2)^n(y_4)^n)-y_1^(n-1)`

`f_2=y_2^n -h(0.04(y_1)^n-10^4(y2)^n(y_3)^n -3.10^7(y_2^2)^n)-y_2^(n-1) =0`

`y_3^n=h(3.10^7(y_2^2)^n)-y_3^(n-1)=0`

The jacobian form 

The differentials in the jacobians are calculated using the forward differencing

`(df_i)/dy_i=(f_i(y_i+triangley_i))/(triangley_i)`

and here `triangley_i` is taken as small  and the value is taken is1e-8

The Python Code 

import numpy as np
from numpy.linalg import inv
import matplotlib.pyplot as plt


#Defining the root solving function
def f1(y1_n,y2_n,y3_n,y1_o,h):
	return y1_n + 0.04*h*y1_n - 1e4*h*y2_n*y3_n - y1_o

def f2(y1_n,y2_n,y3_n,y2_o,h):
	return y2_n -0.04*h*y1_n + 1e4*h*y2_n*y3_n + 3e7*h*pow(y2_n,2) - y2_o

def f3(y1_n,y2_n,y3_n,y3_o,h):
	return y3_n - 3e7*h*pow(y2_n,2) - y3_o

#Calculating Jacobian using spcial forward differencing
def jac(Y_n,Y_o,h):
	dy = 1e-8
	y1_n = Y_n[0]
	y2_n = Y_n[1]
	y3_n = Y_n[2]

	y1_o = Y_o[0]
	y2_o = Y_o[1]
	y3_o = Y_o[2]

	#Jacobian matrix for all the three equation and three unkown
	J = np.zeros((3,3))

	J[0,0] = (f1(y1_n+dy,y2_n,y3_n,y1_o,h) - f1(y1_n,y2_n,y3_n,y1_o,h))/dy
	J[0,1] = (f1(y1_n,y2_n+dy,y3_n,y1_o,h) - f1(y1_n,y2_n,y3_n,y1_o,h))/dy
	J[0,2] = (f1(y1_n,y2_n,y3_n+dy,y1_o,h) - f1(y1_n,y2_n,y3_n,y1_o,h))/dy

	J[1,0] = (f2(y1_n+dy,y2_n,y3_n,y2_o,h) - f2(y1_n,y2_n,y3_n,y2_o,h))/dy
	J[1,1] = (f2(y1_n,y2_n+dy,y3_n,y2_o,h) - f2(y1_n,y2_n,y3_n,y2_o,h))/dy
	J[1,2] = (f2(y1_n,y2_n,y3_n+dy,y2_o,h) - f2(y1_n,y2_n,y3_n,y2_o,h))/dy

	J[2,0] = (f3(y1_n+dy,y2_n,y3_n,y3_o,h) - f3(y1_n,y2_n,y3_n,y3_o,h))/dy
	J[2,1] = (f3(y1_n,y2_n+dy,y3_n,y3_o,h) - f3(y1_n,y2_n,y3_n,y3_o,h))/dy
	J[2,2] = (f3(y1_n,y2_n,y3_n+dy,y3_o,h) - f3(y1_n,y2_n,y3_n,y3_o,h))/dy

	return J

#Defining the initial condition
Y_o = np.zeros((3,1))
Y_o[0] = 1

Y_n = np.zeros((3,1))

F= np.copy(Y_o)

error = 1e9
alpha = 1
tol = 1e-10
iter = 0
t= np.arange(0,600,step=0.1)
h=t[1] - t[0]

y1 = [1]*len(t)
y2 = [0]*len(t)
y3 = [0]*len(t)
iteration=[]

# Outer time loop
for k in range(1,len(t)):
	y1_o = Y_o[0]
	y2_o = Y_o[1]
	y3_o = Y_o[2]
	Y_fm  = Y_o

	#Inner iteratve solver loop
	while error >= tol:
		J = jac(Y_n,Y_o,h)
		y1_fm = Y_fm[0]
		y2_fm = Y_fm[1]
		y3_fm = Y_fm[2]

		F[0] = f1(y1_fm,y2_fm,y3_fm,y1_o,h)
		F[1] = f2(y1_fm,y2_fm,y3_fm,y2_o,h)
		F[2] = f3(y1_fm,y2_fm,y3_fm,y3_o,h)

		Y_n = Y_fm - alpha*np.matmul(inv (J), F)
		error = max(abs(Y_n-Y_fm))

		Y_fm = Y_n



	Y_o = Y_n
	y1[k] = Y_n[0]
	y2[k] = Y_n[1]
	y3[k] = Y_n[2]

	print(f'time ={round(t[k], 1)} sec, iteration No = {k},y1 = {round(Y_n[0][0], 2)}, y2 = {round(Y_n[1][0], 2)}, y3 = {round(Y_n[2][0], 2)}')


	iter =iter+1
	iteration.append(iter)
	error=1e9
plt.plot(t,y1,color = 'r')
plt.plot(t,y2,color = 'b')
plt.plot(t,y3,color = 'g')
plt.xlabel('Time(sec)')
plt.ylabel('Variable')
plt.legend(['y1','y2','y3'])
plt.show()

Results

Time Step=0.1

Time Step=0.001

Time step =1

Since the implicit scheme is being used, the solution will stable regardless of the time step being used.but what needs to consider to choose an ideal time step is an accuracy and No of iteration.The time step of  0.01 took too many iterations which takes a large amount of memory space while the step of 1 took less number of iteration about 599 and we cannot conclude its accuracy. The step time step of 0.1 shown results somewhere between the two, having a moderate amount of iteration and not taking much memory space 

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.

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.