clawtest.py.html clawcode2html   
 Source file:   clawtest.py
 Directory:   /home/rjl/www/pubs/cise08/cise08levequeV2
 Converted:   Wed Jul 2 2008 at 13:40:44
 This documentation file will not reflect any later changes in the source file.

#!/usr/bin/env python
#
# Python script to run xclaw with several different parameter choices.
#

import shelve
import os
from clawplotting import *
from clawtools import *

t0 = os.times()   # keep track of CPU time 

#-------------------------------------
def runtests(itest=1, plotsoln=False):
#-------------------------------------
    '''
    ================================
    Main code to run a set of tests:
    ================================
    '''

    if plotsoln:
        from plotclaw import plotclaw
    


    # set data values:
    data = ClawData()
    data.tfinal = 0.75     # final time

    if plotsoln:
        data.nout = 3          # output at several times for plotting
        data.plot_contour = True
        data.plot_grid = 0
        data.write('setplot2.data')
    else:
        data.nout = 1          # only output at final time
    
    if itest==1:
        # Test only coarse Cartesian grids, runs quickly
        grids = [1]            # set of grids to test
        limiters = [0,3]         # set of limiters (mthlim values) to test
        mxvals_polar = array([10,20])        # mx values on polar grid
        myvals_polar = array([75,150])      # my values on polar grid
        mxvals_other = array([30,60])       # mx values on other grids
        myvals_other = array([30,60])       # my values on other grids
    elif itest==2:
        # Do a few more tests
        grids = [1,3]        # set of grids to test
        limiters = [0,3]       # set of limiters (mthlim values) to test
        mxvals_polar = array([10,20,40])       # mx values on polar grid
        myvals_polar = array([75,150,300])    # my values on polar grid
        mxvals_other = array([30,60,120])     # mx values on other grids
        myvals_other = array([30,60,120])     # my values on other grids
    elif itest==3:
        # Full test of all grids
        grids = [1,2,3]        # set of grids to test
        limiters = [0,3]       # set of limiters (mthlim values) to test
        mxvals_polar = array([10,20,40,80])       # mx values on polar grid
        myvals_polar = array([75,150,300,600])    # my values on polar grid
        mxvals_other = array([30,60,120,240])     # mx values on other grids
        myvals_other = array([30,60,120,240])     # my values on other grids
    else:
        print "Unrecognized input:  itest = ", itest
        sys.exit(1)

    print "------------------------------------------------------------------"

    
    table = {}  # dictionary of data and results for each test
    
    for mthlim in limiters:
        data.mthlim = mthlim
        for igrid in grids:
            data.igrid = igrid
        
            if igrid==2:
                # for polar grid:
                mxvals = mxvals_polar
                myvals = myvals_polar
                data.xlower = 0.2
                data.xupper = 1.0
                data.ylower = 0
                data.yupper = 2*pi
                data.mthbc_ylower = 2
                data.mthbc_yupper = 2
                area = (1 - data.xlower**2)*pi 
            else:
                # for other grids:
                mxvals = mxvals_other
                myvals = myvals_other
                data.xlower = -1.0
                data.xlower = -1.0
                data.xupper = 1.0
                data.ylower = -1.0
                data.yupper = 1.0
                data.mthbc_ylower = 1
                data.mthbc_yupper = 1
                area = pi
        
            table[(mthlim,igrid)] = {} # dictionary to hold data
                                       # and results for this test
            this_table = table[(mthlim,igrid)]  # short name
            this_table['mxvals'] = mxvals       # grid resolutions to test
            this_table['myvals'] = myvals
            this_table['ave_cell_area'] = area / (mxvals*myvals)
            this_table['tfinal'] = data.tfinal
            this_table['errors'] = empty(len(mxvals))
            
            for itest in range(len(mxvals)):
                mx = mxvals[itest]
                my = myvals[itest]
                data.mx = mx
                data.my = my
                data.write('claw2ez.data')
                data.write('setprob.data')

                print "-------------------------------------------------------"
                print 'Running code with igrid = %i, mx = %g, my = %g ...' \
                                      % (igrid,mx,my)
            
                odir = '.'
                # or use next line to put each set of output in separate subdir:
                # odir = 'output_lim%ggrid%gmx%g' % (mthlim,igrid,mx)

                # run fortran code:
                t1 = os.times()
                runclaw(outdir=odir, overwrite=True)
		t2 = os.times()
                CPUtime = t2[2]-t1[2] + t2[3]-t1[3]
                print "CPU time = ",CPUtime
            
                # compute errors:
                errors = compute_errors(odir, frame=data.nout)

                # max-norm of error:
                errormax = abs(errors).max()   

                # approx 1-norm of error:
                errorsum = abs(errors).sum() 
                error1 = errorsum * this_table['ave_cell_area'][itest]

                this_table['errors'][itest] = error1
            
                if plotsoln:
                    # put each set of plots in a different directory:
                    pdir = 'plots_lim%ggrid%gmx%g' % (mthlim,igrid,data.mx)
                    plotclaw(outdir=odir, plotdir=pdir, overwrite=True, \
                         indexentry='mthlim = %2i, igrid = %2i, mx = %4i, \
                         my = %4i' % (mthlim,igrid,mx,my))


    # Save results by shelving them.
    # The results can later be accessed from a different Python process
    # if desired:
    db = shelve.open('table.db')
    db['tfinal'] = data.tfinal
    db['limiters'] = limiters
    db['grids'] = grids
    db['table'] = table
    db.close
    
    # output tables:
    make_text_table(table, limiters, grids, fname='errortables.txt')
    make_latex_table(table, limiters, grids, fname='errortables.tex')

    # log-log plot of errors:
    make_error_plots(table, limiters, grids, fname='errors.png')


