Challenge

Week 6 - Multivariate Newton Rhapson Solver

Week 6 - Multivariate Newton Rhapson Solver

Aim:- To solve the a given set of 'ODE system of coupled non-linear equations', by using the Multivariate Newton Rhapson Solver.

Introduction:- The Multivariate Newton -Rhapson Method is a direct extension of the single variable Newton-Raphson Method.

Where the single variable Newton Rhapson Method solved,

f(x) =0, the multivariate version will solve a system of n equations of the form:

`f_1 =(x_1,x_2,x_3,.....) =0`

`f_2 =(x_1,x_2,x_3,.....) =0`

`f_3 =(x_1,x_2,x_3,.....) =0`

'

'

'

`f_(n-1) =(x_1,x_2,x_3,.....) =0`

`f_n =(x_1,x_2,x_3,.....) =0`

we will adopt the shorthand notation for the equation

f(x) =0

According to 'Multivariate Newton Rhapson Method', to get the solution out of coupled non-linear ODE below equation we use:

`y_n =y _(old) - alpha * J^-1 *F`

where, alpha -relaxation factor

Vector F will be written as,

`f=((f_1),(f_2),(f_3))`

old value or guess value will be written as,

`y _(old)=((y_1old),(y_2old),(y_3old))`

Jacobian Matrix,

`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]]`

where, number of column = number of independent variables

number of rows = number of Functions

Code:-

"""
# Implicit Euler Method/Backward Differencing Scheme
Program to solve the ODE system of coupled non-linear  equations
	dy1/dt=(-0.04*y1)+(10^44*y2*y3)
	dy2/dt =(0.04*y1 -(10^4*y2*y3) -(3*10^7*y2^2)
	dy3/dt = (3*10^7*y2^2)
"""
#libraries
import matplotlib.pyplot as plt  # plotting the graph
import numpy as np   # matrix manipulation, calculations
from numpy.linalg import inv  # 'linalg (linear algebra)' package from the 'numpy',inv (inverse) for 'Jacobian Inverse'



# First non-linear equation
def f1(y1,y2,y3,y1_old,dt):
	return y1_old + dt*(-0.04*y1 + (pow(10,4)*y2*y3)) - y1
# Second non-linear equation
def f2(y1,y2,y3,y2_old,dt):
	 
	return y2_old + dt*(0.04*y1 - (pow(10,4)*y2*y3) - (3*pow(10,7)*pow(y2,2))) - y2
 #Third non-linear equation
def f3(y1,y2,y3,y3_old,dt):
	
    return y3_old + dt*(3*pow(10,7)*pow(y2,2)) - y3

#Define the Jocobian Matrix
def jacobian(y1,y2,y3,y1_old,y2_old,y3_old,dt):
	
	J = np.ones((3,3))
	
	dy=1e-4
	#Row 1
	J[0,0] =  (f1(y1+dy,y2,y3,y1_old,dt) - f1(y1,y2,y3,y1_old,dt))/dy
	J[0,1] =  (f1(y1,y2+dy,y3,y1_old,dt) - f1(y1,y2,y3,y1_old,dt))/dy   
	J[0,2] =  (f1(y1,y2,y3+dy,y1_old,dt) - f1(y1,y2,y3,y1_old,dt))/dy 

	#Row 2
	J[1,0] = (f2(y1+dy,y2,y3,y2_old,dt) - f2(y1,y2,y3,y2_old,dt))/dy
	J[1,1] = (f2(y1,y2+dy,y3,y2_old,dt) - f2(y1,y2,y3,y2_old,dt))/dy
	J[1,2] = (f2(y1,y2,y3+dy,y2_old,dt) - f2(y1,y2,y3,y2_old,dt))/dy

	#Row 3
	J[2,0] = (f3(y1+dy,y2,y3,y3_old,dt) - f3(y1,y2,y3,y3_old,dt))/dy
	J[2,1] = (f3(y1,y2+dy,y3,y3_old,dt) - f3(y1,y2,y3,y3_old,dt))/dy
	J[2,2] = (f3(y1,y2,y3+dy,y3_old,dt) - f3(y1,y2,y3,y3_old,dt))/dy

	return(J)

#  given 'initial guess values' 
# numpy column vecotr
y_old = np.zeros((3,1))
y_old[0] = 1   # decalring the conditions provided for the y1
 
F =np.zeros((3,1)) # you can declare the F vector as zeros as they are going to change with the iterations 
y_new = np.zeros((3,1))  # variable used to update the Y's in the while loop for every time step 
dy = 1e-4  # differential parameters

# parameters for newton rhapson solver
alpha =1   # relaxation factor 'given '
T = 60 # 600sec
dt = 0.1  # step size

n =int(T/dt) # no.of grid points
print(n)      # print the 'grid points'
time =np.arange(0,n)  # time  between '0' to 'n' 
print(time)          # print the 'time'
 
y_new1 =[]   # new values of 'y1' stored in the array
y_new2 =[]   # new values of 'y2' stored in the array
y_new3 =[]   # new values of 'y3' stored in the array

# starting the newton rhapson loop
iter =1  # initial the of 'iteration values'

for i in range(0,len(time)):
	error =9e9    # assume the error value
	tol = 1e-6    # assume tolerance value
	y_guess = np.copy(y_old)  ## Running while loop with the guessed values of 'y' untill the Final value is obtained for that time step
	print(i)      
	while error >tol:
	# computing the Jacobian -old values are used
		J = jacobian(y_new[0],y_new[1],y_new[2],y_old[0],y_old[1],y_old[2],dt)

		F[0]=f1(y_guess[0],y_guess[1],y_guess[2],y_old[0],dt)
		F[1]=f2(y_guess[0],y_guess[1],y_guess[2],y_old[1],dt)
		F[2]=f3(y_guess[0],y_guess[1],y_guess[2],y_old[2],dt)

	# computing new values
		y_new= y_guess - alpha*np.matmul(inv(J),F)  ## We are updating the y_guess over the while loop until the error becomes less than tolerance
		error=max(abs(y_new-y_guess))  # error values
		y_guess= y_new         # you need to update the guess vector until the while loop is satisfied
	

	#updating the old values 
	y_old = y_new
	y_new1.append(y_new[0])
	y_new2.append(y_new[1])
	y_new3.append(y_new[2])
		
 
#plotting
plt.plot(time,y_new1,color='red',label='y new1')
plt.plot(time,y_new2,color='blue',label='y new2')
plt.plot(time,y_new3,color='green',label='y new3')
plt.xlabel('Simulation Time in s')
plt.ylabel('y new values')
plt.title('Simulation Time versus y new values')
plt.grid('on')
plt.legend(fontsize = 10)
plt.show()

Conclusion:- In the above graphs, the simulation time run at 10 mintues @ ideal step size (dt=0.1). while , changing the 'dt =0.2 @ simulation time (300 s) & dt =0.3 @ simulation time (200 s).' Therefore, increase the time step size (dt) reduces the 'simulation time'.

********************

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.