Пример #1
0
def beta_plane_gyre_red_grav():
    print "Running reduced gravity beta-plane gyre example"
    xlen = 1e6
    ylen = 2e6
    nx = 100 
    ny = 200
    layers = 1 # also set in aronnax.conf file
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    def wind(_, Y):
        
        wind_forcing = 0.05 * (1 - np.cos(2*np.pi * Y/np.max(grid.y)))

        plt.figure()
        plt.plot(Y[:,1]/1e3, wind_forcing[:,1])
        plt.xlabel('y coordinate (km)')
        plt.ylabel('Wind forcing (N/m^2)')
        plt.savefig('twin_gyre_wind_forcing.png', 
            bbox_inches='tight', dpi=200)
        plt.close()

        return wind_forcing

    with working_directory(p.join(self_path,
                            "reduced_gravity/beta_plane_gyre")):
        drv.simulate(zonalWindFile=[wind],
                     nx=nx, ny=ny,
                     dx=xlen/nx, dy=ylen/ny,
                     exe=executable)
        with working_directory("figures"):
            plt_output(grid, 'red-grav-twin-gyre', colour_lim=20)
Пример #2
0
def run_davis_control_final_five(nx,
                                 ny,
                                 layers,
                                 nTimeSteps,
                                 dt,
                                 simulation=None):

    #assert layers == 1
    xlen = 1530e3
    ylen = 2730e3
    dx = xlen / nx
    dy = ylen / ny

    grid = aro.Grid(nx, ny, layers, dx, dy)

    with working_directory(
            p.join(self_path, "Davis_et_al_2014/{0}".format(simulation))):
        drv.simulate(initHfile='../final_state_of_control/final.h.0001244161',
                     initUfile='../final_state_of_control/final.u.0001244161',
                     initVfile='../final_state_of_control/final.v.0001244161',
                     zonalWindFile=[davis_wind_x],
                     meridionalWindFile=[davis_wind_y],
                     wind_mag_time_series_file=[davis_wind_time_series],
                     wetMaskFile=[davis_wetmask],
                     spongeHTimeScaleFile=[davis_sponge_h_timescale],
                     spongeHFile=[davis_sponge_h],
                     nx=nx,
                     ny=ny,
                     dx=dx,
                     dy=dy,
                     exe='aronnax_core',
                     dt=dt,
                     dumpFreq=int(86400. * 5.),
                     nTimeSteps=nTimeSteps)
Пример #3
0
def benchmark_gaussian_bump_red_grav_save(grid_points):
    run_time_O1 = np.zeros(len(grid_points))
    run_time_Ofast = np.zeros(len(grid_points))

    def bump(X, Y):
        return 500. + 20 * np.exp(-((6e5 - X)**2 + (5e5 - Y)**2) /
                                  (2 * 1e5**2))

    with working_directory(p.join(self_path, "beta_plane_bump_red_grav")):
        aro_exec = "aronnax_test"
        for counter, nx in enumerate(grid_points):
            run_time_O1[counter] = aro.simulate(exe=aro_exec,
                                                initHfile=[bump],
                                                nx=nx,
                                                ny=nx)

        aro_exec = "aronnax_core"
        for counter, nx in enumerate(grid_points):
            run_time_Ofast[counter] = aro.simulate(exe=aro_exec,
                                                   initHfile=[bump],
                                                   nx=nx,
                                                   ny=nx)

        with open("times.pkl", "w") as f:
            pkl.dump((grid_points, run_time_O1, run_time_Ofast), f)
Пример #4
0
def beta_plane_gyre_n_layer():
    print "Running n-layer beta-plane gyre example"
    xlen = 1e6
    ylen = 2e6
    nx = 100
    ny = 200
    layers = 2
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    def wind(_, Y):
        
        wind_forcing = 0.05 * (1 - np.cos(2*np.pi * Y/np.max(grid.y)))

        plt.figure()
        plt.plot(Y[:,1]/1e3, wind_forcing[:,1])
        plt.xlabel('Latitude (km)')
        plt.ylabel('Wind forcing (N/m^2)')
        plt.savefig('twin_gyre_wind_forcing.png', 
            bbox_inches='tight', dpi=200)
        plt.close()

        return wind_forcing

    with working_directory(p.join(self_path, "n_layer/beta_plane_gyre")):
        drv.simulate(zonalWindFile=[wind],
                     exe=executable,
                     nx=nx, ny=ny, layers=layers,
                     dx=xlen/nx, dy=ylen/ny,
                     nTimeSteps = 20001, dumpFreq = 6e5, avFreq = 48e5
                     # NB: this takes quite a long time to run.
                     )
        with working_directory("figures"):
            plt_output(grid, 'n-layer-twin-gyre', colour_lim=20)
Пример #5
0
def benchmark_parallel_gaussian_bump_save(n_procs):
    run_time = np.zeros(len(n_procs))
    nx = 120

    def bump(X, Y):
        return 500. + 20 * np.exp(-((6e5 - X)**2 + (5e5 - Y)**2) /
                                  (2 * 1e5**2))

    with working_directory(p.join(self_path, "beta_plane_bump")):
        aro_exec = "aronnax_external_solver"
        for counter, nProcX in enumerate(n_procs):
            if nProcX == 1:
                run_time[counter] = aro.simulate(
                    exe=aro_exec,
                    initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)],
                    nx=nx,
                    ny=nx)
            else:
                run_time[counter] = aro.simulate(
                    exe=aro_exec,
                    initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)],
                    nx=nx,
                    ny=nx,
                    nProcX=nProcX)

        with open("mpi_times.pkl", "wb") as f:
            pkl.dump((n_procs, run_time), f)
Пример #6
0
def do_n_layer(nx, aro_build, perf):
    with working_directory(p.join(self_path, "beta_plane_bump")):
        aro.simulate(exe=aro_build,
                     nx=nx,
                     ny=nx,
                     perf=perf,
                     initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)])
