Homework 6 (Due 6 pm, Wednesday, 11/29/2017)ΒΆ

There are two channels you should submit your homework.

  1. Git repo submission: Please submit your homework to your git repo by 6 pm, Wednesday, 11/29/2017.
  2. Sphinx homepage upload: Please upload your homework files to your homepage two bussiness days after the deadline between 6 pm, Thursday, 11/30/2017 and 6 pm, Friday, 12/1/2017.

In this homework, you are going to implement a Python routine, pyRun_rootFinder.py, which performs the following sequential tasks to compile, run and plot some of the results of the Newton’s root finder algorithm we studied in Fortran Example – Newton’s method to find a root.

Here are very specific guidlines of this homework. It is strongly encouraged that you implement each step by following the guidlines carefully:

  1. make two subdirectories: newton_rootFinder and pyRun, and copy the Fortran Newton’s method code from lecture_note/chapters/chapt02/codes/newton_rootfinder/ and place under the newton_rootFinder directory.

  2. In the Newton’s method code, delete rootFinder.init and just keep the followings:

    RootFinder.F90
    findRootMethod_module.F90
    makefile
    read_initFile_module.F90
    definition.h
    ftn_module.F90
    output_module.F90
    setup_module.F90
    
  3. Now you’re going to implement pyRun_rootFinder.py in the pyRun directory. You need to implement (at least) four different functions and one main code section followed by if __name__ == '__main__': in pyRun_rootFinder.py. For example, a template example should look like:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    """
    Template file for hw6:
    
    Directory structure:
    
       hw6/
           |-- newton_rootFinder/RootFinder.F90
           |                     findRootMethod_module.F90
           |                     makefile
           |                     read_initFile_module.F90
           |                     definition.h
           |                     ftn_module.F90
           |                     output_module.F90
           |                     setup_module.F90
           |                     (excluding rootFinder.init)
           |
           |-- pyRun/pyRun_rootFinder.py
           
    
    """
    
    
    import #import some necessary Python modules
    
    
    def make_make(some inputs???):
        # 1. Compile the Fortran code if has not been compiled
        #    (i.e., if 'rootFinder.exe' does not exists yet);
        #
        # 2. Otherwise do "make clean" first and then "make".
        #
        # 3. You need to change your directory from "pyRun/" to
        #    "newton_rootFinder/" to compile the Fortran code.
    
        
    def runtimeParameters_init(some inputs???):
        # 1. Implement a routine that generates a new "rootFinder.init"
        #    runtime parameter file. Use a proper set of
        #    input arguments to produce a new rootFinder.init
        #    which has all the necessary input parameters to run the Fortran code.
        #    For instance, the first few lines can look like:
        #      run_name     (... and some space ...) 'newton'
        #      method_type  (... and some space ...) 'newton'
        #      ...
        # 2. When writing a new "rootFinder.init", check if there is an old one already.
        #    If so, rename the old one to, say, "rootFinder.init.1" before
        #    creating a new "rootFinder.init". You would end up with having multiple
        #    of them, e.g., "rootFinder.init.1", "rootFinder.init.2", etc.,
        #    along with "rootFinder.init" which is the active runtime parameter file in use.
        
          
    def run_rootFinder(some inputs???):
        # This one executes the Fortran excutable, "rootFinder.exe"
        # using "rootFinder.init" you just created.
    
        
    def plot_data(plotFileName, and more???):
        # 1. This function produces two figures:
        #     (1) solution (y-axis) vs. iteration number (x-axis), and
        #     (2) error (y-axis) vs. iteration number (x-axis).
        #
        # 2. You can plot the two as either subfigures or two separate figures.
        #
        # 3. In each figure, you need to have at least:
        #    xlabel, ylabel, title, line plot with reasonable choices of linestyle and marker.
        #    (see for instance, http://www.scipy-lectures.org/intro/matplotlib/matplotlib.html)
        #
        # 4. Your plots need to have big enough x and y ranges so that your solution and error
        #    graphs are properly fit in the figures.
        #    Make sure that you use one same y-range for solutions and errors, respectively,
        #    so that ALL plots of three different threshold values have the same respective scales in y.
        #
        # 5. You need to plot your results to BOTH screen and png files.
        #    The png file names should bear information on ftn_type, threshold values at least, e.g.,
        #    the file name "result_2_1e-08.png" implies ftn_type = 2, threshold value = 1.e-8.
        #    Do not hardwire three different file names, but use string manipulations in naming them
        #    in your implementation.
        #
        # 6. After plotting, you save the data file "rootFinder_newton.dat"
        #    to a new name, e.g.., "rootFinder_newton.dat.1", etc..
        #    At the end of running three runs for three different threshold values,
        #    you should have collected "rootFinder_newton.dat.1", "rootFinder_newton.dat.2",
        #    as well as the latest data file "rootFinder_newton.dat".
    
        
    if __name__ == '__main__':
    
        # Set runtime parameters here
        # and call the above functions properly,
        # so that this Python code executes the Fortran code
        # for three different threshold values
        # 1.e-4, 1.e-6, 1.e-8
        # ...
        # ...
    

    Your implementation should produce three different data for three different threshold values, 10^{-4}, 10^{-6}, 10^{-8}.

    To do this, you excute pyRun_rootFinder.py only once in the script mode:

    >>> python pyRun_rootFinder.py
    

    which will conduct the following all four tasks sequentially:

    1. compile the Fortran code before running,
    2. write a new runtime parameter file rootFinder.init for each of the three different threshold value, 10^{-4}, 10^{-6}, 10^{-8},
    3. run the Fortran code for each threshold value,
    4. plot each result for each threshold value to both screen and to a file.
  4. Finally, write up a LaTeX report on your findings including figures. You need to specify what your test function is (a function of a single variable x). For your test function, please explore at least two different initial guesses, one that is relatively close to a true solution, the other that is farther away from the true solution of the function. Discuss any convergent behaviors on two different initial guesses. All you need is to find a rough location of an analytic solution, at least approximately, by plotting the function using Python. Keep in mind that all of the run cases are to be done in one execution of pyRun_rootFinder.py in the script mode.