Challenge

Week 6 - Multivariate Newton Rhapson Solver

Multivariate Newton Rhapson Solver

Aim:

writing a code to solve the set of ODE equations with multi variables using Multivariate Newton Rhapson Solver. use Implicit Euler Method/Backward Differencing for jacobian matrix.

Equations:

`dy_1/dt = -0.04*y_1 + 10^4*y_2*y_3 ------------(1)`

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

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

Solution Procedure:-

To solve multivariable system of equations we use Multivariate Newton Rhapson Solver

The Newton-Raphson method is a way to quickly find a good approximation for the root of a real-valued function `f ( x ) = 0`. It uses the idea that a continuous and differentiable function can be approximated by a straight line tangent to it.

for single variable:-

`x_(text(new))=x_(guess)-alpha**[f(x_(guess))/(f'(x_(guess)))]`

`alpha` = relaxation factor

for multivariable problem:-

`x_(text(new))=x_(guess)-alpha**(J^(-1)**F)_(guess)`

where ,

J = Jacobian matrix of the couples equations.

Newton-Raphson method is used with the analytical solution of the Jacobian matrix to give an iterative solution of pole placement equations with better percentage success rate than the other methods quoted in literature.

for this case J is,

`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 = Function matrix

matrix formed by system of coupled non linear equations.

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

Procedure to obtain function matrix:-

Use Backward differencing scheme to descritise the above equations 1 , 2, 3.

`f^' (x_i )= (f(x_i )-f(x_(i-1)))/(Deltax )`

`Deltax =` Step size

`((y_1^n)-(y_1^(n-1)))/(Deltat) = -0.04(y_1^n)+10^4(y_2^n)(y_3^n)`

`((y_2^n)-(y_2^(n-1)))/(Deltat) = 0.04(y_1^n)-10^4(y_2^n)(y_3^n) - 3*10^7*(y_2^n)^2`

`((y_3^n)-(y_3^(n-1)))/(Deltat) = 3*10^7*(y_2^n)^2`

`Delta t = h = time step`

`y_1^n=y_1^(n-1)+h.(-0.04*y_1^n+10^4*y_2^n*y_3^n)`

`y_2^n=(y_2^(n-1))+h.(0.04(y_1^n)-10^4(y_2^n)(y_3^n)-3**10^7(y_2^2)^n)`

`y_3^n=(y_3^(n-1))+h.(3**10^7(y_2^2)^n)`

To find roots of the we have to equate the equations to 0.

The function form of equations are:-

`f_1=y_1^(n-1)+h.(-0.04*y_1^n+10^4*y_2^n*y_3^n)-y_1^n=0`

`f_2=(y_2^(n-1))+h.(0.04(y_1^n)-10^4(y_2^n)(y_3^n)-3**10^7(y_2^2)^n)-y_2^n=0`

`f_3=(y_3^(n-1))+h.(3**10^7(y_2^2)^n)-y_3^n=0`

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

Given Data:-

Initial conditions:

`[[Y_1 = 1],[Y_2 = 0],[Y_3 = 0]]`

`text(Relaxation factor ) => alpha =1`

`text(simulation time)= 10 min =600 sec`

Program Procedure:

  1. Import the required libraries and modules, like numpy, matplotlib , inv in numpy.
  2. Define the functions `f_1,f_2,f_3`
  3. Write function code to calculate Jacobian matrix.
  4. Give initial values and guess values. take both as same to reduce number of steps.
  5. Declare the values like `alpha = 1`, `dy = 1e-6`,`text(tolerance) = 1e-12`,`dt = [100,50,25,10,5,2.5,1,0.5,0.1]`
  6. dy = step size ; dt = h= array of time steps.
  7. Create a time step loop to analyze solutions for different time step sizes
  8. Outer time integration loop
  9. Assembling of ODE system
  10. Run the Newton Raphson till the solution Converges
  11. Get New values + Perform required updates
  12. End time loop
  13. End Time step loop
  14. Plot the results.
  15. Give conclusions.

Main Program:-

'''
Program to solve the system of coupled non-linear equations
	y1_old + h*(-0.04*y1 + pow(10,4)*y2*y3)-y1 = 0
	y2_old + h*(0.04*y1 - pow(10,4)*y2*y3 - 3*pow(10,7)*pow(y2,2))-y2 = 0
	y3_old + h*(3*pow(10,7)*pow(y2,2))-y3 = 0
	h = dt = time step
Modules required
1. numpy is required for matrix multiplication 
2. inv is required for computing the inverse of a matrix
3. matplotlib is required to plot the results
'''
import numpy as np
from numpy.linalg import inv
import matplotlib.pyplot as plt

def f1(y1, y2, y3, y1_old, h):
	# First non-linear equation
	return y1_old + h*(-0.04*y1 + pow(10,4)*y2*y3)-y1

def f2(y1, y2, y3, y2_old, h):
	# Second non-linear equation
	return y2_old + h*(0.04*y1 - pow(10,4)*y2*y3 - 3*pow(10,7)*pow(y2,2))-y2

def f3(y1, y2, y3, y3_old, h):
	# third non-linear equation
	return y3_old + h*(3*pow(10,7)*pow(y2,2))-y3 

