Lab05wsolns

Embed Size (px)

Citation preview

  • 8/13/2019 Lab05wsolns

    1/10

    * Notes based on Chapter 5 from Applied Numerical Methods with MATLAB for Engineers and Scientists,

    Steven C. Chapra, 3rd

    Edition, McGraw-Hill, 2012.

    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 1stpower 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

  • 8/13/2019 Lab05wsolns

    2/10

    o General Non-linearall other equations. # of roots = ?Ex.

    3. Graphical Method

    Plotand 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 Start with interval , o If function changes sign over the interval, evaluate function at midpoint o Define new interval using and whichever from , that gives a function value with

    the sign opposite too Continue iterations (halving the interval) until size of the interval reaches a tolerance

    value.

  • 8/13/2019 Lab05wsolns

    3/10

    Ex. if we want , then we continue the iterations until (take the midpoint as your solution)

    So, if , and = # of iterations, then

    Solving for gives us the number of iterations required to reach a pre-specified valuefor

    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.

  • 8/13/2019 Lab05wsolns

    4/10

    #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 = xrelif 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 = 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 you want to find

    the root for, and feed it to the bisectfunction:

    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:

  • 8/13/2019 Lab05wsolns

    5/10

    root = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000763, Niter = 17

    root = 1.00, ea = 0.0000763, Niter = 17

    root = 1.00, ea = 0.0000763, Niter = 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 = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000763, Niter = 17

    root = 1.00, ea = 0.0000763, Niter = 17

    root = 1.00, ea = 0.0000763, Niter = 17

  • 8/13/2019 Lab05wsolns

    6/10

    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 tobisectat 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 ), weget:

  • 8/13/2019 Lab05wsolns

    7/10

    root = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000006, Niter = 24

    root = 1.00, ea = 0.0000763, Niter = 17

    root = 1.00, ea = 0.0000763, Niter = 17

    Changing the equation to, say , only requires changing the parameters, butnot 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 Start with and o Draw a straight line connectingando Location of is at intersection of this line with x-axiso Define new interval using and whichever from , that gives a function value with

    sign opposite to

    - 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.

  • 8/13/2019 Lab05wsolns

    8/10

    5. Practice Problem

    The resistivity of doped silicon is based on the charge on an electron, the electron density , and theelectron mobility by the equation:

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

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

    For a desired resistivity of V s cm/C, we would like to know how the doping density dependson temperature. Using a reference mobility of cm2(V s)-1at a reference temperature of 300 K andan intrinsic carrier density of cm-3, use the bisection method to solve for the doping densityfor a range of temperatures from 1000 K to 5000 K. Use initial guesses of and for the bisectionmethod. 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:

    defresistivity(N,(rho,ni,miu0,T,T0)):

    c)Finally, write a third Python file with the script that uses a forloop to find for a range of valuesby feeding the function created in b)to the bisection function created in a). Have the script plot vs. .

  • 8/13/2019 Lab05wsolns

    9/10

    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 forloop, and plots the results:

    The output plot follows:

  • 8/13/2019 Lab05wsolns

    10/10