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)
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)
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)
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)
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')
def benchmark_gaussian_bump_red_grav_plot(): with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): with open("times.pkl", "r") as f: (grid_points, run_time_O1, run_time_Ofast) = pkl.load(f) plt.figure() plt.loglog(grid_points, run_time_O1 * scale_factor, '-*', label='aronnax_test') plt.loglog(grid_points, run_time_Ofast * scale_factor, '-*', label='aronnax_core') scale = scale_factor * run_time_O1[-7] / (grid_points[-7]**2) plt.loglog(grid_points, scale * grid_points**2, ':', label='O(nx**2)', color='black', linewidth=0.5) plt.legend() plt.xlabel('Resolution (grid cells on one side)') plt.ylabel('Avg time per integration step (ms)') plt.title( 'Runtime scaling of a 1.5-layer Aronnax simulation on a square grid' ) plt.savefig('beta_plane_bump_red_grav_scaling.png', dpi=150)
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)
def benchmark_parallel_gaussian_bump_plot(): with working_directory(p.join(self_path, "beta_plane_bump")): with open("mpi_times.pkl", "rb") as f: (n_procs, run_time) = pkl.load(f) plt.figure() plt.loglog(n_procs, run_time * scale_factor, '-*', label='aronnax_external_solver') scale = scale_factor * run_time[0] plt.loglog(n_procs, scale / n_procs, ':', label='O(1/n)', color='black', linewidth=0.5) plt.legend() plt.xlabel('Number of processors') plt.ylabel('Avg time per integration step (ms)') plt.title( 'Runtime scaling of a 2-layer Aronnax simulation\n on a square grid' ) plt.savefig('beta_plane_bump_mpi_scaling.png', dpi=150, bbox_inches='tight')
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)])
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')
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
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)
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)
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)
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)
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)
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)
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)
def test_open_mfdataarray_multiple_variables(): '''This test tries to open multiple different variables in the same call, and should fail.''' xlen = 1e6 ylen = 2e6 nx = 10 ny = 20 layers = 1 grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny) with working_directory(p.join(self_path, "beta_plane_gyre_red_grav")): with pytest.raises(Exception): output_files = glob.glob('output/snap.*') ds = aro.open_mfdataarray(output_files, grid)
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)
def benchmark_gaussian_bump_plot(): with working_directory(p.join(self_path, "beta_plane_bump")): with open("times.pkl", "rb") as f: (grid_points, run_time_O1, run_time_Ofast, run_time_hypre_test, run_time_hypre) = pkl.load(f) plt.figure() plt.loglog(grid_points, run_time_O1 * scale_factor, '-*', label='aronnax_test') plt.loglog(grid_points, run_time_Ofast * scale_factor, '-*', label='aronnax_core') plt.loglog(grid_points, run_time_hypre_test * scale_factor, '-o', label='aronnax_external_solver_test') plt.loglog(grid_points, run_time_hypre * scale_factor, '-o', label='aronnax_external_solver') scale = scale_factor * run_time_O1[3] / (grid_points[3]**3) plt.loglog(grid_points, scale * grid_points**3, ':', label='O(nx**3)', color='black', linewidth=0.5) scale = scale_factor * run_time_hypre[3] / (grid_points[3]**2) plt.loglog(grid_points, scale * grid_points**2, ':', label='O(nx**2)', color='blue', linewidth=0.5) plt.legend() plt.xlabel('Resolution (grid cells on one side)') plt.ylabel('Avg time per integration step (ms)') plt.title( 'Runtime scaling of a 2-layer Aronnax simulation\nwith bathymetry on a square grid' ) plt.savefig('beta_plane_bump_scaling.png', dpi=150)
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
def test_open_mfdataarray_h_location(): '''Open a number of files and assert that the length of the iter dimension is the same as the number of files, and that the correct x and y variables have been used.''' xlen = 1e6 ylen = 2e6 nx = 10 ny = 20 layers = 1 grid = aro.Grid(nx, ny, layers, xlen / nx, ylen / ny) with working_directory(p.join(self_path, "beta_plane_gyre_red_grav")): output_files = glob.glob('output/snap.h*') ds = aro.open_mfdataarray(output_files, grid) assert len(output_files) == ds.iter.shape[0] assert nx == ds.x.shape[0] assert ny == ds.y.shape[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)
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)
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)
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)
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
def compile_core(config): """Compile the Aronnax core, if needed.""" core_name = config.get("executable", "exe") with working_directory(root_path): sub.check_call(["make", core_name])
def simulate(work_dir=".", config_path="aronnax.conf", **options): """Main entry point for running an Aronnax simulation. A simulation occurs in the working directory given by the `work_dir` parameter, which defaults to the current directory when `simulate` is invoked. The default arrangement of the working directory is as follows: - aronnax.conf - configuration file for that run - aronnax-merged.conf - file to save effective configuration, including effects of options passed to `simulate`. This file is automatically generated by merging the aronnax.conf file with the options passed to this function - parameters.in - relevant portions of aronnax-merged.conf in Fortran namelist format. Also generated automatically - input/ - subdirectory where Aronnax will save input field files in Fortran raw array format - output/ - subdirectory where Aronnax will save output field files in Fortran raw array format The process for a simulation is to 1. Compute the configuration 2. Recompile the Fortran core if necessary 3. Save the computed configuration in aronnax-merged.conf 4. Write raw-format input fields into input/ 5. Write parameters.in 6. Execute the Fortran core, which writes progress messages to standard output and raw-format output fields into output/ All the simulation parameters can be controlled from the configuration file aronnax.conf, and additionally can be overridden by passing them as optional arguments to `simulate`. Calling `simulate` directly provides one capability that cannot be accessed from the configuration file: custom idealized input generators. """ config_file = p.join(work_dir, config_path) config = default_configuration() config.read(config_file) merge_config(config, options) with working_directory(work_dir): compile_core(config) # XXX Try to avoid overwriting the input configuration with open('aronnax-merged.conf', 'w') as f: config.write(f) # sub.check_call(["rm", "-rf", "output/"]) sub.check_call(["mkdir", "-p", "output/"]) sub.check_call(["mkdir", "-p", "checkpoints/"]) with working_directory("input"): generate_input_data_files(config) generate_parameters_file(config) then = time.time() run_executable(config) core_run_time = time.time() - then sub.check_call(["rm", "-rf", "netcdf-output/"]) sub.check_call(["mkdir", "-p", "netcdf-output/"]) convert_output_to_netcdf(config) return core_run_time