def jacobian(y1, y2, y3, y1_old, y2_old, y3_old, h, dy):
	# Defining the Jacobian
	#3 by 3 unit matrix 
	J = np.ones((3,3))

	# Row 1 df(n)/dy(n) = (f(n+1)-f(n))/dy
	J[0,0] = (f1(y1+dy, y2, y3, y1_old, h)-f1(y1, y2, y3, y1_old, h))/dy    # df1/dy1
	J[0,1] = (f1(y1, y2+dy, y3, y1_old, h)-f1(y1, y2, y3, y1_old, h))/dy    # df1/dy2
	J[0,2] = (f1(y1, y2, y3+dy, y1_old, h)-f1(y1, y2, y3, y1_old, h))/dy    # df1/dy3

	# Row 2  
	J[1,0] =  (f2(y1+dy, y2, y3, y2_old, h)-f2(y1, y2, y3, y2_old, h))/dy    # df2/dy1
	J[1,1] =  (f2(y1, y2+dy, y3, y2_old, h)-f2(y1, y2, y3, y2_old, h))/dy    # df2/dy2
	J[1,2] =  (f2(y1, y2, y3+dy, y2_old, h)-f2(y1, y2, y3, y2_old, h))/dy    # df2/dy3

	# Row 3  
	J[2,0] = (f3(y1+dy, y2, y3, y3_old, h)-f3(y1, y2, y3, y3_old, h))/dy    # df3/dy1
	J[2,1] = (f3(y1, y2+dy, y3, y3_old, h)-f3(y1, y2, y3, y3_old, h))/dy    # df3/dy2
	J[2,2] = (f3(y1, y2, y3+dy, y3_old, h)-f3(y1, y2, y3, y3_old, h))/dy    # df3/dy3

	return J


# parameters for newton rhapson solver 
alpha = 1
dy = 1e-6 
dt = [100,50,25,10,5,2.5,1,0.5,0.1] # Time step
# dt = [0.1,] # Time step
tol   = 1e-10
fig = 1
for h in dt:
	#numpy column vector for old values (previous time step values)
	Y_old = np.zeros((3,1))
	Y_old[0] = 1 

	#numpy column vector initial guess values g = guess
	Y_g = np.copy(Y_old)

	#numpy column vector for F 
	F = np.copy(Y_g)

	Y1 = []
	Y2 = []
	Y3 = []
	t = np.arange(0,600,h)  # Time 
	print(h)

	# Starting the newton rhapson loop
	for i in range(0,len(t)):
		# print(i)
		error = 9e9
		while error > tol:
			# Computing the Jacobian old values are used
			J = jacobian(Y_g[0], Y_g[1], Y_g[2], Y_old[0], Y_old[1], Y_old[2], h, dy)

			# Computing the F vector- old values are used
			F[0] = f1(Y_g[0], Y_g[1], Y_g[2], Y_old[0], h)
			F[1] = f2(Y_g[0], Y_g[1], Y_g[2], Y_old[1], h)
			F[2] = f3(Y_g[0], Y_g[1], Y_g[2], Y_old[2], h)

			# Computing new values
			Y_new = Y_g - alpha*np.matmul(inv(J), F)
			# Computing max abs error 
			error = max(np.abs(Y_new-Y_g))
			# Updating guess values 
			Y_g   = Y_new

		# print(Y_new)
		# Updating old values 
		Y_old = Y_new
		Y1.append(Y_new[0])
		Y2.append(Y_new[1])
		Y3.append(Y_new[2])
		
	# Ploting Results
	plt.figure(fig)
	plt.plot(t,Y1,label='Y1')
	plt.plot(t,Y2,label='Y2')
	plt.plot(t,Y3,label='Y3')
	plt.xlabel("Time (seconds)")
	plt.ylabel("Y (Species concentration)")
	plt.title('''Multi Varient Newton Raphson Solver at 
dy = 1e-6  ;  alpha  = 1   ;    h = dt = ''' + str(h) )
	plt.grid("on")
	plt.legend()
	fig = fig + 1

plt.show()

PLOTS:-

  • Choose a suitable step size and explain the reason for choosing that step size, what is the ideal step size in this case?

Time step size

`dt`

Time taken to compute the results in seconds
100 1.5
50 1.6
25 1.6
10 1.8
5 1.8
2.5 2
1 2.7
0.5 3.6
0.1 9

i computed the results for different step sizes `dt = [100,50,25,10,5,2.5,1,0.5,0.1]`

From the plots, we can understand that, as the step size decreases the solution is more smooth and accurate. For steps sizes, dt >10 the plots are not smooth and they are changing. step size dt < 10 plots are looking similar and exact as we reduce time step the plots remains same.

from the above table, we can notice that as the time step size decreases the time taken to compute the results also increases for dt = 100 it took 1.5 seconds to compute the results for dt = 0.1 it took 9 seconds to compute the results.

Reduced step size give accurate results but computation time increases by considering both the parameters accuracy and time taken to compute the results i recommend `1 > text(dt) >0.5`

NOTE:-

This Assignment is an example to solve the combustion mechanisms. in this, we considered 3 species `Y_1,Y_2,Y_3` as reference to analyzing how they are undergoing from reactants to products.

In real-time we will have 100,1000 species and reactions but the solution procedure is same as what we are doing here but, the scale of the problem will increase.

`text(Eample):-Y_1,Y_2,Y_3 == O_2,H_2O,C`

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.