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_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 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 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 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 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_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_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_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_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_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_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 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 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(): 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_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_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 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)
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)
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 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)
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)
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)
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()
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]