Anda di halaman 1dari 10

Lab #5: Roots: Bracketing Methods*

1. Root (of an equation)


Is the value of the independent variable, which satisfies the equation. Ex. Move all terms to the same side:

The root is the value of

that makes this statement true.

2. Types of equations examined here


# of independent variables = 1 Linear equations - independent variable appears to the 1st power only. # of roots = 1 Ex. Non-linear o Polynomial - independent variable appears raised to powers of positive integers only. Order of the equation is defined by the highest power. # of roots order Ex. potential # of roots = 3 but real # of roots = 1

* Notes based on Chapter 5 from Applied Numerical Methods with MATLAB for Engineers and Scientists, Steven C. Chapra, 3rd Edition, McGraw-Hill, 2012.

General Non-linear all other equations. # of roots = ? Ex.

3. Graphical Method
Plot and observe where at crosses the x-axis.

Useful to predict # of roots, and to approximate their positions. Ex.

4. Bracketing methods
Based on making two initial guesses that bracket the root (they are on either side of the root). Bisection Method

o o o o

Start with interval , If function changes sign over the interval, evaluate function at midpoint Define new interval using and whichever from , that gives a function value with the sign opposite to Continue iterations (halving the interval) until size of the interval reaches a tolerance value.

Ex. if we want , then we continue the iterations until (take the midpoint as your solution) So, if , and = # of iterations, then

Solving for for

gives us the number of iterations required to reach a pre-specified value

Programming the bisection method with Python A python function to apply the bisection method to find the root of a mathematical function: from numpy import abs from sys import exit def bisect(func,xl,xu,es=0.0001,maxit=50,*args): # bisect: root location zeroes # uses bisection method to find the root of func # input: # func = function handle # xl, xu = lower and upper guesses # es = desired relative error (default = 0.0001%) # maxit = maximum allowable iterations (default = 50) # pi, p2,... = additional parameters used by func # output: # root = real root # ea = approximate relative error (%) # iter = number of iterations # Set default values for es and maxit if es == '': es = 0.0001 if maxit == '': maxit = 50 # Check that the function changes sign when going from xl to xu test = func(xl,args)*func(xu,args) if test > 0.: print 'No sign change. Root is not bracketed' exit(0) # Initialize iteration number iter = 0 while 1: #calculate present value for solution (midpoint) xr = (xl+xu)/2.

#update iteration number iter = iter+1 #choose what points to keep for the next iteration test = func(xl,args)*func(xr,args) if test < 0.: #if f(xl)*f(xr) is negative, keep xl xu = xr elif test > 0.: #if f(xl)*f(xr) is positive, keep xu xl = xr else: #if f(xl)*f(xr) is zero, a root was found ea = 0. #If f(xr) is sufficiently close to zero, we have a root. ea = abs(func(xr,args)) if (ea <= es) or (iter >= maxit): break root = xr return root,ea,iter Ex. Use the bisect function to find the root of the function: Create a python function that contains the mathematical function the root for, and feed it to the bisect function: import lab5 # Define function for which root is to be found func = lambda x,*args: (x**10)-1 # Feed function to bisect, along with xl, xu, es, and maxit [root,ea,iter] = lab5.bisect(func,0.,3.,0.000001,70) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, and es [root,ea,iter] = lab5.bisect(func,0.,3.,0.000001) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl and xu [root,ea,iter] = lab5.bisect(func,0.,3.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, and maxit [root,ea,iter] = lab5.bisect(func,0.,3.,'',70) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl and xu [root,ea,iter] = lab5.bisect(func,0.,3.,'','') print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) The output from this script is: you want to find

root root root root root

= = = = =

1.00, 1.00, 1.00, 1.00, 1.00,

ea ea ea ea ea

= = = = =

0.0000006, 0.0000006, 0.0000763, 0.0000763, 0.0000763,

Niter Niter Niter Niter Niter

= = = = =

24 24 17 17 17