Пример #7
0
def test_vertical_thickness_diffusion_Hypre_3_layers():
    nx = 2
    ny = 2
    layers = 3

    dx = 1e4
    dy = 1e4

    grid = aro.Grid(nx, ny, layers, dx, dy)

    kv = 1e-5
    initH = [10., 100., 10.]

    def wetmask(X, Y):
        mask = np.ones(X.shape, dtype=np.float64)
        return mask

    # 2 years
    dt = 200.
    nTimeSteps = int(0.25 * 365 * 86400 / dt)
    diagFreq = nTimeSteps * dt / 50.

    with working_directory(p.join(self_path, "vertical_diffusion")):
        drv.simulate(initHfile=[10., 100., 10.],
                     nx=nx,
                     ny=ny,
                     dx=dx,
                     dy=dy,
                     layers=3,
                     exe="aronnax_external_solver_test",
                     wetMaskFile=[wetmask],
                     depthFile=[120.],
                     fUfile=[-1e-4],
                     fVfile=[-1e-4],
                     kv=kv,
                     dt=dt,
                     nTimeSteps=nTimeSteps,
                     diagFreq=diagFreq,
                     dumpFreq=1e9,
                     RedGrav=0)

        simuated_h_evo = np.loadtxt('output/diagnostic.h.csv',
                                    delimiter=',',
                                    skiprows=1,
                                    usecols=(0, 2, 6, 10))
        expected_h_evo = np.sqrt(simuated_h_evo[:, 0] * dt * kv * 2. +
                                 initH[0]**2)

        # plt.plot(simuated_h_evo[:,0]*dt, expected_h_evo, label='expected')
        # plt.plot(simuated_h_evo[:,0]*dt, simuated_h_evo[:,1], label='simulated top')
        # plt.plot(simuated_h_evo[:,0]*dt, simuated_h_evo[:,2], label='simulated mid')
        # plt.plot(simuated_h_evo[:,0]*dt, simuated_h_evo[:,3], label='simulated bottom')
        # plt.legend()
        # plt.savefig('h_evo.pdf')
        assert np.max(
            abs(simuated_h_evo[:, 1] - simuated_h_evo[:, 3])) < 0.0005
Пример #8
0
def test_gaussian_bump_red_grav():
    xlen = 1e6
    ylen = 1e6
    with working_directory(p.join(self_path, "beta_plane_bump_red_grav")):
        drv.simulate(initHfile=[bump],
                     exe=test_executable,
                     nx=10,
                     ny=10,
                     dx=xlen / 10,
                     dy=ylen / 10)
        assert_outputs_close(10, 10, 1, 1.5e-13)
        assert_volume_conservation(10, 10, 1, 1e-5)
Пример #9
0
def test_gaussian_bump():
    xlen = 1e6
    ylen = 1e6
    with working_directory(p.join(self_path, "beta_plane_bump")):
        drv.simulate(initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)],
                     nx=10,
                     ny=10,
                     exe=test_executable,
                     dx=xlen / 10,
                     dy=ylen / 10)
        assert_outputs_close(10, 10, 2, 2e-13)
        assert_volume_conservation(10, 10, 2, 1e-5)
Пример #10
0
def test_f_plane():
    xlen = 1e6
    ylen = 1e6
    with working_directory(p.join(self_path, "f_plane")):
        drv.simulate(exe=test_executable,
                     nx=10,
                     ny=10,
                     dx=xlen / 10,
                     dy=ylen / 10)
        assert_outputs_close(10, 10, 2, 1e-15)
        assert_volume_conservation(10, 10, 2, 1e-5)
        assert_diagnostics_similar(['h'], 1e-10)