#------------------
def qtrue(x,y,t):
#------------------
    # true solution, rotating flow and cosine hump:

    # parameters:
    data = ClawData('setprob.data')
    x1 = data.x1
    x2 = data.x2
    y1 = data.y1
    y2 = data.y2
    xm = (x1 + x2) / 2
    ym = (y1 + y2) / 2
    xscale = 2*pi / (x2-x1)
    yscale = 2*pi / (y2-y1)

    # rotate (x,y) back to time 0:
    tr = 2*pi*t
    x0 = cos(tr)*x + sin(tr)*y
    y0 = -sin(tr)*x + cos(tr)*y

    # evaluate q(x,y,t=0):
    coshump = (1 + cos((x0-xm)*xscale)) * (1 + cos((y0-ym)*yscale))
    inhump = (x0 > x1) & (x0 < x2) & (y0 > y1) & (y0 < y2)
    qtrue = where(inhump, coshump, 0)
    return qtrue



#------------------------------------
def compute_errors(odir='.',frame=0):
#------------------------------------
    # change to output directory and read in solution from fort.q000N
    # for frame N.

    # read in clawpack solution for this frame:
    os.chdir(odir)
    clawframe = read_clawframe(frame)
    
    t = clawframe.t
    
    # Assume there is only one grid (AMR not used):
    grid = clawframe.grids[0]
    
    print "Computing errors for mx, my = ",grid.mx,grid.my
    
    xc = grid.xcenter
    yc = grid.ycenter
    Xc,Yc = meshgrid(xc,yc)
    try:
        file = open('mapc2p.py')
        exec(file)
        file.close()
    except:
        print "Error: mapc2p file not found"
        sys.exit(1)
    
    Xp,Yp = mapc2p(Xc,Yc)
    qq = qtrue(Xp,Yp,t)
    q = transpose(grid.q[:,:,0])
    errors = qq - q
    return errors

    
#-------------------------------------------------------------------
def make_text_table(table, limiters, grids, fname='errortables.txt'):
#-------------------------------------------------------------------
    errfile = open(fname,'w')
    errfile.write('Errors computed by clawtest.py on %s \n\n' \
                   % current_time())
    for mthlim in limiters:
        errfile.write('\n\nLimiter = %g\n===========\n'  % mthlim)
        for igrid in grids:
            errfile.write('\n\nGrid Number %g\n-------------\n'  % igrid)
            errfile.write('  mx    my      ave Delta x         error  ')
            errfile.write('      observed order\n\n')

            # table values for this table:
            te = table[(mthlim,igrid)]   
            for itest in range(len(te['mxvals'])):
                mx = te['mxvals'][itest]
                my = te['myvals'][itest]
                ave_cell_area = te['ave_cell_area'][itest]
                ave_dx = sqrt(ave_cell_area)
                errornorm = te['errors'][itest]
                if itest>0:
                    E1 = te['errors'][itest-1]
                    E2 = te['errors'][itest]
                    A1 = te['ave_cell_area'][itest-1]
                    A2 = te['ave_cell_area'][itest]
                    porder = 2*log(E1/E2)/log(A1/A2)
                else:
                    porder = nan
                errfile.write('%4i  %4i  %14.4e  %16.4e  %16.4e\n' \
                            % (mx, my, ave_dx, errornorm, porder))

    final_time = os.times()
    python_user_time = final_time[0] - t0[0]
    python_system_time = final_time[1] - t0[1]
    fortran_user_time = final_time[2] - t0[2]
    fortran_system_time = final_time[3] - t0[3]
    python_CPUtime = python_user_time + python_system_time
    fortran_CPUtime = fortran_user_time + fortran_system_time
    errfile.write('\n\nTotal python CPU time: %g seconds\n\n' % python_CPUtime)
    errfile.write('\n\nTotal fortran CPU time: %g seconds\n\n' % fortran_CPUtime)
    errfile.close()

    print "------------------------------------------------------------------"
    print "Table of errors is in file ",   fname
    print "------------------------------------------------------------------"
    