You can also create the Python function containing the mathematical function in a module: import numpy import sys def example2(x,*args): f = (x**10)-1. return f def bisect(func,xl,xu,es=0.001,maxit=50,*args): # bisect: root location zeroes Running this is essentially the same as using the lambda statement: import lab5 # Feed function to bisect, along with xl, xu, es, and maxit [root,ea,iter] = lab5.bisect(lab5.example2,0.,3.,0.000001,70) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, and es [root,ea,iter] = lab5.bisect(lab5.example2,0.,3.,0.000001) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl and xu [root,ea,iter] = lab5.bisect(lab5.example2,0.,3.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, and maxit [root,ea,iter] = lab5.bisect(lab5.example2,0.,3.,'',70) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl and xu [root,ea,iter] = lab5.bisect(lab5.example2,0.,3.,'','') print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) And the output is the same as before: root root root root root = = = = = 1.00, 1.00, 1.00, 1.00, 1.00, ea ea ea ea ea = = = = = 0.0000006, 0.0000006, 0.0000763, 0.0000763, 0.0000763, Niter Niter Niter Niter Niter = = = = = 24 24 17 17 17

Finally, one can also write the mathematical function in such a way that one can change its parameters on the fly: import numpy import sys def example2(x,*args): f = (x**10)-1. return f def example3(x,(a,n,b)): f = a*(x**n)-b return f def bisect(func,xl,xu,es=0.001,maxit=50,*args): The parameters for the function are now being fed to bisect at the end of the list of arguments: import lab5 # Feed function to bisect, along with xl, xu, es, maxit, and # function parameters [root,ea,iter] = lab5.bisect(lab5.example3,0.,3.,0.000001,70, \ 1.,10,1.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, es, and # function parameters [root,ea,iter] = lab5.bisect(lab5.example3,0.,3.,0.000001,'', \ 1.,10,1.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, maxit, and # function parameters [root,ea,iter] = lab5.bisect(lab5.example3,0.,3.,'',70,1.,10,1.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) # Feed function to bisect, along with xl, xu, and # function parameters [root,ea,iter] = lab5.bisect(lab5.example3,0.,3.,'','',1.,10,1.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter)

By setting the parameters for the function such that it looks the same as before ( and make the function equal to get:

, ), we

root root root root

= = = =

1.00, 1.00, 1.00, 1.00,

ea ea ea ea

= = = =

0.0000006, 0.0000006, 0.0000763, 0.0000763,

Niter Niter Niter Niter

= = = =

24 24 17 17 , only requires changing the parameters, but

Changing the equation to, say not the definition of the function:

[root,ea,iter] = lab5.bisect(lab5.example3,0.,3.,'','',1.,2,2.) print 'root = %4.2f, ea = %9.7f, Niter = %d' % (root,ea,iter) with the result: root = 1.41, ea = 0.0000043, Niter = 15 False Position Method

o o o o

Start with and Draw a straight line connecting and Location of is at intersection of this line with x-axis Define new interval using and whichever from , sign opposite to

that gives a function value with

Bisection vs. False Position Method Bisection does not take into account the shape of the function (usually a good thing), and with bisection you are guaranteed a reduction in the interval of with every iteration.

5. Practice Problem
The resistivity of doped silicon is based on the charge electron mobility by the equation: on an electron, the electron density , and the

where the electron density is given in terms of the doping density by the equation:

and the intrinsic carrier density

and the electron mobility is described by the temperature , the reference temperature reference mobility by:

, and the

For a desired resistivity of V s cm/C, we would like to know how the doping density depends on temperature. Using a reference mobility of cm2 (V s)-1 at a reference temperature of 300 K and an intrinsic carrier density of cm-3, use the bisection method to solve for the doping density for a range of temperatures from 1000 K to 5000 K. Use initial guesses of and for the bisection method. Plot your results (doping density vs. temperature). The charge of an electron is C. a) First, you will need the bisect function included above. Copy this into a Python module file. b) Second, create another Python module file with the function for which the roots need to be found. The first line of this function might look like: def resistivity(N,(rho,ni,miu0,T,T0)): c) Finally, write a third Python file with the script that uses a for loop to find for a range of values by feeding the function created in b) to the bisection function created in a). Have the script plot vs. .

6. Solution
To find the function for which we need to find the roots, plug the second and third equations into the first one and move all terms to one side of the equality sign:

This function is entered as a Python function file as follows:

Now, we can feed this function to the bisection function to find the roots. The following script does that for various values of in a for loop, and plots the results:

The output plot follows:

Anda mungkin juga menyukai