Пример #11
0
def test_relative_wind_upwind_advection():
    nx = 320
    ny = 320
    layers = 1
    xlen = 1280e3
    ylen = 1280e3
    dx = xlen / nx
    dy = ylen / ny

    grid = aro.Grid(nx, ny, layers, dx, dy)

    def wetmask(X, Y):
        # water everywhere, doubly periodic
        wetmask = np.ones(X.shape, dtype=np.float64)
        return wetmask

    def wind_x(X, Y):
        rMx = 300e3  # radius of circle where Max wind stress
        r = np.sqrt((Y - 640e3)**2 + (X - 640e3)**2)
        theta = np.arctan2(Y - 640e3, X - 640e3)
        tau = np.sin(np.pi * r / rMx / 2.)
        tau_x = tau * np.sin(theta)
        tau_x[r > 2. * rMx] = 0

        return tau_x

    def wind_y(X, Y):
        rMx = 300e3  # radius of circle where Max wind stress
        r = np.sqrt((Y - 640e3)**2 + (X - 640e3)**2)
        theta = np.arctan2(Y - 640e3, X - 640e3)
        tau = np.sin(np.pi * r / rMx / 2.)
        tau_y = -tau * np.cos(theta)
        tau_y[r > 2. * rMx] = 0
        return tau_y

    with working_directory(p.join(self_path, "relative_wind")):
        drv.simulate(initHfile=[400],
                     zonalWindFile=[wind_x],
                     meridionalWindFile=[wind_y],
                     wind_mag_time_series_file=[0.08],
                     exe=test_executable,
                     wetMaskFile=[wetmask],
                     nx=nx,
                     ny=ny,
                     dx=dx,
                     dy=dy,
                     hAdvecScheme=2)
        assert_outputs_close(nx, ny, layers, 3e-11)
        assert_volume_conservation(nx, ny, layers, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v'], 1e-10)
Пример #12
0
def test_gaussian_bump_continuation():
    xlen = 1e6
    ylen = 1e6
    with working_directory(p.join(self_path, "beta_plane_bump")):
        drv.simulate(initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)],
                     nx=10,
                     ny=10,
                     exe=test_executable,
                     dx=xlen / 10,
                     dy=ylen / 10,
                     niter0=201,
                     nTimeSteps=200)
        assert_outputs_close(10, 10, 2, 2e-13)
        assert_volume_conservation(10, 10, 2, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v', 'eta'], 1e-10)
Пример #13
0
def test_gaussian_bump_red_grav_debug_test():
    xlen = 1e6
    ylen = 1e6
    with working_directory(
            p.join(self_path, "beta_plane_bump_red_grav_debug_test")):
        drv.simulate(initHfile=[bump],
                     exe=test_executable,
                     nx=10,
                     ny=10,
                     dx=xlen / 10,
                     dy=ylen / 10,
                     nProcY=2)
        assert_outputs_close(10, 10, 1, 1.5e-13)
        assert_volume_conservation(10, 10, 1, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v'], 1e-10)
Пример #14
0
def test_gaussian_bump_red_grav_continuation_of_single_core_MPI_2X():
    xlen = 1e6
    ylen = 1e6
    with working_directory(p.join(self_path, "beta_plane_bump_red_grav")):
        drv.simulate(initHfile=[bump],
                     exe=test_executable,
                     nx=10,
                     ny=10,
                     dx=xlen / 10,
                     dy=ylen / 10,
                     niter0=101,
                     nTimeSteps=400,
                     nProcX=2)
        assert_outputs_close(10, 10, 1, 1.5e-13)
        assert_volume_conservation(10, 10, 1, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v'], 1e-10)
Пример #15
0
def beta_plane_bump_n_layer():
    print "Running n-layer beta-plane bump example"
    xlen = 1e6
    ylen = 1e6
    nx = 100
    ny = 100
    layers = 2 # also set in aronnax.conf file
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    with working_directory(p.join(self_path, "n_layer/beta_plane_bump")):
        drv.simulate(initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)],
                     exe=executable,
                     nx=nx, ny=ny,
                     dx=xlen/nx, dy=ylen/ny)
        with working_directory("figures"):
            plt_output(grid, 'n-layer-bump')
Пример #16
0
def beta_plane_bump_red_grav():
    print "Running reduced gravity beta-plane bump example"
    xlen = 1e6
    ylen = 1e6
    nx = 100
    ny = 100
    layers = 1 # also set in aronnax.conf file
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    with working_directory(p.join(self_path,
                            "reduced_gravity/beta_plane_bump")):
        drv.simulate(initHfile=[bump],
                     exe=executable,
                     nx=nx, ny=ny,
                     dx=xlen/nx, dy=ylen/ny)
        with working_directory("figures"):
            plt_output(grid, 'red-grav-bump')
Пример #17
0
def test_vertical_thickness_diffusion():
    nx = 2
    ny = 2

    dx = 1e4
    dy = 1e4

    grid = aro.Grid(nx, ny, 1, dx, dy)

    kv = 1e-5
    initH = 10.

    def wetmask(X, Y):
        mask = np.ones(X.shape, dtype=np.float64)
        return mask

    # 2 years
    dt = 200.
    nTimeSteps = int(0.25 * 365 * 86400 / dt)
    diagFreq = nTimeSteps * dt / 50.

    with working_directory(p.join(self_path, "vertical_diffusion")):
        drv.simulate(initHfile=[initH],
                     nx=nx,
                     ny=ny,
                     dx=dx,
                     dy=dy,
                     exe="aronnax_test",
                     wetMaskFile=[wetmask],
                     fUfile=[-1e-4],
                     fVfile=[-1e-4],
                     kv=kv,
                     dt=dt,
                     nTimeSteps=nTimeSteps,
                     diagFreq=diagFreq,
                     dumpFreq=1e9)

        simuated_h_evo = np.loadtxt('output/diagnostic.h.csv',
                                    delimiter=',',
                                    skiprows=1,
                                    usecols=(0, 2))
        expected_h_evo = np.sqrt(simuated_h_evo[:, 0] * dt * kv * 2. +
                                 initH**2)
        assert np.max(abs(simuated_h_evo[:, 1] - expected_h_evo)) < 0.0005
Пример #18
0
def test_beta_plane_gyre_free_surf_Hypre_MPI(nProcX=1, nProcY=1):
    xlen = 1e6
    ylen = 2e6
    nx = 10
    ny = 20
    layers = 2
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    def wind(_, Y):
        return 0.05 * (1 - np.cos(2 * np.pi * Y / np.max(grid.y)))

    with working_directory(p.join(self_path,
                                  "beta_plane_gyre_free_surf_hypre")):
        if (nProcX == 1 and nProcY == 1):
            drv.simulate(zonalWindFile=[wind],
                         valgrind=False,
                         nx=nx,
                         ny=ny,
                         exe='aronnax_external_solver_test',
                         dx=xlen / nx,
                         dy=ylen / ny)
        elif (nProcX != 1 and nProcY == 1):
            drv.simulate(zonalWindFile=[wind],
                         valgrind=False,
                         nx=nx,
                         ny=ny,
                         exe='aronnax_external_solver_test',
                         dx=xlen / nx,
                         dy=ylen / ny,
                         nProcX=nProcX)
        elif (nProcX == 1 and nProcY != 1):
            drv.simulate(zonalWindFile=[wind],
                         valgrind=False,
                         nx=nx,
                         ny=ny,
                         exe='aronnax_external_solver_test',
                         dx=xlen / nx,
                         dy=ylen / ny,
                         nProcY=nProcY)
        else:
            drv.simulate(zonalWindFile=[wind],
                         valgrind=False,
                         nx=nx,
                         ny=ny,
                         exe='aronnax_external_solver_test',
                         dx=xlen / nx,
                         dy=ylen / ny,
                         nProcX=nProcX,
                         nProcY=nProcY)

        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v', 'eta'], 1e-8)
Пример #19
0
def test_periodic_BC_red_grav():
    nx = 50
    ny = 20
    layers = 2

    dx = 5e4
    dy = 5e4

    grid = aro.Grid(nx, ny, layers, dx, dy)

    rho0 = 1035

    def wetmask(X, Y):
        mask = np.ones(X.shape, dtype=np.float64)
        return mask

    def layer_1(X, Y):
        return 500. + 300 * np.exp(-((6e5 - X)**2 + (6e5 - Y)**2) /
                                   (2 * 1e5**2))

    def layer_2(X, Y):
        return 1000. - layer_1(X, Y)

    with working_directory(p.join(self_path, "periodic_BC_red_grav")):
        drv.simulate(initHfile=[layer_1, layer_2],
                     nx=nx,
                     ny=ny,
                     layers=layers,
                     dx=dx,
                     dy=dy,
                     exe=test_executable,
                     wetMaskFile=[wetmask],
                     fUfile=[-1e-4],
                     fVfile=[-1e-4],
                     nTimeSteps=801,
                     dumpFreq=10000,
                     nProcY=2)
        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v'], 1e-10)
Пример #20
0
def test_beta_plane_gyre_free_surf():
    xlen = 1e6
    ylen = 2e6
    nx = 10
    ny = 20
    layers = 2
    grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny)

    def wind(_, Y):
        return 0.05 * (1 - np.cos(2 * np.pi * Y / np.max(grid.y)))

    with working_directory(p.join(self_path, "beta_plane_gyre_free_surf")):
        drv.simulate(zonalWindFile=[wind],
                     valgrind=False,
                     nx=nx,
                     ny=ny,
                     exe=test_executable,
                     dx=xlen / nx,
                     dy=ylen / ny)
        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v', 'eta'], 1e-8)