#-------------------------------------------------------------------
def make_latex_table(table, limiters, grids, fname='errortables.tex'):
#-------------------------------------------------------------------

    errfile = open(fname,'w')
    errfile.write(r'% ')
    errfile.write(' Errors computed by clawtest.py on %s \n\n' \
                   % current_time())
    
    for igrid in grids:
        t0 = table[(0,igrid)]   # limiter mthlim = 0
        t3 = table[(3,igrid)]   # limiter mthlim = 3
        errfile.write(r'''

          \begin{table}[th]
          \caption{Errors on Grid %i }
          \begin{center}
          \begin{tabular}{|ccc|c|c|c|c|}
          \hline
          &&&\multicolumn{2}{c|}{Limiter = 0}
            &\multicolumn{2}{c|}{Limiter = 3}\\ \hline
          mx & my & Ave $\Delta x$& Error & Observed order
                                  & Error & Observed order\\
          \hline
        '''  % igrid)
        errfile.write('\n')

        # lines in table for each grid resolution:
        for itest in range(len(t0['mxvals'])):
            mx = t0['mxvals'][itest]
            my = t0['myvals'][itest]
            ave_cell_area = t0['ave_cell_area'][itest]
            ave_dx = sqrt(ave_cell_area)
            errornorm0 = t0['errors'][itest]
            if itest>0:
                E1 = t0['errors'][itest-1]
                E2 = t0['errors'][itest]
                A1 = t0['ave_cell_area'][itest-1]
                A2 = t0['ave_cell_area'][itest]
                porder0 = 2*log(E1/E2)/log(A1/A2)
            else:
                porder0 = nan
            errornorm3 = t3['errors'][itest]
            if itest>0:
                E1 = t3['errors'][itest-1]
                E2 = t3['errors'][itest]
                A1 = t3['ave_cell_area'][itest-1]
                A2 = t3['ave_cell_area'][itest]
                porder3 = 2*log(E1/E2)/log(A1/A2)
            else:
                porder3 = nan
            errfile.write('%4i & %4i & %14.4f & %16.4f & %16.2f' \
                        % (mx, my, ave_dx, errornorm0, porder0))
            errfile.write(' & %16.4f & %16.2f \\\\ \n' \
                        % (errornorm3, porder3))


        errfile.write(r'''
          \hline
          \end{tabular}
          \end{center}
          \end{table}

        ''')

    errfile.close()

    print "------------------------------------------------------------------"
    print "Latex table of errors is in file ",  fname
    print "------------------------------------------------------------------"
    
    
#-------------------------------------------------------------------
def make_error_plots(table, limiters, grids, fname='errors.png'):
#-------------------------------------------------------------------
    clf()
    hold(True)
    legendtext = []
    # perform plots in proper order for legend, from worst to best:
    for (igrid,mthlim) in [(3,0),(1,0), (3,3),(1,3), (2,0),(2,3)]:
        try:
            # table entries for this test case:
            te = table[(mthlim,igrid)]   
            dx = sqrt(te['ave_cell_area'])
            loglog(dx,te['errors'],'o-')
	    legendtext.append('Grid %i, Limiter %i' % (igrid,mthlim))
        except:
            pass   # if this case not present
    axis([2e-3,1e-1,1e-4,1])
    xlabel('Average Delta x', fontsize=15)
    ylabel('1-norm of Error', fontsize=15)
    title('Log-log plot of errors', fontsize=15)
    legend(legendtext,'upper left')
    hold(False)
    savefig(fname)


    print "------------------------------------------------------------------"
    print "Plot of errors is in file ",   fname
    print "------------------------------------------------------------------"

if __name__ == '__main__':
    import string
    # execute runtests with any command line arguments:
    cmd = 'runtests(%s)' % string.join(sys.argv[1:])
    exec(cmd)