Пример #21
0
def test_periodic_BC_Hypre():
    nx = 50
    ny = 20
    layers = 2

    dx = 5e4
    dy = 5e4

    grid = aro.Grid(nx, ny, layers, dx, dy)

    rho0 = 1035

    def wetmask(X, Y):
        mask = np.ones(X.shape, dtype=np.float64)
        return mask

    def eta(X, Y):
        return 0. + 1. * np.exp(-((6e5 - X)**2 + (5e5 - Y)**2) / (2 * 1e5**2))

    with working_directory(p.join(self_path, "periodic_BC")):
        drv.simulate(initHfile=[500., 500.],
                     nx=nx,
                     ny=ny,
                     layers=layers,
                     dx=dx,
                     dy=dy,
                     exe="aronnax_external_solver_test",
                     wetMaskFile=[wetmask],
                     fUfile=[-1e-4],
                     fVfile=[-1e-4],
                     initEtaFile=[eta],
                     depthFile=[1000.],
                     nTimeSteps=801,
                     dumpFreq=10000)
        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 3e-5)
Пример #22
0
def do_red_grav(nx, aro_build, perf):
    with working_directory(p.join(self_path, "beta_plane_bump_red_grav")):
        aro.simulate(exe=aro_build, initHfile=[bump], nx=nx, ny=nx, perf=perf)
Пример #23
0
def run_ice_drag(nTimeSteps, dt, kappa, wind_mag, wind_stoch, wind_period,
                    dir=None, iniH=400.):

    #assert layers == 1
    nx = 320
    ny = 320
    layers = 1
    xlen = 1280e3
    ylen = 1280e3
    dx = xlen / nx
    dy = ylen / ny

    grid = aro.Grid(nx, ny, layers, dx, dy)

    if wind_stoch:
        def wind_time_series(nTimeSteps, dt):
            # np.random.seed(42)
            wind_ts = (np.random.rand(nTimeSteps)*wind_mag) + (wind_mag/2.)
            return wind_ts
    elif wind_period!=0:
        # sinusoidally varying wind
        def wind_time_series(nTimeSteps, dt):
            time_vec = np.arange(nTimeSteps, dtype=np.float)*dt
            wind_ts = wind_mag*(1. + 0.5*np.sin(2.*np.pi*time_vec/wind_period))
            return wind_ts
    else:
        wind_time_series = wind_mag

    with working_directory(p.join(self_path, 
        "{0}".format(dir))):
        niter0 = find_last_checkpoint()

        # because of the frustrating restriction about setting things to
        # 0 or 1, we need if statements here.
        if niter0 == 0:
            if kappa == 0:
                drv.simulate(
                        initHfile=[iniH],
                        wind_mag_time_series_file=[wind_time_series],
                        wetMaskFile=[BG_wetmask],
                        nx=nx, ny=ny, dx=dx, dy=dy, 
                        exe='aronnax_core', 
                        dt=dt, nTimeSteps=nTimeSteps)
            else:
                drv.simulate(
                        initHfile=[iniH],
                        wind_mag_time_series_file=[wind_time_series],
                        wetMaskFile=[BG_wetmask],
                        kh=kappa,
                        nx=nx, ny=ny, dx=dx, dy=dy, 
                        exe='aronnax_core', 
                        dt=dt, nTimeSteps=nTimeSteps)

        else:
            if kappa == 0:
                drv.simulate(
                        initHfile=[iniH],
                        wind_mag_time_series_file=[wind_time_series],
                        wetMaskFile=[BG_wetmask],
                        niter0=niter0,
                        nx=nx, ny=ny, dx=dx, dy=dy, 
                        exe='aronnax_core', 
                        dt=dt, nTimeSteps=nTimeSteps)
            else:
                drv.simulate(
                        initHfile=[iniH],
                        wind_mag_time_series_file=[wind_time_series],
                        wetMaskFile=[BG_wetmask],
                        kh=kappa,
                        niter0=niter0,
                        nx=nx, ny=ny, dx=dx, dy=dy, 
                        exe='aronnax_core', 
                        dt=dt, nTimeSteps=nTimeSteps)
Пример #24
0
def ocean_drain():

    nx = 400
    ny = 960
    layers = 1
    dx = 5000
    dy = 5000

    def wetmask(X, Y):
        """The wet mask."""

        depth = bathymetry(X, Y, plot=False)

        wetmask = np.zeros(X.shape, dtype=np.float64)

        wetmask[depth > 0] = 1

        # set land on the edges
        wetmask[0, :] = 0
        wetmask[-1, :] = 0
        wetmask[:, 0] = 0
        wetmask[:, -1] = 0

        return wetmask

    def bathymetry(X, Y, plot=True):

        d_max = 6000
        width_scale = 3. / 1000e3

        x_depth = 0.5 * d_max * (np.tanh(X * width_scale) + np.tanh(
            (X.max() - X) * width_scale))

        y_depth = (0.5 * d_max * (np.tanh(Y * width_scale) + np.tanh(
            (Y.max() - Y) * width_scale)) -
                   np.maximum(4e2 * (4320e3 - Y) / 1823e3, 0))

        depth = (x_depth + y_depth) / 2.

        depth = depth - 2000

        depth[depth < 0] = 0

        # set minimum depth to 250 m (also the model won't run if depthFile
        #   contains negative numbers)
        # depth = np.maximum(depth, 250)

        if plot:
            plt.pcolormesh(X / 1e3, Y / 1e3,
                           np.ma.masked_where(depth < 0, depth))
            plt.colorbar()
            plt.axes().set_aspect('equal')
            plt.savefig('depth.png', bbox_inches='tight')
            plt.close()

        return depth

    with working_directory(p.join(self_path, 'spin_up')):
        drv.simulate(
            # give it flat layers and let it squash them to fit
            initHfile=[4000],
            wetMaskFile=[wetmask],
            depthFile=[bathymetry],
            nx=nx,
            ny=ny,
            dx=dx,
            dy=dy,
            exe='aronnax_external_solver',
            dt=50,
            nTimeSteps=12441600)
Пример #25
0
def test_f_plane_Hypre_botDrag(botDrag=1e-5, layers=1):

    test_executable = "aronnax_external_solver_test"

    dt = 100

    nx = 10
    ny = 10
    dx = 1e3
    dy = 1e3

    rho0 = 1035.

    grid = aro.Grid(nx, ny, layers, dx, dy)

    def init_U(X, Y, *arg):
        init_u = np.zeros(Y.shape, dtype=np.float64)
        init_u[:, :] = 3e-5

        return init_u

    def dbl_periodic_wetmask(X, Y):
        return np.ones(X.shape, dtype=np.float64)

    with working_directory(p.join(self_path, "bot_drag")):

        if layers == 1:
            drv.simulate(initHfile=[400.],
                         initUfile=[init_U],
                         depthFile=[layers * 400],
                         exe=test_executable,
                         wetMaskFile=[dbl_periodic_wetmask],
                         nx=nx,
                         ny=ny,
                         dx=dx,
                         dy=dy,
                         dt=dt,
                         dumpFreq=200,
                         diagFreq=dt,
                         botDrag=botDrag,
                         nTimeSteps=400)
        else:
            drv.simulate(initHfile=[400. for i in range(layers)],
                         initUfile=[init_U for i in range(layers)],
                         depthFile=[layers * 400],
                         exe=test_executable,
                         wetMaskFile=[dbl_periodic_wetmask],
                         nx=nx,
                         ny=ny,
                         layers=layers,
                         dx=dx,
                         dy=dy,
                         dt=dt,
                         dumpFreq=200,
                         diagFreq=dt,
                         botDrag=botDrag,
                         nTimeSteps=400)

        hfiles = sorted(glob.glob("output/snap.h.*"))
        ufiles = sorted(glob.glob("output/snap.u.*"))
        vfiles = sorted(glob.glob("output/snap.v.*"))

        model_iteration = np.zeros(len(hfiles))

        momentum = np.zeros(len(hfiles))
        momentum_expected = np.zeros(len(hfiles))

        for counter, ufile in enumerate(ufiles):

            h = aro.interpret_raw_file(hfiles[counter], nx, ny, layers)
            u = aro.interpret_raw_file(ufile, nx, ny, layers)
            v = aro.interpret_raw_file(vfiles[counter], nx, ny, layers)

            model_iteration[counter] = float(ufile[-10:])

            momentum[counter] = (
                nx * ny * dx * dy * rho0 *
                (np.mean(h[-1, :, :]) *
                 (np.mean(u[-1, :, :]) + np.mean(v[-1, :, :]))))

        opt.assert_volume_conservation(nx, ny, layers, 1e-9)

        init_h = 400
        X, Y = np.meshgrid(grid.x, grid.yp1)
        init_u = init_U(X, Y)

        momentum_expected[:] = (nx * ny * dx * dy * rho0 *
                                (np.mean(init_h) * np.mean(init_u[:, :])) *
                                np.exp(-model_iteration * dt * botDrag))

        test_passes = True

        try:
            np.testing.assert_allclose(momentum,
                                       momentum_expected,
                                       rtol=2e-3,
                                       atol=0)
            return
        except AssertionError as error:
            test_passes = False

            # plot output for visual inspection
            plt.figure()
            plt.plot(model_iteration * dt / (86400),
                     momentum,
                     '-',
                     alpha=1,
                     label='Simulated momentum')
            plt.plot(model_iteration * dt / (86400),
                     momentum_expected,
                     '-',
                     alpha=1,
                     label='Expected momentum')
            plt.legend()
            plt.xlabel('Time (days)')
            plt.ylabel('Momentum')
            plt.savefig('f_plane_momentum_test.png', dpi=150)

            plt.figure()
            plt.plot(model_iteration, momentum / momentum_expected)
            plt.xlabel('timestep')
            plt.ylabel('simulated/expected')
            plt.savefig('momentum_ratio.png')
            plt.close()

            plt.figure()
            plt.plot(model_iteration * dt / (86400),
                     100. * (momentum - momentum_expected) / momentum_expected)
            plt.xlabel('Time (days)')
            plt.ylabel('percent error')
            plt.ylim(-20, 80)
            plt.savefig('momentum_percent_error.png')
            plt.close()

        assert test_passes
Пример #26
0
def test_Hypre_spatial_wind_interp():
    nx = 16
    ny = 32
    layers = 2
    xlen = 640e3
    ylen = 1280e3
    dx = xlen / nx
    dy = ylen / ny

    grid = aro.Grid(nx, ny, layers, dx, dy)

    wind_n_records = 2

    def wetmask(X, Y):
        # water everywhere, doubly periodic
        wetmask = np.ones(X.shape, dtype=np.float64)
        wetmask[0, :] = 0
        wetmask[-1, :] = 0
        # wetmask[:,0] = 0
        # wetmask[:,-1] = 0
        return wetmask

    def wind_x(X, Y, wind_n_records):
        tau_x = np.zeros((wind_n_records, X.shape[0], X.shape[1]))

        rMx = 300e3  # radius of circle where Max wind stress

        for i in range(wind_n_records):
            X0 = 640e3 * i / (wind_n_records - 1)
            r = np.sqrt((Y - 640e3)**2 + (X - X0)**2)
            theta = np.arctan2(Y - 640e3, X - X0)
            tau = np.sin(np.pi * r / rMx / 2.)
            tau_x[i, :, :] = tau * np.sin(theta)
            r = np.sqrt((Y - 640e3)**2 + (X - 640e3)**2)
            tau_x[i, r > 2. * rMx] = 0

        return tau_x

    def wind_y(X, Y, wind_n_records):
        tau_y = np.zeros((wind_n_records, X.shape[0], X.shape[1]))
        rMx = 300e3  # radius of circle where Max wind stress

        for i in range(wind_n_records):
            X0 = 640e3 * i / (wind_n_records - 1)
            r = np.sqrt((Y - 640e3)**2 + (X - X0)**2)
            theta = np.arctan2(Y - 640e3, X - X0)
            tau = np.sin(np.pi * r / rMx / 2.)
            tau_y[i, :, :] = -tau * np.cos(theta)
            r = np.sqrt((Y - 640e3)**2 + (X - 640e3)**2)
            tau_y[i, r > 2. * rMx] = 0
        return tau_y

    with working_directory(p.join(self_path, "shifting_wind_interp")):
        drv.simulate(initHfile=[400, 400],
                     depthFile=[800],
                     wind_n_records=3,
                     zonalWindFile=[wind_x],
                     meridionalWindFile=[wind_y],
                     wind_mag_time_series_file=[0.1],
                     exe=test_executable,
                     wetMaskFile=[wetmask],
                     nx=nx,
                     ny=ny,
                     dx=dx,
                     dy=dy)
        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 1e-5)
        assert_diagnostics_similar(['h', 'u', 'v'], 1e-10)
Пример #27
0
def test_outcropping_Hypre():

    nx = 60
    ny = 30
    layers = 2
    xlen = 120e3
    ylen = 120e3
    dx = xlen / nx
    dy = ylen / ny

    grid = aro.Grid(nx, ny, layers, dx, dy)

    def wetmask(X, Y):
        # start with water everywhere and add some land
        wetmask = np.ones(X.shape, dtype=np.float64)

        # clean up the edges
        wetmask[0, :] = 0
        wetmask[-1, :] = 0

        return wetmask

    def bathymetry(X, Y):
        depth = 50 + 50 * Y / Y.max()
        return depth

    def init_h1(X, Y):
        depth = bathymetry(X, Y)
        proto_h1 = 150 - 200 * Y / Y.max()
        # leave 0.1 m for bottom layer
        h1 = np.minimum(proto_h1, depth) - 0.1
        # set outrcropped region to 0.1 m thick
        h1 = np.maximum(h1, 0.1 + 0 * X)
        # crude smoothing to reduce the sharp gradients
        h1[1:, :] = (h1[1:, :] + h1[:-1, :]) / 2
        h1[:, 1:] = (h1[:, 1:] + h1[:, :-1]) / 2.
        return h1

    def init_h2(X, Y):
        depth = bathymetry(X, Y)
        h1 = init_h1(X, Y)
        h2 = depth - h1
        return h2

    with working_directory(p.join(self_path, 'outcropping')):
        drv.simulate(initHfile=[init_h1, init_h2],
                     zonalWindFile=[0.1],
                     meridionalWindFile=[0],
                     wind_depth=40,
                     wetMaskFile=[wetmask],
                     depthFile=[bathymetry],
                     nx=nx,
                     ny=ny,
                     layers=layers,
                     dx=dx,
                     dy=dy,
                     exe='aronnax_external_solver_test',
                     dt=10,
                     nTimeSteps=1000)
        assert_outputs_close(nx, ny, layers, 3e-12)
        assert_volume_conservation(nx, ny, layers, 3e-5)
Пример #28
0
def Yang_et_al_spin_up():

    nx = 200
    ny = 200
    layers = 2
    xlen = 1000e3
    ylen = 1000e3
    dx = xlen / nx
    dy = ylen / ny

    def wind_x(X, Y):

        L = 500e3

        r = np.sqrt((Y - 500e3)**2 + (X - 500e3)**2)
        theta = np.arctan2(Y - 500e3, X - 500e3)

        tau_x = np.sin(0.5 * np.pi * r / L)
        tau_x = tau_x * np.sin(theta) * 0.025
        tau_x[r > L] = 0

        plt.pcolormesh(X, Y, tau_x)
        plt.colorbar()
        plt.savefig('tau_x.pdf')
        plt.close()

        return tau_x

    def wind_y(X, Y):
        L = 500e3

        r = np.sqrt((Y - 500e3)**2 + (X - 500e3)**2)
        theta = np.arctan2(Y - 500e3, X - 500e3)

        tau_y = np.sin(0.5 * np.pi * r / L)
        tau_y = -tau_y * np.cos(theta) * 0.025
        tau_y[r > L] = 0

        plt.pcolormesh(X, Y, tau_y)
        plt.colorbar()
        plt.savefig('tau_y.pdf')
        plt.close()

        return tau_y

    def wetmask(X, Y):
        """The wet mask."""

        # start with land everywhere and carve out space for water
        wetmask = np.zeros(X.shape, dtype=np.float64)
        # circular gyre region
        wetmask[((Y - 500e3)**2 + (X - 500e3)**2) < 500e3**2] = 1

        # clean up the edges
        wetmask[0, :] = 0
        wetmask[-1, :] = 0
        wetmask[:, 0] = 0
        wetmask[:, -1] = 0

        return wetmask

    def bathymetry(X, Y):
        mask = wetmask(X, Y)
        r = np.sqrt((Y - 500e3)**2 + (X - 500e3)**2)

        # creating slope near southern boundary
        depth = np.minimum(4000 * np.ones(X.shape), 15250 - 0.03 * r)
        # set minimum depth to 250 m (also the model won't run if depthFile
        #   contains negative numbers)
        depth = np.maximum(depth, 250)

        plt.pcolormesh(X, Y, np.ma.masked_where(mask == 0, depth))
        plt.colorbar()
        plt.savefig('depth.pdf')
        plt.close()

        return depth

    def coriolis(X, Y):
        r = np.sqrt((Y - 500e3)**2 + (X - 500e3)**2)

        f0 = 14.5842318e-5  # at north pole
        beta = f0 * np.cos(np.pi * 85 / 180) / 6371e3

        f = f0 - beta * r

        plt.pcolormesh(X, Y, f)
        plt.colorbar()
        plt.savefig('coriolis.pdf')
        plt.close()
        return f

    with working_directory(p.join(self_path, 'spin_up')):
        drv.simulate(
            # give it flat layers and let it squash them to fit
            initHfile=[400, 3600],
            zonalWindFile=[wind_x],
            meridionalWindFile=[wind_y],
            wind_depth=30,
            wetMaskFile=[wetmask],
            depthFile=[bathymetry],
            fUfile=[coriolis],
            fVfile=[coriolis],
            nx=nx,
            ny=ny,
            layers=layers,
            dx=dx,
            dy=dy,
            exe='aronnax_external_solver',
            dt=50,
            nTimeSteps=12441600)
Пример #29
0
def f_plane_init_u_test(physics, aro_exec, dt):
    nx = 100
    ny = 100
    layers = 1

    dx = 10e3
    dy = 10e3

    rho0 = 1035.

    grid = aro.Grid(nx, ny, layers, dx, dy)

    def init_U(X, Y, *arg):
        init_u = np.zeros(Y.shape, dtype=np.float64)
        init_u[int(grid.nx / 2), int(grid.ny / 2)] = 3e-5
        init_u[:, :] = 3e-5

        if not arg:
            plt.figure()
            plt.pcolormesh(init_u)
            plt.colorbar()
            plt.savefig('init_u.png')
        return init_u

    def init_V(X, Y, *arg):
        init_v = np.zeros(X.shape, dtype=np.float64)
        init_v[int(nx / 2), int(ny / 2)] = 3e-5
        init_v[:, :] = 3e-5

        if not arg:
            plt.figure()
            plt.pcolormesh(init_v)
            plt.colorbar()
            plt.savefig('init_v.png')
        return init_v

    def dbl_periodic_wetmask(X, Y):
        return np.ones(X.shape, dtype=np.float64)

    with working_directory(
            p.join(self_path,
                   "physics_tests/f_plane_{0}_init_u".format(physics))):

        sub.check_call(["rm", "-rf", "output/"])
        drv.simulate(
            initHfile=[400.],
            initUfile=[init_U],
            # initVfile=[init_V], valgrind=False,
            wetMaskFile=[dbl_periodic_wetmask],
            nx=nx,
            ny=ny,
            exe=aro_exec,
            dx=dx,
            dy=dy,
            nTimeSteps=40000)

        hfiles = sorted(glob.glob("output/snap.h.*"))
        ufiles = sorted(glob.glob("output/snap.u.*"))
        vfiles = sorted(glob.glob("output/snap.v.*"))

        model_iteration = np.zeros(len(hfiles))

        energy = np.zeros(len(hfiles))
        energy_expected = np.zeros(len(hfiles))

        momentum = np.zeros(len(hfiles))
        momentum_expected = np.zeros(len(hfiles))

        volume = np.zeros(len(hfiles))

        for counter, ufile in enumerate(ufiles):

            h = aro.interpret_raw_file(hfiles[counter], nx, ny, layers)
            u = aro.interpret_raw_file(ufile, nx, ny, layers)
            v = aro.interpret_raw_file(vfiles[counter], nx, ny, layers)

            model_iteration[counter] = float(ufile[-10:])

            # plt.figure()
            # plt.pcolormesh(grid.xp1,grid.y,u[:,:,0].transpose())
            # plt.colorbar()
            # plt.savefig('u.{0}.png'.format(ufile[-10:]),dpi=150)
            # plt.close()

            # plt.figure()
            # plt.pcolormesh(grid.x,grid.y,h[:,:,0].transpose())
            # plt.colorbar()
            # plt.savefig('h.{0}.png'.format(ufile[-10:]),dpi=150)
            # plt.close()

            energy[counter] = nx * ny * (dx * dy * rho0 * (np.sum(
                np.absolute(h * (u[:, :, 1:]**2 + u[:, :, :-1]**2) / 4.) /
                2.) + np.sum(
                    np.absolute(h *
                                (v[:, 1:, :]**2 + v[:, :-1, :]**2) / 4.) / 2.))
                                         + dx * dy * rho0 * 0.01 *
                                         np.sum(np.absolute(h - 400.)))

            momentum[counter] = nx * ny * dx * dy * rho0 * (
                np.sum(np.absolute(h * (u[:, :, 1:] + u[:, :, :-1]) / 2.)) +
                np.sum(np.absolute(h * (v[:, 1:, :] + v[:, :-1, :]) / 2.)))

            volume[counter] = np.sum(h)

            # plt.figure()
            # plt.pcolormesh(grid.xp1, grid.y, np.transpose(u[:,:,0]))
            # plt.colorbar()
            # plt.savefig('output/u.{0}.png'.format(model_iteration[counter]),dpi=100)
            # plt.close()

        opt.assert_volume_conservation(nx, ny, layers, 1e-9)

        X, Y = np.meshgrid(grid.xp1, grid.y)
        init_u = aro.interpret_raw_file(ufiles[1], nx, ny,
                                        layers)  #init_U(X, Y, True)

        X, Y = np.meshgrid(grid.x, grid.yp1)
        init_v = aro.interpret_raw_file(vfiles[1], nx, ny,
                                        layers)  #init_V(X, Y, True)

        energy_expected[:] = nx * ny * (dx * dy * rho0 * (np.sum(
            np.absolute(400. *
                        (init_u[:, :, 1:]**2 + init_u[:, :, :-1]**2) / 4.) /
            2.) + np.sum(
                np.absolute(400. *
                            (init_v[:, 1:, :]**2 + init_v[:, :-1, :]**2) / 4.)
                / 2.)))

        momentum_expected[:] = nx * ny * dx * dy * rho0 * (
            np.sum(np.absolute(h *
                               (init_u[:, :, 1:] + init_u[:, :, :-1]) / 2.)) +
            np.sum(np.absolute(h *
                               (init_v[:, 1:, :] + init_v[:, :-1, :]) / 2.)))

        # print momentum[0]/momentum_expected[0]

        #assert np.amax(array_relative_error(ans, good_ans)) < rtol
        plt.figure()
        #plt.plot(model_iteration, energy_expected, '-o', alpha=0.5,
        #        label='Expected energy')
        plt.plot(model_iteration * dt / (86400),
                 energy,
                 '-',
                 alpha=1,
                 label='Simulated energy')
        plt.legend()
        plt.xlabel('Time (days)')
        plt.ylabel('Energy')
        plt.savefig('f_plane_energy_test.png', dpi=150)

        plt.figure()
        plt.plot(model_iteration * dt / (86400), energy / energy_expected)
        plt.xlabel('timestep')
        plt.ylabel('simulated/expected')
        plt.savefig('energy_ratio.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration, volume)
        plt.ylabel('Volume')
        plt.xlabel('timestep')
        plt.savefig('volume.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration * dt / (86400),
                 momentum,
                 '-',
                 alpha=1,
                 label='Simulated momentum')
        plt.legend()
        plt.xlabel('Time (days)')
        plt.ylabel('Momentum')
        plt.savefig('f_plane_momentum_test.png', dpi=150)

        plt.figure()
        plt.plot(model_iteration, momentum / momentum_expected)
        plt.xlabel('timestep')
        plt.ylabel('simulated/expected')
        plt.savefig('momentum_ratio.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration * dt / (86400),
                 100. * (momentum - momentum_expected) / momentum_expected)
        plt.xlabel('Time (days)')
        plt.ylabel('percent error')
        plt.ylim(-20, 80)
        plt.savefig('momentum_percent_error.png')
        plt.close()
Пример #30
0
def f_plane_wind_test(physics, aro_exec, nx, ny, dx, dy, dt, nTimeSteps):

    layers = 1
    grid = aro.Grid(nx, ny, layers, dx, dy)

    rho0 = 1035.

    def wind_x(X, Y, *arg):
        wind_x = np.zeros(Y.shape, dtype=np.float64)
        wind_x[int(grid.nx / 2), int(grid.ny / 2)] = 1e-5

        if not arg:
            plt.figure()
            plt.pcolormesh(X / 1e3, Y / 1e3, wind_x)
            plt.colorbar()
            plt.savefig('wind_x.png')
            plt.close()
        return wind_x

    def wind_y(X, Y, *arg):
        wind_y = np.zeros(X.shape, dtype=np.float64)
        wind_y[int(grid.nx / 2), int(grid.ny / 2)] = 1e-5

        if not arg:
            plt.figure()
            plt.pcolormesh(X / 1e3, Y / 1e3, wind_y)
            plt.colorbar()
            plt.savefig('wind_y.png')
            plt.close()
        return wind_y

    def dbl_periodic_wetmask(X, Y):
        return np.ones(X.shape, dtype=np.float64)

    with opt.working_directory(
            p.join(self_path,
                   "physics_tests/f_plane_{0}_wind".format(physics))):

        sub.check_call(["rm", "-rf", "output/"])
        drv.simulate(initHfile=[400.],
                     zonalWindFile=[wind_x],
                     meridionalWindFile=[wind_y],
                     valgrind=False,
                     nx=nx,
                     ny=ny,
                     exe=aro_exec,
                     dx=dx,
                     dy=dy,
                     wetMaskFile=[dbl_periodic_wetmask],
                     dt=dt,
                     dumpFreq=int(dt * nTimeSteps / 50),
                     nTimeSteps=nTimeSteps)

        hfiles = sorted(glob.glob("output/snap.h.*"))
        ufiles = sorted(glob.glob("output/snap.u.*"))
        vfiles = sorted(glob.glob("output/snap.v.*"))

        # expect the momentum to grow according to u*h*rho0 = delta_t * wind
        # F = m * a
        # m * v = h * rho0 * xlen * ylen * v
        #       = m * a * dt
        #       = F * dt
        #       = wind * dx * dy * dt

        momentum = np.zeros(len(hfiles), dtype=np.float64)
        model_iteration = np.zeros(len(hfiles), dtype=np.float64)

        momentum_expected = np.zeros(len(hfiles), dtype=np.float64)

        volume = np.zeros(len(hfiles))

        for counter, ufile in enumerate(ufiles):

            h = aro.interpret_raw_file(hfiles[counter], nx, ny, layers)
            u = aro.interpret_raw_file(ufile, nx, ny, layers)
            v = aro.interpret_raw_file(vfiles[counter], nx, ny, layers)

            model_iteration[counter] = float(ufile[-10:])

            # plt.figure()
            # plt.pcolormesh(grid.xp1,grid.y,u[:,:,0].transpose())
            # plt.colorbar()
            # plt.savefig('u.{0}.png'.format(ufile[-10:]),dpi=150)
            # plt.close()

            # plt.figure()
            # plt.pcolormesh(grid.x,grid.y,h[:,:,0].transpose())
            # plt.colorbar()
            # plt.savefig('h.{0}.png'.format(ufile[-10:]),dpi=150)
            # plt.close()

            momentum[counter] = dx * dy * rho0 * (
                np.sum(np.absolute(h * (u[:, :, 1:] + u[:, :, :-1]) / 2.)) +
                np.sum(np.absolute(h * (v[:, 1:, :] + v[:, :-1, :]) / 2.)))

            momentum_expected[counter] = 2. * dx * dy * 1e-5 * (
                model_iteration[counter] + 2) * dt

            volume[counter] = np.sum(dx * dy * h)

            # plt.figure()
            # plt.pcolormesh(grid.xp1, grid.y, np.transpose(u[:,:,0]))
            # plt.colorbar()
            # plt.savefig('output/u.{0}.png'.format(model_iteration[counter]),dpi=100)
            # plt.close()

        opt.assert_volume_conservation(nx, ny, layers, 1e-9)

        plt.figure()
        plt.plot(model_iteration * dt / (30 * 86400),
                 momentum_expected,
                 '-',
                 alpha=1,
                 label='Expected momentum')
        plt.plot(model_iteration * dt / (30 * 86400),
                 momentum,
                 '-',
                 alpha=1,
                 label='Simulated momentum')
        plt.legend()
        plt.xlabel('Time (months)')
        plt.ylabel('Momentum')
        plt.savefig('f_plane_momentum_test.png', dpi=150)
        plt.close()

        plt.figure()
        plt.plot(model_iteration, momentum / momentum_expected)
        plt.xlabel('timestep')
        plt.ylabel('simulated/expected')
        plt.title('final ratio = {0}'.format(
            str(momentum[-1] / momentum_expected[-1])))
        plt.savefig('ratio.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration,
                 100. * (momentum - momentum_expected) / momentum_expected)
        plt.xlabel('timestep')
        plt.ylabel('percent error')
        plt.ylim(-4, 4)
        plt.savefig('percent_error.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration, momentum - momentum_expected)
        plt.xlabel('timestep')
        plt.ylabel('simulated - expected')
        plt.savefig('difference.png')
        plt.close()

        plt.figure()
        plt.plot(model_iteration, volume)
        plt.ylabel('Volume')
        plt.xlabel('timestep')
        plt.ylim(np.min(volume), np.max(volume))
        plt.savefig('volume.png')
        plt.close()

        percent_error = 100. * (momentum -
                                momentum_expected) / momentum_expected

        return percent_error[-1]