def test_buffer_length_stranding(self): o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=1, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='i', projection='merc') o1.add_reader([basemap]) o1.fallback_values['x_sea_water_velocity'] = 1.0 # onshore drift o1.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o1.run(steps=100, time_step=900, time_step_output=3600, export_buffer_length=10) # Without buffer o2 = OceanDrift(loglevel=20) o2.add_reader([basemap]) o2.fallback_values['x_sea_water_velocity'] = 1.0 # onshore drift o2.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o2.run(steps=100, time_step=900, time_step_output=3600, outfile='test_buffer_length_stranding.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) self.assertItemsEqual(o1.history['status'].compressed(), o2.history['status'].compressed()) os.remove('test_buffer_length_stranding.nc')
def test_reader_boundary(self): # Check that the element outside reader coverage is # not deactivated if fallback value exist o = OceanDrift() nordic3d = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') lon = [12.0, 12.0] lat = [70.0, 70.5] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 2) self.assertEqual(o.num_elements_deactivated(), 0) # Check that the outside element is deactivated, # if no fallback value exists o = OceanDrift() del o.fallback_values['x_sea_water_velocity'] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1)
def test_stranding_options(self): reader_osc = reader_oscillating.Reader( 'x_sea_water_velocity', amplitude=1, zero_time=datetime.now()) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=12, llcrnrlat=67.6, urcrnrlon=13.6, urcrnrlat=68.1, resolution='i', projection='merc') # Three different stranding options, with # expected final status and position options = ['stranding', 'previous', 'none'] status = ['stranded', 'active', 'active'] lons = [12.930, 13.348, 12.444] for i, option in enumerate(options): o = OceanDrift(loglevel=30) o.set_config('general:coastline_action', option) o.add_reader([reader_osc, reader_basemap]) # Adding northwards drift o.fallback_values['y_sea_water_velocity'] = .2 o.seed_elements(lon=12.2, lat=67.7, radius=0, time=reader_osc.zero_time) o.run(steps=28, time_step=3600*2) print 'Testing stranding: %s' % option if len(o.elements) == 1: el = o.elements else: el = o.elements_deactivated self.assertEqual(o.status_categories[int(el.status)], status[i]) self.assertAlmostEqual(el.lon, lons[i], 2)
def test_output_time_step(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4.5, llcrnrlat=60.0, urcrnrlon=5.2, urcrnrlat=60.5, resolution='i', projection='merc') o1.add_reader([basemap, norkyst]) o1.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=30) o2.add_reader([basemap, norkyst]) o2.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100,25)) self.assertEqual(o2.history.shape, (100,13)) # Check that start and end conditions (longitudes) are idential self.assertItemsEqual(o1.history['lon'][:,24].compressed(), o2.history['lon'][:,12].compressed()) self.assertItemsEqual(o1.history['lon'][:,0].compressed(), o2.history['lon'][:,0].compressed()) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertItemsEqual(o2i.history['lon'][:,12].compressed(), o2.history['lon'][:,12].compressed()) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated())
def test_adding_readers(self): o = OceanDrift() r = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') o.add_reader([r, basemap]) self.assertEqual(o.priority_list['land_binary_mask'], ['roms native', 'basemap_landmask']) self.assertEqual(o.priority_list['x_sea_water_velocity'], ['roms native']) # Switch order o = OceanDrift() o.add_reader([basemap, r]) self.assertEqual(o.priority_list['land_binary_mask'], ['basemap_landmask', 'roms native']) self.assertEqual(o.priority_list['x_sea_water_velocity'], ['roms native'])
def test_reader_order(self): # Check that we get the same output indepenently of reader order o = OceanDrift(loglevel=50) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') arome = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=2, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='c', projection='merc') lon=4.; lat=60. # First run o.add_reader([basemap, norkyst, arome]) o.seed_elements(lon, lat, time=norkyst.start_time) o.run(steps=30) # Second run # Check that we get almost identical results with other projection o1 = OceanDrift(loglevel=50) o1.add_reader([norkyst, arome, basemap]) o1.seed_elements(lon, lat, time=norkyst.start_time) o1.run(steps=30) self.assertAlmostEqual(o.elements.lon, o1.elements.lon, 2) self.assertAlmostEqual(o.elements.lat, o1.elements.lat, 2) # Third run # Check that this is identical to run 1 if projection set equal o2 = OceanDrift(loglevel=50) o2.add_reader([norkyst, arome, basemap]) o2.seed_elements(lon, lat, time=norkyst.start_time) o2.set_projection(basemap.proj4) o2.run(steps=30) self.assertEqual(o.elements.lon, o2.elements.lon)
def test_export_step_interval(self): # Export to file only at end o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o1.add_reader(norkyst) o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o1.run(steps=40) # Export to file during simulation o2 = OceanDrift(loglevel=20) o2.add_reader(norkyst) o2.fallback_values['land_binary_mask'] = 0 o2.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o2.run(steps=40, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) # Finally check when steps is multiple of export_buffer_length o3 = OceanDrift(loglevel=20) o3.add_reader(norkyst) o3.fallback_values['land_binary_mask'] = 0 o3.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o3.run(steps=42) # Export to file during simulation o4 = OceanDrift(loglevel=20) o4.add_reader(norkyst) o4.fallback_values['land_binary_mask'] = 0 o4.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o4.run(steps=42, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o3.history['lon'].compressed(), o4.history['lon'].compressed()) os.remove('export_step_interval.nc')
from datetime import datetime from opendrift.readers import reader_basemap_landmask from opendrift.readers import reader_ArtificialOceanEddy from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=-1.5, llcrnrlat=59, urcrnrlon=7, urcrnrlat=64, resolution='h') o.add_reader([fake_eddy, reader_basemap]) lon = 2.0; lat = 63.0; # Close to Station M # First run, with Euler scheme: o.set_config('drift:scheme', 'euler') o.seed_elements(lon, lat, radius=0, number=1, time=datetime(2015,1,1)) o.run(steps=300, time_step=3600) # Second run, with Runge-Kutta scheme: o2 = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information o2.add_reader([fake_eddy, reader_basemap]) o2.set_config('drift:scheme', 'runge-kutta') o2.seed_elements(lon, lat, radius=0, number=1, time=datetime(2015,1,1)) o2.run(steps=300, time_step=3600) o.plot(compare=o2, legend=['Euler scheme', 'Runge-Kutta scheme'])
Grid ============= """ import numpy as np from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information # Norkyst reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o.add_reader(reader_norkyst) #o.fallback_values['land_binary_mask'] = 0 #%% # Seeding some particles lons = np.linspace(3.5, 5.0, 100) lats = np.linspace(60, 61, 100) lons, lats = np.meshgrid(lons, lats) lons = lons.ravel() lats = lats.ravel() #%% # Seed oil elements at defined position and time o.seed_elements(lons, lats, radius=0,
""" import numpy as np from opendrift.readers import reader_global_landmask from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information # Norkyst #reader_norkyst = reader_netCDF_CF_generic.Reader('https://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o.add_reader([reader_norkyst]) o.set_config('drift:vertical_mixing', False) #%% # Seeding particles in a checkerboard pattern di = 5 # Horizontal number of particles per square dj = 5 # Vertical number of particles per square lons = np.linspace(3.5, 5.0, 100) lats = np.linspace(60, 61, 100) ii = np.arange(len(lons)) // di jj = np.arange(len(lats)) // dj ii, jj = np.meshgrid(ii, jj) board = (ii + jj) % 2 > 0 lons, lats = np.meshgrid(lons, lats)
class TestRun(unittest.TestCase): """Tests for (non-scalar) LagrangianArray""" def make_OceanDrift_object(self): self.o = OceanDrift(loglevel=30) self.fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) self.reader_landmask = reader_global_landmask.Reader( extent=[-1.5, 59, 7, 64]) self.o.add_reader([self.fake_eddy, self.reader_landmask]) def test_seed(self): """Test seeding""" o = OceanDrift(loglevel=20) number = 3 lonvec = np.linspace(2, 5, number) latvec = np.linspace(60, 61, number) o.seed_elements(lonvec, latvec, number=number, time=datetime(2015, 1, 1, 12, 5, 17)) #time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.num_elements_active(), 0) self.assertEqual(o.num_elements_activated(), 0) self.assertEqual(o.num_elements_deactivated(), 0) self.assertEqual(o.num_elements_total(), number) def test_seed_cone(self): o = OceanDrift(loglevel=20) o.seed_cone(time=[datetime.now(), datetime.now() + timedelta(hours=3)], number=100, lat=[60.5, 60.6], lon=[4.4, 4.5]) self.assertAlmostEqual(o.elements_scheduled.lon[50], 4.450, 2) def test_seed_outside_coverage(self): """Test seeding""" o = OpenOil(loglevel=0) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') landmask = reader_global_landmask.Reader(extent=[4, 6, 60, 64]) o.add_reader([landmask, norkyst]) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) o.set_config('seed:oil_type', 'SNORRE B 2004') o.seed_elements(5, 63, number=5, time=norkyst.start_time - 24 * timedelta(hours=24)) # Check that the oiltype is taken from config self.assertEqual(o.oil_name, o.get_config('seed:oil_type')) self.assertEqual(o.oil_name, 'SNORRE B 2004') with self.assertRaises(ValueError): o.run(steps=3, time_step=timedelta(minutes=15)) def test_invalid_config(self): o = OceanDrift(loglevel=20) with self.assertRaises(ValueError): # outside min-max o.set_config('seed:number', 0) with self.assertRaises(ValueError): # not in list/enum o.set_config('vertical_mixing:diffusivitymodel', 'not_in_list') o.set_config('seed:number', 100) self.assertEqual(o.get_config('seed:number'), 100) def test_config_suggestion(self): o = Leeway(loglevel=20) try: o.set_config('seed:object_type', 'person') except Exception as e: self.assertTrue('Did you mean' in str(e)) def test_config_seed(self): #o = Leeway(loglevel=20) o = OceanDrift(loglevel=20) o.list_configspec() def test_config_constant_fallback(self): o = OceanDrift(loglevel=0) reader_arome = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') print(reader_norkyst, reader_arome) o.add_reader([reader_norkyst, reader_arome]) o.seed_elements(lon=4, lat=60, time=reader_arome.end_time - timedelta(hours=3), number=1) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_sea_water_velocity', 1) o.set_config('environment:fallback:y_sea_water_velocity', 0) o.set_config('environment:constant:x_wind', 0) o.set_config('environment:constant:y_wind', 5) o.run(duration=timedelta(hours=6)) y_wind = np.array(o.get_property('y_wind')[0][:, 0]) x_current = np.array(o.get_property('x_sea_water_velocity')[0][:, 0]) # Check that constant wind is used for whole simulation self.assertAlmostEqual(y_wind[0], 5, 2) self.assertAlmostEqual(y_wind[-1], 5, 2) # Check that fallback current is used only after end of reader self.assertAlmostEqual(x_current[0], 0.155, 2) self.assertAlmostEqual(x_current[-1], 1, 2) def test_runge_kutta(self): number = 50 # With Euler o = OceanDrift(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.set_config('environment:fallback:land_binary_mask', 0) o.add_reader([norkyst]) z = -40 * np.random.rand(number) o.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o.run(steps=4 * 3, time_step=timedelta(minutes=15)) # With Runge-Kutta o2 = OceanDrift(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o2.set_config('environment:fallback:land_binary_mask', 0) o2.add_reader([norkyst]) z = -40 * np.random.rand(number) o2.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o2.set_config('drift:advection_scheme', 'runge-kutta') o2.run(steps=4 * 3, time_step=timedelta(minutes=15)) # And finally repeating the initial run to check that indetical o3 = OceanDrift(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o3.set_config('environment:fallback:land_binary_mask', 0) o3.add_reader([norkyst]) z = -40 * np.random.rand(number) o3.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o3.run(steps=4 * 3, time_step=timedelta(minutes=15)) # Check that we get some difference with Runge-Kutta: self.assertIsNone( np.testing.assert_array_almost_equal( (o2.elements.lon - o.elements.lon).max(), 0.0015, 3)) #(o2.elements.lon-o.elements.lon).max(), 0.013, 3)) # Check that runs with Euler are identical self.assertIsNone( np.testing.assert_array_almost_equal( (o3.elements.lon - o.elements.lon).max(), 0)) def test_seed_polygon(self): o = OpenOil(loglevel=0) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time = datetime(2015, 1, 1, 12, 5, 17) o.set_config('seed:oil_type', 'HEIDRUN') o.seed_within_polygon(lonvec, latvec, number=number, time=time, wind_drift_factor=.09) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time) self.assertAlmostEqual(o.elements_scheduled.wind_drift_factor, .09) # Check that oil type is taken fom config self.assertEqual(o.oil_name, 'HEIDRUN') def test_seed_polygon_timespan(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time = [ datetime(2015, 1, 1, 12, 5, 17), datetime(2015, 1, 1, 18, 5, 17) ] o.seed_within_polygon(lonvec, latvec, number=number, time=time) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time[0]) self.assertEqual(o.elements_scheduled_time[-1], time[-1]) @unittest.skipIf(has_ogr is False, 'OGR library needed to parse WKT') def test_seed_wkt(self): wkt = 'MULTIPOLYGON(((7.784889 64.353442,7.777561 64.353842,7.774236 64.354707,7.770215 64.355829,7.774269 64.356015,7.776829 64.356863,7.779107 64.3578,7.782827 64.358355,7.786346 64.359615,7.787109 64.361975,7.790125 64.361132,7.794584 64.359908,7.798455 64.359624,7.797258 64.358193,7.79978 64.356904,7.795957 64.356494,7.792955 64.355335,7.789134 64.355339,7.784889 64.353442)))' o = OceanDrift(loglevel=20) o.set_config('seed:number', 100) o.seed_from_wkt(wkt, time=datetime.now()) wkt_multi = 'MULTIPOLYGON(((2.458058 59.178919,2.456276 59.179283,2.454867 59.180692,2.45277 59.182852,2.452521 59.183759,2.452675 59.184726,2.451365 59.18534,2.451436 59.186609,2.450835 59.188138,2.449576 59.189435,2.447393 59.190818,2.447211 59.191915,2.446273 59.193573,2.445551 59.19423,2.446597 59.195015,2.44838 59.194651,2.450277 59.193,2.452377 59.191919,2.453315 59.19026,2.45457 59.187885,2.455473 59.186131,2.457033 59.18461,2.458774 59.181992,2.458971 59.180403,2.459775 59.179444,2.459606 59.178969,2.458058 59.178919)),((2.442682 59.197444,2.440531 59.198922,2.439575 59.199994,2.440874 59.200951,2.439596 59.20166,2.436232 59.202958,2.433255 59.203728,2.42982 59.203756,2.428 59.202946,2.425857 59.200693,2.42454 59.199149,2.422418 59.198563,2.419404 59.198158,2.417332 59.197175,2.41514 59.19532,2.412395 59.194596,2.410072 59.194519,2.409481 59.193397,2.408199 59.191947,2.405959 59.190489,2.403129 59.188988,2.401292 59.18759,2.398331 59.187867,2.395639 59.187825,2.393585 59.187428,2.389665 59.187697,2.38736 59.188208,2.386923 59.189132,2.390625 59.188785,2.392191 59.189424,2.395825 59.188887,2.398602 59.188627,2.402104 59.189869,2.403773 59.191871,2.407276 59.193113,2.407648 59.194158,2.407751 59.195522,2.410008 59.196488,2.411979 59.197187,2.41439 59.19912,2.415839 59.199965,2.417946 59.201043,2.417796 59.202235,2.414886 59.203195,2.411923 59.203473,2.40923 59.203431,2.409753 59.204363,2.412549 59.20469,2.415342 59.203937,2.41891 59.20321,2.420325 59.203961,2.420463 59.20542,2.419357 59.207683,2.4218 59.208631,2.420303 59.209262,2.418925 59.210766,2.421401 59.21073,2.424984 59.20951,2.425201 59.208508,2.425939 59.207359,2.428832 59.205812,2.431004 59.206001,2.433124 59.205507,2.436926 59.204365,2.439568 59.203724,2.441518 59.202755,2.442879 59.201744,2.443246 59.20063,2.443311 59.199741,2.444589 59.199032,2.445428 59.198168,2.445088 59.197218,2.442682 59.197444)))' o.seed_from_wkt(wkt_multi, time=datetime.now(), number=200) self.assertEqual(len(o.elements_scheduled), 300) self.assertAlmostEqual(o.elements_scheduled.lat.max(), 64.36, 2) self.assertAlmostEqual(o.elements_scheduled.lat.min(), 59.18, 2) @unittest.skipIf(has_ogr is False, 'OGR library needed to read shapefiles') def test_seed_shapefile(self): o = OceanDrift(loglevel=20) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=100, layername=None, featurenum=[2, 4], time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 100) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=300, layername=None, featurenum=None, time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 400) self.assertAlmostEqual(o.elements_scheduled.lat[-1], 52.5, 2) #@unittest.skipIf(has_ogr is False, # 'GDAL library needed to read shapefiles') #def test_write_geotiff(self): # o = OceanDrift(loglevel=20) # o.seed_elements(lon=4, lat=60, time=datetime(2016, 1, 1)) # o.run(steps=3) # o.write_geotiff('geotiff.tif') def test_seed_single_point_over_time(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements(2.0, 61.0, radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30) # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 5) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) def test_temporal_seed(self): self.o = OceanDrift(loglevel=20) self.o.set_config('environment:fallback:x_sea_water_velocity', 1) self.o.set_config('environment:fallback:land_binary_mask', 0) # Seed elements on a grid at regular time interval start_time = datetime(2016, 9, 16) time_step = timedelta(hours=6) num_steps = 10 lon = 4.4 lat = 60.0 for i in range(num_steps + 1): self.o.seed_elements(lon, lat, radius=0, number=2, time=start_time + i * time_step) # Running model self.o.run(steps=20, time_step=3600, outfile='temporal_seed.nc') self.o = OceanDrift(loglevel=20) # Check that data imported is properly masked self.o.io_import_file('temporal_seed.nc') self.assertTrue(self.o.history['lon'].max() < 1000) self.assertTrue(self.o.history['lon'].min() > -1000) self.assertTrue(self.o.history['lon'].mask[5, 5]) self.assertFalse(self.o.history['lon'].mask[1, 1]) os.remove('temporal_seed.nc') def test_vertical_mixing(self): # Export to file only at end o1 = PelagicEggDrift(loglevel=20) # Profiles and vertical mixing norkyst = reader_netCDF_CF_generic.Reader( o1.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o1.add_reader([norkyst]) o1.set_config('environment:fallback:x_wind', 8) o1.set_config('environment:fallback:land_binary_mask', 0) o1.seed_elements(4.1, 63.3, radius=1000, number=100, time=norkyst.start_time) o1.set_config('vertical_mixing:timestep', 20.) # seconds o1.run(steps=20, time_step=300, time_step_output=1800, export_buffer_length=10, outfile='verticalmixing.nc') self.assertAlmostEqual(o1.history['z'].min(), -44.4, 1) self.assertAlmostEqual(o1.history['z'].max(), 0.0, 1) os.remove('verticalmixing.nc') def test_vertical_mixing_profiles(self): # Testing an isolated mixing timestep cases = [ # Some cases with expected outcome { 'vt': 0, 'K': 0, 'K_below': .01, 'T': 60, # No mixing 'zmin': -10, 'zmax': -10, 'zmean': -10 }, { 'vt': -.005, 'K': 0, 'K_below': .01, 'T': 60, # Sinking #'zmin': -74.0, 'zmax': -21.4, 'zmean': -50.2}, # With old seed_elements 'zmin': -74.79, 'zmax': -21.6, 'zmean': -49.97 }, { 'vt': 0, 'K': .01, 'K_below': .01, 'T': 60, # Mixing #'zmin': -39.8, 'zmax': -0.1, 'zmean': -14.5}, 'zmin': -42.76, 'zmax': -0.02, 'zmean': -14.38 }, { 'vt': .005, 'K': .01, 'K_below': .01, 'T': 60, # Mixing and rising #'zmin': -8.1, 'zmax': -0.01, 'zmean': -2.1}, 'zmin': -7.86, 'zmax': -0.01, 'zmean': -2.1 }, { 'vt': -0.005, 'K': .01, 'K_below': .01, 'T': 60, # Mixing and sinking #'zmin': -75.8, 'zmax': -20.7, 'zmean': -48.1}, 'zmin': -78.76, 'zmax': -19.74, 'zmean': -48.0 }, { 'vt': 0, 'K': .02, 'K_below': .001, 'T': 60, # Mixing in mixed layer #'zmin': -22.8, 'zmax': -0.1, 'zmean': -9.8}, 'zmin': -21.3, 'zmax': -0.1, 'zmean': -9.55 }, ] N = 100 z = np.arange(0, -30, -2) time = datetime.now() for case in cases: diffusivity = np.ones(z.shape) * case['K'] diffusivity[z < -15] = case['K_below'] o = OceanDrift(loglevel=20) o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:diffusivitymodel', 'environment') o.set_config('vertical_mixing:timestep', case['T']) o.seed_elements(lon=4, lat=60, z=-10, time=time, number=N, terminal_velocity=case['vt']) o.time = time o.time_step = timedelta(hours=2) o.release_elements() o.set_config('environment:fallback:land_binary_mask', 0) o.environment = np.array(np.ones(N) * 100, dtype=[('sea_floor_depth_below_sea_level', np.float32)]).view(np.recarray) o.environment_profiles = { 'z': z, 'ocean_vertical_diffusivity': np.tile(diffusivity, (N, 1)).T } o.set_fallback_values() o.vertical_mixing() self.assertAlmostEqual(o.elements.z.min(), case['zmin'], 1) self.assertAlmostEqual(o.elements.z.max(), case['zmax'], 1) self.assertAlmostEqual(o.elements.z.mean(), case['zmean'], 1) def test_export_step_interval(self): # Export to file only at end o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader( o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o1.add_reader(norkyst) o1.set_config('environment:fallback:land_binary_mask', 0) o1.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o1.run(steps=40) # Export to file during simulation o2 = OceanDrift(loglevel=20) o2.add_reader(norkyst) o2.set_config('environment:fallback:land_binary_mask', 0) o2.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o2.run(steps=40, export_buffer_length=6, outfile='export_step_interval.nc') self.assertIsNone( np.testing.assert_array_equal(o1.history['lon'].compressed(), o2.history['lon'].compressed())) # Finally check when steps is multiple of export_buffer_length o3 = OceanDrift(loglevel=20) o3.add_reader(norkyst) o3.set_config('environment:fallback:land_binary_mask', 0) o3.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o3.run(steps=42) # Export to file during simulation o4 = OceanDrift(loglevel=20) o4.add_reader(norkyst) o4.set_config('environment:fallback:land_binary_mask', 0) o4.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o4.run(steps=42, export_buffer_length=6, outfile='export_step_interval.nc') self.assertIsNone( np.testing.assert_array_equal(o3.history['lon'].compressed(), o4.history['lon'].compressed())) os.remove('export_step_interval.nc') def test_export_final_timestep(self): o = OceanDrift() o.set_config('environment:constant:land_binary_mask', 0) o.set_config('general:use_auto_landmask', False) o.seed_elements(lon=0, lat=0, radius=500, number=100, time=[datetime(2010, 1, 1), datetime(2010, 1, 3)]) o.run(duration=timedelta(hours=20), time_step=3600, time_step_output=3600 * 3) index_of_first, index_of_last = \ o.index_of_activation_and_deactivation() assert o.num_elements_active() == len(index_of_first) def test_buffer_length_stranding(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader( o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader(extent=[4.5, 6.0, 60.1, 60.4]) o1.add_reader([landmask]) o1.set_config('environment:fallback:x_sea_water_velocity', 0.8) # onshore drift o1.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o1.run(steps=100, time_step=900, time_step_output=3600, export_buffer_length=10) # Without buffer o2 = OceanDrift(loglevel=30) o2.add_reader([landmask]) o2.set_config('environment:fallback:x_sea_water_velocity', 0.8) # onshore drift o2.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o2.run(steps=100, time_step=900, time_step_output=3600, outfile='test_buffer_length_stranding.nc') self.assertIsNone( np.testing.assert_array_equal(o1.history['lon'].compressed(), o2.history['lon'].compressed())) self.assertIsNone( np.testing.assert_array_almost_equal( o1.history['status'].compressed(), o2.history['status'].compressed())) os.remove('test_buffer_length_stranding.nc') def test_output_time_step(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader( o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader(extent=[4.5, 5.2, 60.0, 60.5]) o1.add_reader([landmask, norkyst]) o1.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=30) o2.add_reader([landmask, norkyst]) o2.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100, 25)) self.assertEqual(o2.history.shape, (100, 13)) # Check that start and end conditions (longitudes) are idential self.assertIsNone( np.testing.assert_array_equal( o1.history['lon'][:, 24].compressed(), o2.history['lon'][:, 12].compressed())) self.assertIsNone( np.testing.assert_array_equal(o1.history['lon'][:, 0].compressed(), o2.history['lon'][:, 0].compressed())) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertIsNone( np.testing.assert_array_equal( o2i.history['lon'][:, 12].compressed(), o2.history['lon'][:, 12].compressed())) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated()) def test_time_step_config(self): # Default o = OceanDrift(loglevel=50) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 3600) self.assertEqual(o.time_step_output.total_seconds(), 3600) # Setting time_step o = OceanDrift(loglevel=50) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2, time_step=1800) self.assertEqual(o.time_step.total_seconds(), 1800) # Setting time_step and time_step_output o = OceanDrift(loglevel=50) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2, time_step=1800, time_step_output=3600) self.assertEqual(o.time_step.total_seconds(), 1800) self.assertEqual(o.time_step_output.total_seconds(), 3600) # time_step from config o = OceanDrift(loglevel=50) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=4, lat=60, time=datetime.now()) o.set_config('general:time_step_minutes', 15) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 900) self.assertEqual(o.time_step_output.total_seconds(), 900) # time_step and time_step_output from config o = OceanDrift(loglevel=50) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=4, lat=60, time=datetime.now()) o.set_config('general:time_step_minutes', 15) o.set_config('general:time_step_output_minutes', 120) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 900) self.assertEqual(o.time_step_output.total_seconds(), 7200) def test_reader_boundary(self): # Check that the element outside reader coverage is # not deactivated if fallback value exist o = OceanDrift() nordic3d = reader_ROMS_native.Reader( o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc' ) lon = [12.0, 12.0] lat = [70.0, 70.5] o.add_reader(nordic3d) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 2) self.assertEqual(o.num_elements_deactivated(), 0) # Check that the outside element is deactivated, # if no fallback value exists o = OceanDrift() o.set_config('environment:fallback:x_sea_water_velocity', None) o.add_reader(nordic3d) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) def test_seed_seafloor(self): o = OpenOil(loglevel=50) reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') # Adding reader as lazy, to test seafloor seeding o.add_readers_from_list([ o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc' ]) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) #o.set_config('environment:fallback:x_sea_water_velocity', 0) #o.set_config('environment:fallback:y_sea_water_velocity', 0) lon = 4.5 lat = 62.0 o.set_config('seed:droplet_diameter_min_subsea', 0.0010) # s o.set_config('seed:droplet_diameter_max_subsea', 0.0010) # s o.seed_elements(lon, lat, z='seafloor', time=reader_norkyst.start_time, density=1000, oiltype='GENERIC BUNKER C') o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0, 0], -147.3, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1, 0], -122.52, 1) # After some rising def test_seed_above_seafloor(self): o = OpenOil(loglevel=30) reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) o.set_config('environment:fallback:x_sea_water_velocity', 0) o.set_config('environment:fallback:y_sea_water_velocity', 0) o.add_reader([reader_norkyst]) lon = 4.5 lat = 62.0 o.set_config('seed:droplet_diameter_min_subsea', 0.0010) # s o.set_config('seed:droplet_diameter_max_subsea', 0.0010) # s # Seed elements 50 meters above seafloor: o.seed_elements(lon, lat, z='seafloor+50', time=reader_norkyst.start_time, density=1000, oil_type='AASGARD A 2003') o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0, 0], -97.3, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1, 0], -72.0, 1) # After some rising def test_seed_below_reader_coverage(self): o = OpenOil(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) o.add_reader([reader_norkyst]) lon = 5.0 lat = 64.0 o.set_config('seed:droplet_diameter_min_subsea', 0.0005) o.set_config('seed:droplet_diameter_max_subsea', 0.005) o.seed_elements(lon, lat, z=-350, time=reader_norkyst.start_time, density=1000, oil_type='AASGARD A 2003') #o.set_config('vertical_mixing:TSprofiles', True) o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[-1, 0], -134.0, 1) # After some rising def test_seed_below_seafloor(self): o = OpenOil(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) o.set_config('environment:fallback:x_sea_water_velocity', 0) o.set_config('environment:fallback:y_sea_water_velocity', 0) lon = 4.5 lat = 62.0 o.set_config('seed:droplet_diameter_min_subsea', 0.0005) o.set_config('seed:droplet_diameter_max_subsea', 0.001) o.seed_elements(lon, lat, z=-5000, time=reader_norkyst.start_time, density=1000, oil_type='GENERIC BUNKER C') o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[0, 0], -147.3, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1, 0], -132.45, 1) # After some rising def test_seed_below_seafloor_deactivating(self): o = OpenOil(loglevel=50) reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:x_wind', 0) o.set_config('environment:fallback:y_wind', 0) o.set_config('environment:fallback:x_sea_water_velocity', 0) o.set_config('environment:fallback:y_sea_water_velocity', 0) lon = 4.5 lat = 62.0 o.set_config('seed:droplet_diameter_min_subsea', 0.0005) o.set_config('seed:droplet_diameter_max_subsea', 0.001) o.seed_elements(lon, lat, z=[-5000, -100], time=reader_norkyst.start_time, density=1000, number=2, oil_type='AASGARD A 2003') o.set_config('general:seafloor_action', 'deactivate') # This time we deactivate o.set_config('drift:vertical_mixing', True) o.set_config('vertical_mixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertEqual(o.num_elements_total(), 2) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) self.assertAlmostEqual(z[0, 1], -100, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1, 1], -81.4, 1) # After some rising def test_lift_above_seafloor(self): # See an element at some depth, and progapate towards coast # (shallower water) and check that it is not penetrating seafloor o = OceanDrift(loglevel=50) o.max_speed = 100 reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') reader_norkyst.buffer = 200 o.add_reader([reader_norkyst], variables='sea_floor_depth_below_sea_level') o.set_config('environment:fallback:x_sea_water_velocity', 10) # Pure eastward motion o.set_config('environment:fallback:y_sea_water_velocity', 0) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(3.9, 62.0, z=-200, time=reader_norkyst.start_time) o.set_config('drift:vertical_mixing', False) o.run(steps=12, time_step=300) seafloor_depth, status = o.get_property( 'sea_floor_depth_below_sea_level') z, status = o.get_property('z') # Uncomment to plot #import matplotlib.pyplot as plt #plt.plot(-seafloor_depth, label='Seafloor depth') #plt.plot(z, label='Element depth') #plt.legend(loc='best') #plt.show() # Check that element has not penetrated seafloor self.assertFalse( o.elements.z < -o.environment.sea_floor_depth_below_sea_level) self.assertIsNone( np.testing.assert_array_almost_equal(o.elements.z, -134.5, 1)) def test_seed_on_land(self): o = OceanDrift(loglevel=50) o.seed_elements(lon=9, lat=60, time=datetime.now(), number=100) outfile = 'out.nc' with self.assertRaises(ValueError): o.run(steps=4, time_step=1800, time_step_output=3600, outfile=outfile) os.remove(outfile) #o.write_netcdf_density_map(outfile) #os.remove(outfile) def test_retirement(self): o = OceanDrift(loglevel=0) o.set_config('drift:max_age_seconds', 5000) o.set_config('environment:fallback:x_sea_water_velocity', .5) o.set_config('environment:fallback:y_sea_water_velocity', .3) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements( lon=0, lat=60, number=10, time=[datetime.now(), datetime.now() + timedelta(seconds=6000)]) o.run(time_step=1000, duration=timedelta(seconds=7000)) self.assertEqual(o.num_elements_deactivated(), 5) def test_outside_domain(self): o = OceanDrift(loglevel=50) reader_osc_x = reader_oscillating.Reader('x_sea_water_velocity', amplitude=1, zero_time=datetime.now()) reader_osc_y = reader_oscillating.Reader('y_sea_water_velocity', amplitude=1, zero_time=datetime.now()) o.add_reader([reader_osc_x, reader_osc_y]) o.set_config('drift:deactivate_east_of', 2.1) o.set_config('drift:deactivate_west_of', 1.9) o.set_config('drift:deactivate_south_of', 59.9) o.set_config('drift:deactivate_north_of', 60.1) o.set_config('environment:fallback:land_binary_mask', 0) o.seed_elements(lon=2, lat=60, number=1000, time=datetime.now(), radius=10000) o.run(duration=timedelta(hours=5)) self.assertEqual(o.num_elements_deactivated(), 768) self.assertEqual(o.num_elements_active(), 232) def test_seed_time_backwards_run(self): o = OceanDrift(loglevel=20) o.set_config('drift:max_age_seconds', 2000) o.set_config('environment:fallback:x_sea_water_velocity', .5) o.set_config('environment:fallback:y_sea_water_velocity', .3) o.set_config('environment:fallback:land_binary_mask', 0) time = [datetime(2018, 1, 1, i) for i in range(10)] o.seed_elements(lon=0, lat=60, time=time) o.seed_elements(lon=1, lat=60, time=datetime(2018, 1, 1, 7)) o.run(end_time=datetime(2018, 1, 1, 2), time_step=-1800) self.assertEqual(o.num_elements_scheduled(), 3) self.assertEqual(o.num_elements_active(), 8) self.assertEqual(o.steps_calculation, 14) def test_oil_mixed_to_seafloor(self): o = OpenOil(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader(norkyst) o.set_config('processes:evaporation', False) o.set_config('environment:fallback:x_wind', 25) o.set_config('environment:fallback:y_wind', 0) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:ocean_vertical_diffusivity', 0.9) o.seed_elements(lon=5.38, lat=62.77, time=norkyst.start_time, number=100, radius=5000) o.run(end_time=norkyst.end_time) self.assertEqual(o.num_elements_active(), 100) def test_unseeded_elements(self): o = PlastDrift() # Seeding elements for 12 hours, but running only 6 time = datetime(2019, 8, 30, 12) o.seed_elements(lon=4.85, lat=60, number=10, time=[time, time + timedelta(hours=6)], origin_marker=7) o.seed_elements(lon=4.75, lat=60, number=10, time=[time, time + timedelta(hours=6)], origin_marker=8) o.set_config('environment:fallback:land_binary_mask', 0) o.set_config('environment:fallback:y_sea_water_velocity', 1) o.run(duration=timedelta(hours=3)) self.assertEqual(o.history.shape[0], 10) self.assertEqual(o.history.shape[1], 4) self.assertEqual(o.history['origin_marker'].min(), 7) self.assertEqual(o.history['origin_marker'].max(), 8) def test_no_active_but_still_unseeded_elements(self): o = OceanDrift(loglevel=20) # deactivate elements after 3 hours o.set_config('drift:max_age_seconds', 3600 * 3) norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader(norkyst) # seed two elements at 6 hour interval o.seed_elements( number=2, lon=4, lat=62, time=[norkyst.start_time, norkyst.start_time + timedelta(hours=6)]) o.set_config('environment:fallback:land_binary_mask', 0) o.run(duration=timedelta(hours=8), outfile='test.nc') os.remove('test.nc') # Check that simulations has run until scheduled end self.assertEqual(o.steps_calculation, 8)
from opendrift.models.oceandrift import OceanDrift o = OceanDrift() # Basic drift model suitable for passive tracers or drifters ####################### # Preparing Readers ####################### reader_current = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') reader_wind = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') o.add_reader([reader_current, reader_wind]) ####################### # Seeding elements ####################### # Elements are moved with the ocean current, in addition to a fraction of # the wind speed (wind_drift_factor). This factor depends on the properties # of the elements. Typical empirical values are: # - 0.035 (3.5 %) for oil and iSphere driftes # - 0.01 (1 %) for CODE drifters partly submerged ~0.5 m # As there are large uncertainties, it makes sence to provide a statistical # distribution of wind_drift_factors # Using a constant value for all elements: #wind_drift_factor = 0.03
Example to illustrate stranding options using an artificial east-west oscillating current field Knut-Frode Dagestad, Feb 2017 """ from datetime import datetime from opendrift.readers import reader_oscillating from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information reader_osc = reader_oscillating.Reader('x_sea_water_velocity', amplitude=1, zero_time=datetime.now()) o.add_reader([reader_osc]) # Oscillating east-west current component o.fallback_values['y_sea_water_velocity'] = .2 # Adding northwards drift #%% # Try different options: 'previous', 'stranding', 'none' o.set_config('general:coastline_action', 'previous') o.seed_elements(lon=12.2, lat=67.7, radius=5000, number=25, time=reader_osc.zero_time) o.run(steps=36 * 4, time_step=900, time_step_output=1800)
================================================ """ from datetime import timedelta import numpy as np from opendrift.readers.unstructured import shyfem from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information o.set_config('general:coastline_action', 'previous') shyfem = shyfem.Reader( 'https://iws.ismar.cnr.it/thredds/dodsC/emerge/shyfem_unstructured_adriatic.nc' ) o.add_reader(shyfem) print(shyfem) # Seed elements at defined positions, depth and time N = 1000 z = -15 * np.random.uniform(0, 1, N) o.seed_elements(lon=12.4, lat=45.25, radius=1000, number=N, z=z, time=shyfem.start_time) #%% # Running model o.run(time_step=1800, duration=timedelta(hours=12))
thredds_path_2 = 'http://thredds.moanaproject.org:8080/thredds/dodsC/moana/ocean/NZB/v1.9/raw_3D/nz5km_his_201708.nc?ntimes,dt,hc,grid,s_rho[5:1:12],Cs_r[5:1:12],h[0:1:466][0:1:396],lon_rho[0:1:466][0:1:396],lat_rho[0:1:466][0:1:396],lon_u[0:1:466][0:1:395],lat_u[0:1:466][0:1:395],lon_v[0:1:465][0:1:396],lat_v[0:1:465][0:1:396],lon_psi[0:1:465][0:1:395],angle[0:1:466][0:1:396],mask_rho[0:1:466][0:1:396],mask_u[0:1:466][0:1:395],mask_v[0:1:465][0:1:396],ocean_time[0:1:248],z_rho[0:1:248][5:1:12][0:1:466][0:1:396],u_eastward[0:1:248][5:1:12][0:1:466][0:1:396],v_northward[0:1:248][5:1:12][0:1:466][0:1:396]' # to finish the run in the previous month reader_moana_v19_2 = reader_ROMS_native_MOANA.Reader([thredds_path_2]) # reader_moana_v19_2.multiprocessing_fail = True thredds_path_3 = 'http://thredds.moanaproject.org:8080/thredds/dodsC/moana/ocean/NZB/v1.9/raw_3D/nz5km_his_201707.nc?ntimes,dt,hc,grid,s_rho[5:1:12],Cs_r[5:1:12],h[0:1:466][0:1:396],lon_rho[0:1:466][0:1:396],lat_rho[0:1:466][0:1:396],lon_u[0:1:466][0:1:395],lat_u[0:1:466][0:1:395],lon_v[0:1:465][0:1:396],lat_v[0:1:465][0:1:396],lon_psi[0:1:465][0:1:395],angle[0:1:466][0:1:396],mask_rho[0:1:466][0:1:396],mask_u[0:1:466][0:1:395],mask_v[0:1:465][0:1:396],ocean_time[0:1:248],z_rho[0:1:248][5:1:12][0:1:466][0:1:396],u_eastward[0:1:248][5:1:12][0:1:466][0:1:396],v_northward[0:1:248][5:1:12][0:1:466][0:1:396]' # to finish the run in the previous month reader_moana_v19_3 = reader_ROMS_native_MOANA.Reader([thredds_path_3]) # reader_moana_v19_3.multiprocessing_fail = True # Making customised landmask - not required here, using ROMS landmask #reader_landmask = reader_global_landmask.Reader( # llcrnrlon=171.0, llcrnrlat=184.5, # urcrnrlon=-42.0, urcrnrlat=-32.0)# max is 185deg # use native landmask of ROMS files o.add_reader([reader_moana_v19_1, reader_moana_v19_2, reader_moana_v19_3]) #o.add_reader([reader_moana_v19]) o.set_config('general:use_auto_landmask', True) # dynamical landmask ############################### # PARTICLE SEEDING ############################### # Define the starting position of the particles on the Ninety miles beach: 200 random points along the beach, spreading 200m offshore. nb_parts = 501 # number of particles released per point during the release interval points = np.loadtxt( './Second_backtrack_input_files/Release_Ninety_miles_beach_backtrack2_high_dens_500mbuff.xyz', delimiter='\t', dtype=str) plon = points[:, 0].astype(np.float)
from opendrift.readers import reader_basemap_landmask from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=4.0, llcrnrlat=59.9, urcrnrlon=5.5, urcrnrlat=61.2, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_norkyst]) # Seeding some particles lons = np.linspace(4.4, 4.6, 10) lats = np.linspace(60.0, 60.1, 10) lons, lats = np.meshgrid(lons, lats) lons = lons.ravel() lats = lats.ravel() # Seed oil elements on a grid at regular time interval start_time = reader_norkyst.start_time time_step = timedelta(hours=6) num_steps = 10 for i in range(num_steps+1): o.seed_elements(lons, lats, radius=0, number=100, time=start_time + i*time_step)
from opendrift.readers import reader_telemac_selafin from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) filename = '{}Telemac_3D{}r3d_tide_open_drift.slf'.format( o.test_data_folder(), sep) #Lambert North proj = "+proj=lcc +lat_1=49.50000000000001 +lat_0=49.50000000000001 +lon_0=0 \ +k_0=0.999877341 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356515 \ +units=m +no_defs" start_time = datetime(2021, 1, 1, 00, 00) selafin = reader_telemac_selafin.Reader(filename=filename, proj4=proj, start_time=start_time) o.add_reader(selafin) o.set_config('general:coastline_action', 'previous') # start_time = selafin.start_time generally wrong time_step = timedelta(seconds=selafin.slf.tags["times"][1]) length = timedelta(seconds=selafin.slf.tags["times"][-1]) num_steps = len(selafin.slf.tags["times"]) # center seeds in the middle x,y = (selafin.x.max()-selafin.x.min())/2+selafin.x.min(),\ (selafin.y.max()-selafin.y.min())/2+selafin.y.min() p = Proj(proj, preserve_units=False) lon, lat = p(x, y, inverse=True) o.seed_elements(lon=lon, lat=lat, radius=20000, number= 200, z= 0, \ time= start_time) o.run(time_step=time_step / 10, duration=length) o.plot(fast=True)
o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information # Arome reader_arome = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') #reader_arome = reader_netCDF_CF_generic.Reader('https://thredds.met.no/thredds/dodsC/mepslatest/meps_lagged_6_h_latest_2_5km_latest.nc') # Norkyst reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') #reader_norkyst = reader_netCDF_CF_generic.Reader('https://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') o.add_reader([reader_norkyst, reader_arome]) #%% # Seeding some particles lon = 4.2 lat = 60.0 # Outside Bergen time = [reader_arome.start_time, reader_arome.start_time + timedelta(hours=30)] #%% # Seed oil elements at defined position and time o.seed_elements(lon, lat, radius=50, number=5000, time=time) #%% # Using windspeed relative to moving ocean (current) o.set_config('drift:relative_wind', False)
o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader(llcrnrlon=4.0, llcrnrlat=59.9, urcrnrlon=5.5, urcrnrlat=61.2, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_norkyst]) # Seeding some particles lons = np.linspace(4.4, 4.6, 10) lats = np.linspace(60.0, 60.1, 10) lons, lats = np.meshgrid(lons, lats) lons = lons.ravel() lats = lats.ravel() # Seed oil elements on a grid at regular time interval start_time = reader_norkyst.start_time time_step = timedelta(hours=6) num_steps = 10 for i in range(num_steps + 1): o.seed_elements(lons, lats,
reader_current = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') reader_wind = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader(llcrnrlon=4, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_current, reader_wind]) ####################### # Seeding elements ####################### # Elements are moved with the ocean current, in addition to a fraction of # the wind speed (wind_drift_factor). This factor depends on the properties # of the elements. Typical empirical values are: # - 0.035 (3.5 %) for oil and iSphere driftes # - 0.01 (1 %) for CODE drifters partly submerged ~0.5 m # As there are large uncertainties, it makes sence to provide a statistical # distribution of wind_drift_factors # Using a constant value for all elements: #wind_drift_factor = 0.03
from opendrift.readers import reader_ROMS_native from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information # Nordic 4km nordic_native = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=11.0, llcrnrlat=67.5, urcrnrlon=16.0, urcrnrlat=69.0, resolution='h', projection='merc') o.add_reader([reader_basemap, nordic_native]) # Seeding some particles time = nordic_native.start_time lon = 12.0; lat = 68.3; # Seed oil elements at defined position and time o.seed_elements(lon, lat, radius=0, number=10, z=np.linspace(0, -150, 10), time=time) print o # Running model o.run(time_step=3600) # Print and plot results print o
import numpy as np from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information # Norkyst reader_norkyst = reader_netCDF_CF_generic.Reader( 'https://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') # Nordic4 reader_nordic4 = reader_netCDF_CF_generic.Reader( 'https://thredds.met.no/thredds/dodsC/sea/nordic4km/zdepths1h/aggregate_be' ) o.add_reader([reader_norkyst, reader_nordic4]) o.set_config('environment:fallback:land_binary_mask', 0) #%% # Seeding some particles lons = np.linspace(10.2, 12.2, 50) lats = np.linspace(69.8, 70.8, 50) lons, lats = np.meshgrid(lons, lats) #%% # Seed oil elements at defined position and time o.seed_elements(lons, lats, radius=0, number=2500, time=reader_norkyst.start_time)
import numpy as np from opendrift.readers import reader_netCDF_CF_generic from opendrift.readers import reader_ROMS_native from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information o.max_speed = 3 # This example works better using hourly input from Thredds than the daily data from test folder reader_current = reader_netCDF_CF_generic.Reader( 'https://thredds.met.no/thredds/dodsC/cmems/topaz6/dataset-topaz6-arc-15min-3km-be.ncml' ) #reader_current = reader_ROMS_native.Reader(o.test_data_folder() + # '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') o.add_reader([reader_current]) o.set_config('general:coastline_action', 'previous') #%% # Seeding elements on a grid lons = np.linspace(12, 14.5, 30) lats = np.linspace(67.5, 68.5, 30) lons, lats = np.meshgrid(lons, lats) lon = lons.ravel() lat = lats.ravel() time = reader_current.start_time o.seed_elements(lon, lat, radius=0, number=30 * 30, time=time) o.run(steps=24 * 2, time_step=3600)
# SCHISM reader reader_landmask = reader_global_landmask.Reader(llcrnrlon=171.5, llcrnrlat=-43.5, urcrnrlon=177.0, urcrnrlat=-38.0) # NZTM proj4 string found at https://spatialreference.org/ref/epsg/nzgd2000-new-zealand-transverse-mercator-2000/ proj4str_nztm = '+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' schism_native = reader_schism_native.Reader( filename= 'https://thredds.met.no/thredds/dodsC/metusers/knutfd/thredds/netcdf_unstructured_samples/schism_marl20080101_00z_3D.nc', proj4=proj4str_nztm, use_3d=True) # schism_native.plot_mesh(variable = ['sea_floor_depth_below_sea_level']) # check reader was correctly loaded o.add_reader([reader_landmask, schism_native]) o.set_config( 'general:use_auto_landmask', False ) # prevent opendrift from making a new dynamical landmask with global_landmask # Seed elements at defined positions, depth and time o.seed_elements(lon=174.046669, lat=-40.928116, radius=20, number=100, z=np.linspace(0, -10, 100), time=schism_native.start_time) o.seed_elements(lon=173.8839, lat=-40.9160, radius=20,
o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information # Norkyst reader_norkyst = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') # Nordic4 reader_nordic4 = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/sea/nordic4km/zdepths1h/aggregate_be') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=9.5, llcrnrlat=68.8, urcrnrlon=19.0, urcrnrlat=71.2, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_norkyst, reader_nordic4]) #o.add_reader([reader_basemap, reader_norkyst]) # Seeding some particles lons = np.linspace(10.2, 12.2, 50) lats = np.linspace(69.8, 70.8, 50) lons, lats = np.meshgrid(lons, lats) lons = lons.ravel() lats = lats.ravel() # Seed oil elements at defined position and time o.seed_elements(lons, lats, radius=0, number=2500, time=reader_nordic4.start_time) # Running model (until end of driver data) o.run(steps=16*4, time_step=900)
reader_norkyst = reader_netCDF_CF_generic.Reader( 'http://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') # Nordic4 reader_nordic4 = reader_netCDF_CF_generic.Reader( 'http://thredds.met.no/thredds/dodsC/sea/nordic4km/zdepths1h/aggregate_be') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader(llcrnrlon=9.5, llcrnrlat=68.8, urcrnrlon=19.0, urcrnrlat=71.2, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_norkyst, reader_nordic4]) #o.add_reader([reader_basemap, reader_norkyst]) # Seeding some particles lons = np.linspace(10.2, 12.2, 50) lats = np.linspace(69.8, 70.8, 50) lons, lats = np.meshgrid(lons, lats) lons = lons.ravel() lats = lats.ravel() # Seed oil elements at defined position and time o.seed_elements(lons, lats, radius=0, number=2500, time=reader_nordic4.start_time)
60.013670, 60.013412, 60.013240, 60.013068, 60.013154, 60.013412, 60.013584, 60.013842, 60.014186, 60.014616, 60.015218, 60.015820, 60.016594, 60.017454, 60.018400, 60.019346, 60.020464, 60.021410, 60.022442, 60.023474, 60.024678, 60.025882, 60.026914 ] drifterlats = drifterlats[::-1] drifterlons = drifterlons[::-1] driftertimes = [ datetime(2015, 6, 10, 5, 50) + timedelta(minutes=10) * i for i in range(len(drifterlons)) ] r = reader_current_from_drifter.Reader(lons=drifterlons, lats=drifterlats, times=driftertimes) o.add_reader(r) #%% # We seed elements within polygon, as could have been extracted # from remote sensing imagery lons = [2.39, 2.391, 2.392, 2.393, 2.394, 2.393, 2.392, 2.391, 2.39] lats = [60.02, 60.02, 60.019, 60.02, 60.021, 60.022, 60.021, 60.021, 60.02] o.seed_within_polygon(lons=lons, lats=lats, number=1000, time=r.start_time) #%% # Finally running simulation o.run(end_time=r.end_time, time_step=r.time_step) o.animation(buffer=.01, fast=True) #%%
reader_custom = reader_landmask_custom.Reader( polygon_file= '/home/simon/Documents/GitHub/opendrift/examples/schism_marl_edit.shore') # reader_custom.plot() # check reader was correctly loaded, close figure to continue # NZTM proj4 string found at https://spatialreference.org/ref/epsg/nzgd2000-new-zealand-transverse-mercator-2000/ proj4str_nztm = '+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' schism_native = reader_schism_native.Reader( filename= 'https://thredds.met.no/thredds/dodsC/metusers/knutfd/thredds/netcdf_unstructured_samples/schism_marl20080101_00z_3D.nc', proj4=proj4str_nztm, use_3d=True) # schism_native.plot_mesh(variable = 'sea_floor_depth_below_sea_level') # check reader was correctly loaded, close figure to continue o.add_reader([reader_custom, schism_native]) o.set_config( 'general:use_auto_landmask', False ) # prevent opendrift from making a new dynamical landmask with global_landmask # Seed elements at defined positions, depth and time o.seed_elements(lon=174.046669, lat=-40.928116, radius=20, number=100, z=np.linspace(0, -10, 100), time=schism_native.start_time) o.seed_elements(lon=173.8839, lat=-40.9160, radius=20,
def test_output_time_step(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader( o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader(extent=[4.5, 5.2, 60.0, 60.5]) o1.add_reader([landmask, norkyst]) o1.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=30) o2.add_reader([landmask, norkyst]) o2.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100, 25)) self.assertEqual(o2.history.shape, (100, 13)) # Check that start and end conditions (longitudes) are idential self.assertIsNone( np.testing.assert_array_equal( o1.history['lon'][:, 24].compressed(), o2.history['lon'][:, 12].compressed())) self.assertIsNone( np.testing.assert_array_equal(o1.history['lon'][:, 0].compressed(), o2.history['lon'][:, 0].compressed())) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertIsNone( np.testing.assert_array_equal( o2i.history['lon'][:, 12].compressed(), o2.history['lon'][:, 12].compressed())) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated())
from opendrift.models.oceandrift import OceanDrift lon = 4.5; lat = 60.0; # Outside Bergen o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information # Arome atmospheric model reader_arome = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') # Norkyst ocean model reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') # Uncomment to use live data from thredds #reader_arome = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/meps25files/meps_det_extracted_2_5km_latest.nc') #reader_norkyst = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') o.set_config('general:basemap_resolution', 'i') o.add_reader([reader_norkyst, reader_arome]) time = reader_arome.start_time o.seed_elements(lon, lat, radius=500, number=2000, time=time) o.set_config('drift:current_uncertainty', 0) # 0 is default o.run(duration=timedelta(hours=24)) # Second run, identical, except for added diffusion o2 = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information o2.set_config('general:basemap_resolution', 'i') o2.add_reader([reader_norkyst, reader_arome]) o2.seed_elements(lon, lat, radius=500, number=2000, time=time) o2.set_config('drift:current_uncertainty', .2) # Difference from first run o2.run(duration=timedelta(hours=24)) # Comparing
number = 10000 outfile = 'simulation.nc' # Raw simulation output o.seed_elements(time=t1, lon=4, lat=60, number=number, origin_marker=0) o.seed_elements(time=[t1, t2], lon=4.2, lat=60.4, number=number, origin_marker=1) reader_x = reader_oscillating.Reader('x_sea_water_velocity', amplitude=1, zero_time=t1) reader_y = reader_oscillating.Reader('y_sea_water_velocity', amplitude=1, zero_time=t2) o.add_reader([reader_x, reader_y]) o.set_config('drift:horizontal_diffusivity', 10) o.run(duration=timedelta(hours=24), time_step=900, time_step_output=1800, outfile=outfile) #%% # Opening the output file lazily with Xarray. # This will work even if the file is too large to fit in memory, as it # will read and process data chuck-by-chunk directly from file using Dask. # Note that the analysis file will be re-used if existing. Thus this file should be deleted after making any changes to the simulation above. o = opendrift.open_xarray(outfile, analysis_file='simulation_density.nc') #%% # Making two animations, for each of the two seedings / origin_markers.
import numpy as np from opendrift.readers import reader_netCDF_CF_generic from opendrift.readers import reader_ROMS_native from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information o.max_speed = 3 # This example works better using hourly input from Thredds than the daily data from test folder reader_nordic = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/sea/nordic4km/zdepths1h/aggregate_be') #reader_nordic = reader_ROMS_native.Reader(o.test_data_folder() + # '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') o.add_reader([reader_nordic]) o.set_config('general:basemap_resolution', 'h') o.set_config('general:coastline_action', 'previous') # Seeding elements on a grid lons = np.linspace(12, 14.5, 30) lats = np.linspace(67.5, 68.5, 30) lons, lats = np.meshgrid(lons, lats) lon = lons.ravel() lat = lats.ravel() time = reader_nordic.start_time o.seed_elements(lon, lat, radius=0, number=30*30, time=time) o.run(steps=24*2, time_step=3600)
# By intialisation, only an XML-file with the contents is downloaded. # The netCDF file with data is downloaded later, after the simulation is started, # when necessary coverage (time/space) is known ( <reader>.prepare() ) cmems = reader_cmems.Reader( dataset='global-analysis-forecast-phy-001-024-hourly-merged-uv', variable_mapping={ # Overriding the mapping in reader_cmems.py 'utotal': 'x_sea_water_velocity', 'vtotal': 'y_sea_water_velocity', 'utide': 'sea_ice_x_velocity', # Fake mapping, as standard_name 'vtide': 'sea_ice_y_velocity' }) # must be unique for a reader o = OceanDrift() o.add_reader(cmems) # Alternatively, use OPeNDAP directly: # https://help.marine.copernicus.eu/en/articles/5182598-how-to-consume-the-opendap-api-and-cas-sso-using-python #o.add_readers_from_list(['https://nrt-dev.cmems-du.eu/thredds/dodsC/global-analysis-forecast-phy-001-024-hourly-merged-uv']) o.seed_elements(lon=lon, lat=lat, number=5000, radius=1000, time=time) o.run(duration=duration) # Although total current (SMOC) has been used as forcing, we plot the tidal current as background field, disguised as ice velocity o.animation(fast=True, clabel='Tidal current [m/s]', skip=1, scale=20, background=['sea_ice_x_velocity', 'sea_ice_y_velocity']) #%%
time_step = timedelta(seconds=.5) time_step_output = timedelta(seconds=.5) delta = .01 # spatial resolution steps = int(duration.total_seconds() / time_step_output.total_seconds() + 1) o = OceanDrift(loglevel=20) o.fallback_values['land_binary_mask'] = 0 #%% # Note that Runge-Kutta here makes a difference to Euler scheme o.set_config('drift:scheme', 'runge-kutta4') double_gyre = reader_double_gyre.Reader(epsilon=.25, omega=0.628, A=0.1) print(double_gyre) o.add_reader(double_gyre) #%% # Calculate Lyapunov exponents times = [double_gyre.initial_time + n * time_step_output for n in range(steps)] lcs = o.calculate_ftle(time=times, time_step=time_step, duration=duration, delta=delta, RLCS=False) #%% # Make run with particles for the same period o.reset() x = [.9] y = [.5] lon, lat = double_gyre.xy2lonlat(x, y)
import numpy as np from opendrift.readers import reader_netCDF_CF_generic from opendrift.readers import reader_ROMS_native from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information o.max_speed = 3 # This example works better using hourly input from Thredds than the daily data from test folder reader_nordic = reader_netCDF_CF_generic.Reader( 'https://thredds.met.no/thredds/dodsC/sea/nordic4km/zdepths1h/aggregate_be' ) #reader_nordic = reader_ROMS_native.Reader(o.test_data_folder() + # '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') o.add_reader([reader_nordic]) o.set_config('general:coastline_action', 'previous') #%% # Seeding elements on a grid lons = np.linspace(12, 14.5, 30) lats = np.linspace(67.5, 68.5, 30) lons, lats = np.meshgrid(lons, lats) lon = lons.ravel() lat = lats.ravel() time = reader_nordic.start_time o.seed_elements(lon, lat, radius=0, number=30 * 30, time=time) o.run(steps=24 * 2, time_step=3600)
class TestRun(unittest.TestCase): """Tests for (non-scalar) LagrangianArray""" def make_OceanDrift_object(self): self.o = OceanDrift(loglevel=20) self.fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) self.o.use_block = False self.reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=-1.5, llcrnrlat=59, urcrnrlon=7, urcrnrlat=64, resolution='i') self.o.add_reader([self.fake_eddy, self.reader_basemap]) def test_seed(self): """Test seeding""" o = OceanDrift(loglevel=20) number = 3 lonvec = np.linspace(2, 5, number) latvec = np.linspace(60, 61, number) o.seed_elements(lonvec, latvec, number=number, time=datetime(2015, 1, 1, 12, 5, 17)) #time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.num_elements_active(), 0) self.assertEqual(o.num_elements_activated(), 0) self.assertEqual(o.num_elements_deactivated(), 0) self.assertEqual(o.num_elements_total(), number) def test_seed_outside_coverage(self): """Test seeding""" o = OpenOil3D(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4, llcrnrlat=60, urcrnrlon=6, urcrnrlat=64, resolution='c', projection='merc') o.add_reader([basemap, norkyst]) o.seed_elements(5, 63, number=5, time=norkyst.start_time - 24*timedelta(hours=24)) o.run(steps=3, time_step=timedelta(minutes=15)) def test_runge_kutta(self): number = 50 # With Euler o = OceanDrift3D(loglevel=20, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.add_reader([norkyst]) z=-40*np.random.rand(number) o.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o.run(steps=4*3, time_step=timedelta(minutes=15)) # With Runge-Kutta o2 = OceanDrift3D(loglevel=20, seed=0) o2.fallback_values['land_binary_mask'] = 0 o2.add_reader([norkyst]) z=-40*np.random.rand(number) o2.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o2.set_config('drift:scheme', 'runge-kutta') o2.run(steps=4*3, time_step=timedelta(minutes=15)) # And finally repeating the initial run to check that indetical o3 = OceanDrift3D(loglevel=20, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o3.fallback_values['land_binary_mask'] = 0 o3.add_reader([norkyst]) z=-40*np.random.rand(number) o3.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o3.run(steps=4*3, time_step=timedelta(minutes=15)) # Check that we get some difference with Runge-Kutta: self.assertAlmostEqual((o2.elements.lon-o.elements.lon).max(), 0.0015, 3) # Check that runs with Euler are identical self.assertEqual((o3.elements.lon-o.elements.lon).max(), 0) def test_seed_polygon(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=datetime(2015, 1, 1, 12, 5, 17) o.seed_within_polygon(lonvec, latvec, number=number, time=time, wind_drift_factor=.09) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time) self.assertAlmostEqual(o.elements_scheduled.wind_drift_factor, .09) def test_seed_polygon_timespan(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=[datetime(2015, 1, 1, 12, 5, 17), datetime(2015, 1, 1, 18, 5, 17)] o.seed_within_polygon(lonvec, latvec, number=number, time=time) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time[0]) self.assertEqual(o.elements_scheduled_time[-1], time[-1]) @unittest.skipIf(has_ogr is False, 'OGR library needed to read shapefiles') def test_seed_shapefile(self): o = OceanDrift(loglevel=20) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=100, layername=None, featurenum=[2, 4], time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 100) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=300, layername=None, featurenum=None, time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 400) #@unittest.skipIf(has_ogr is False, # 'GDAL library needed to read shapefiles') #def test_write_geotiff(self): # o = OceanDrift(loglevel=20) # o.seed_elements(lon=4, lat=60, time=datetime(2016, 1, 1)) # o.run(steps=3) # o.write_geotiff('geotiff.tif') def test1_seed_single_point_over_time(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements(2.0, 61.0, radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 5) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) def test2_seed_elementss(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements([2.0, 4.5, 3.0], [61.0, 60.0, 62.0], radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 9) def test3_run_import(self): """Import output file from previous test, and check elements""" self.o = OceanDrift(loglevel=20) self.o.io_import_file('unittest.nc') self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 5) def test4_cleaning(self): """Cleaning up""" os.remove('unittest.nc') def test_temporal_seed(self): self.o = OceanDrift(loglevel=20) self.o.fallback_values['x_sea_water_velocity'] = 1 self.o.fallback_values['land_binary_mask'] = 0 # Seed elements on a grid at regular time interval start_time = datetime(2016,9,16) time_step = timedelta(hours=6) num_steps = 10 lon = 4.4 lat = 60.0 for i in range(num_steps+1): self.o.seed_elements(lon, lat, radius=0, number=2, time=start_time + i*time_step) # Running model self.o.run(steps=20, time_step=3600, outfile='temporal_seed.nc') self.o = OceanDrift(loglevel=20) # Check that data imported is properly masked self.o.io_import_file('temporal_seed.nc') self.assertTrue(self.o.history['lon'].max() < 1000) self.assertTrue(self.o.history['lon'].min() > -1000) self.assertTrue(self.o.history['lon'].mask[5,5]) self.assertFalse(self.o.history['lon'].mask[1,1]) os.remove('temporal_seed.nc') def test_vertical_mixing(self): # Export to file only at end o1 = PelagicEggDrift(loglevel=20) # Profiles and vertical mixing norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o1.add_reader([norkyst]) o1.fallback_values['x_wind'] = 8 o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.1, 63.3, radius=1000, number=100, time=norkyst.start_time) o1.set_config('turbulentmixing:timestep', 20.) # seconds o1.set_config('turbulentmixing:verticalresolution', 1.) # m o1.run(steps=20, time_step=300, time_step_output=1800, export_buffer_length=10, outfile='verticalmixing.nc') self.assertAlmostEqual(o1.history['z'].min(), -25.0) self.assertAlmostEqual(o1.history['z'].max(), 0.0) os.remove('verticalmixing.nc') def test_export_step_interval(self): # Export to file only at end o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o1.add_reader(norkyst) o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o1.run(steps=40) # Export to file during simulation o2 = OceanDrift(loglevel=20) o2.add_reader(norkyst) o2.fallback_values['land_binary_mask'] = 0 o2.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o2.run(steps=40, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) # Finally check when steps is multiple of export_buffer_length o3 = OceanDrift(loglevel=20) o3.add_reader(norkyst) o3.fallback_values['land_binary_mask'] = 0 o3.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o3.run(steps=42) # Export to file during simulation o4 = OceanDrift(loglevel=20) o4.add_reader(norkyst) o4.fallback_values['land_binary_mask'] = 0 o4.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o4.run(steps=42, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o3.history['lon'].compressed(), o4.history['lon'].compressed()) os.remove('export_step_interval.nc') def test_buffer_length_stranding(self): o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=1, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='i', projection='merc') o1.add_reader([basemap]) o1.fallback_values['x_sea_water_velocity'] = 1.0 # onshore drift o1.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o1.run(steps=100, time_step=900, time_step_output=3600, export_buffer_length=10) # Without buffer o2 = OceanDrift(loglevel=20) o2.add_reader([basemap]) o2.fallback_values['x_sea_water_velocity'] = 1.0 # onshore drift o2.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o2.run(steps=100, time_step=900, time_step_output=3600, outfile='test_buffer_length_stranding.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) self.assertItemsEqual(o1.history['status'].compressed(), o2.history['status'].compressed()) os.remove('test_buffer_length_stranding.nc') def test_output_time_step(self): o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='i', projection='merc') o1.add_reader([basemap, norkyst]) o1.seed_elements(4.95, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=20) o2.add_reader([basemap, norkyst]) o2.seed_elements(4.95, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100,25)) self.assertEqual(o2.history.shape, (100,13)) # Check that start and end conditions (longitudes) are idential self.assertItemsEqual(o1.history['lon'][:,24].compressed(), o2.history['lon'][:,12].compressed()) self.assertItemsEqual(o1.history['lon'][:,0].compressed(), o2.history['lon'][:,0].compressed()) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertItemsEqual(o2i.history['lon'][:,12].compressed(), o2.history['lon'][:,12].compressed()) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated()) def test_reader_boundary(self): # Check that the element outside reader coverage is # not deactivated if fallback value exist o = OceanDrift() nordic3d = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') lon = [12.0, 12.0] lat = [70.0, 70.5] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 2) self.assertEqual(o.num_elements_deactivated(), 0) # Check that the outside element is deactivated, # if no fallback value exists o = OceanDrift() del o.fallback_values['x_sea_water_velocity'] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) def test_reader_order(self): # Check that we get the same output indepenently of reader order o = OceanDrift(loglevel=50) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') arome = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=2, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='c', projection='merc') lon=4.; lat=60. # First run o.add_reader([basemap, norkyst, arome]) o.seed_elements(lon, lat, time=norkyst.start_time) o.run(steps=30) # Second run # Check that we get almost identical results with other projection o1 = OceanDrift(loglevel=50) o1.add_reader([norkyst, arome, basemap]) o1.seed_elements(lon, lat, time=norkyst.start_time) o1.run(steps=30) self.assertAlmostEqual(o.elements.lon, o1.elements.lon, 2) self.assertAlmostEqual(o.elements.lat, o1.elements.lat, 2) # Third run # Check that this is identical to run 1 if projection set equal o2 = OceanDrift(loglevel=50) o2.add_reader([norkyst, arome, basemap]) o2.seed_elements(lon, lat, time=norkyst.start_time) o2.set_projection(basemap.proj4) o2.run(steps=30) self.assertEqual(o.elements.lon, o2.elements.lon) def test_seed_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.add_reader([reader_norkyst]) lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z='seafloor', time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.2, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -106.0, 2) # After some rising def test_seed_below_reader_coverage(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.add_reader([reader_norkyst]) lon = 5.0; lat = 64.0 o.seed_elements(lon, lat, z=-350, time=reader_norkyst.start_time, density=1000) #o.set_config('turbulentmixing:TSprofiles', True) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[-1,0], -305.0, 2) # After some rising def test_seed_below_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.fallback_values['land_binary_mask'] = 0 lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z=-5000, time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.2, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -106.0, 2) # After some rising def test_lift_above_seafloor(self): # See an element at some depth, and progapate towards coast # (shallower water) and check that it is not penetrating seafloor o = OceanDrift3D(loglevel=20, proj4='+proj=merc') o.max_speed = 100 reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') reader_norkyst.buffer = 200 o.add_reader([reader_norkyst], variables='sea_floor_depth_below_sea_level') o.fallback_values['x_sea_water_velocity'] = 100 # Pure eastward motion o.fallback_values['y_sea_water_velocity'] = 0 o.fallback_values['land_binary_mask'] = 0 o.seed_elements(3.0, 62.0, z=-200, time=reader_norkyst.start_time) o.set_config('processes:turbulentmixing', False) o.run(steps=26, time_step=30) seafloor_depth, status = o.get_property('sea_floor_depth_below_sea_level') z, status = o.get_property('z') # Uncomment to plot #import matplotlib.pyplot as plt #plt.plot(-seafloor_depth, label='Seafloor depth') #plt.plot(z, label='Element depth') #plt.legend(loc='best') #plt.show() # Check that element has not penetrated seafloor self.assertFalse(o.elements.z < -o.environment.sea_floor_depth_below_sea_level) self.assertAlmostEqual(o.elements.z, -159.6, 1) def test_seed_on_land(self): o = OceanDrift(loglevel=50) o.set_config('general:basemap_resolution', 'c') o.seed_elements(lon=9, lat=60, time=datetime.now(), number=100) outfile='out.nc' o.run(steps=4, time_step=1800, time_step_output=3600, outfile=outfile) os.remove(outfile) o.write_netcdf_density_map(outfile) os.remove(outfile)
class TestRun(unittest.TestCase): """Tests for (non-scalar) LagrangianArray""" def make_OceanDrift_object(self): self.o = OceanDrift(loglevel=30) self.fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) self.o.use_block = False self.reader_landmask = reader_global_landmask.Reader( extent = [-1.5, 59, 7, 64]) self.o.add_reader([self.fake_eddy, self.reader_landmask]) def test_seed(self): """Test seeding""" o = OceanDrift(loglevel=20) number = 3 lonvec = np.linspace(2, 5, number) latvec = np.linspace(60, 61, number) o.seed_elements(lonvec, latvec, number=number, time=datetime(2015, 1, 1, 12, 5, 17)) #time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.num_elements_active(), 0) self.assertEqual(o.num_elements_activated(), 0) self.assertEqual(o.num_elements_deactivated(), 0) self.assertEqual(o.num_elements_total(), number) def test_seed_cone(self): o = OceanDrift(loglevel=20) o.seed_elements(time=[datetime.now(), datetime.now() + timedelta(hours=3)], number=100, cone=True, lat=[60.5, 60.6], lon=[4.4, 4.5]) self.assertAlmostEqual(o.elements_scheduled.lon[50], 4.450, 2) def test_seed_outside_coverage(self): """Test seeding""" o = OpenOil3D(loglevel=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') landmask = reader_global_landmask.Reader( llcrnrlon=4, llcrnrlat=60, urcrnrlon=6, urcrnrlat=64) o.add_reader([landmask, norkyst]) o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.set_config('seed:oil_type', 'SNORRE B') o.seed_elements(5, 63, number=5, time=norkyst.start_time - 24*timedelta(hours=24)) # Check that the oiltype is taken from config self.assertEqual(o.oil_name, o.get_config('seed:oil_type')) self.assertEqual(o.oil_name, 'SNORRE B') with self.assertRaises(ValueError): o.run(steps=3, time_step=timedelta(minutes=15)) def test_runge_kutta(self): number = 50 # With Euler o = OceanDrift3D(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.add_reader([norkyst]) z=-40*np.random.rand(number) o.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o.run(steps=4*3, time_step=timedelta(minutes=15)) # With Runge-Kutta o2 = OceanDrift3D(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o2.fallback_values['land_binary_mask'] = 0 o2.add_reader([norkyst]) z=-40*np.random.rand(number) o2.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o2.set_config('drift:scheme', 'runge-kutta') o2.run(steps=4*3, time_step=timedelta(minutes=15)) # And finally repeating the initial run to check that indetical o3 = OceanDrift3D(loglevel=30, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o3.fallback_values['land_binary_mask'] = 0 o3.add_reader([norkyst]) z=-40*np.random.rand(number) o3.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o3.run(steps=4*3, time_step=timedelta(minutes=15)) # Check that we get some difference with Runge-Kutta: self.assertIsNone(np.testing.assert_array_almost_equal( (o2.elements.lon-o.elements.lon).max(), 0.0015, 3)) #(o2.elements.lon-o.elements.lon).max(), 0.013, 3)) # Check that runs with Euler are identical self.assertIsNone(np.testing.assert_array_almost_equal( (o3.elements.lon-o.elements.lon).max(), 0)) def test_seed_polygon(self): o = OpenOil3D(loglevel=0) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=datetime(2015, 1, 1, 12, 5, 17) o.set_config('seed:oil_type', 'HEIDRUN') o.seed_within_polygon(lonvec, latvec, number=number, time=time, wind_drift_factor=.09) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time) self.assertAlmostEqual(o.elements_scheduled.wind_drift_factor, .09) # Check that oil type is taken fom config self.assertEqual(o.oil_name, 'HEIDRUN') def test_seed_polygon_timespan(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=[datetime(2015, 1, 1, 12, 5, 17), datetime(2015, 1, 1, 18, 5, 17)] o.seed_within_polygon(lonvec, latvec, number=number, time=time) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time[0]) self.assertEqual(o.elements_scheduled_time[-1], time[-1]) @unittest.skipIf(has_ogr is False, 'OGR library needed to parse WKT') def test_seed_wkt(self): wkt = 'MULTIPOLYGON(((7.784889 64.353442,7.777561 64.353842,7.774236 64.354707,7.770215 64.355829,7.774269 64.356015,7.776829 64.356863,7.779107 64.3578,7.782827 64.358355,7.786346 64.359615,7.787109 64.361975,7.790125 64.361132,7.794584 64.359908,7.798455 64.359624,7.797258 64.358193,7.79978 64.356904,7.795957 64.356494,7.792955 64.355335,7.789134 64.355339,7.784889 64.353442)))' o = OceanDrift(loglevel=20) o.seed_from_wkt(wkt, time=datetime.now(), number=100) wkt_multi = 'MULTIPOLYGON(((2.458058 59.178919,2.456276 59.179283,2.454867 59.180692,2.45277 59.182852,2.452521 59.183759,2.452675 59.184726,2.451365 59.18534,2.451436 59.186609,2.450835 59.188138,2.449576 59.189435,2.447393 59.190818,2.447211 59.191915,2.446273 59.193573,2.445551 59.19423,2.446597 59.195015,2.44838 59.194651,2.450277 59.193,2.452377 59.191919,2.453315 59.19026,2.45457 59.187885,2.455473 59.186131,2.457033 59.18461,2.458774 59.181992,2.458971 59.180403,2.459775 59.179444,2.459606 59.178969,2.458058 59.178919)),((2.442682 59.197444,2.440531 59.198922,2.439575 59.199994,2.440874 59.200951,2.439596 59.20166,2.436232 59.202958,2.433255 59.203728,2.42982 59.203756,2.428 59.202946,2.425857 59.200693,2.42454 59.199149,2.422418 59.198563,2.419404 59.198158,2.417332 59.197175,2.41514 59.19532,2.412395 59.194596,2.410072 59.194519,2.409481 59.193397,2.408199 59.191947,2.405959 59.190489,2.403129 59.188988,2.401292 59.18759,2.398331 59.187867,2.395639 59.187825,2.393585 59.187428,2.389665 59.187697,2.38736 59.188208,2.386923 59.189132,2.390625 59.188785,2.392191 59.189424,2.395825 59.188887,2.398602 59.188627,2.402104 59.189869,2.403773 59.191871,2.407276 59.193113,2.407648 59.194158,2.407751 59.195522,2.410008 59.196488,2.411979 59.197187,2.41439 59.19912,2.415839 59.199965,2.417946 59.201043,2.417796 59.202235,2.414886 59.203195,2.411923 59.203473,2.40923 59.203431,2.409753 59.204363,2.412549 59.20469,2.415342 59.203937,2.41891 59.20321,2.420325 59.203961,2.420463 59.20542,2.419357 59.207683,2.4218 59.208631,2.420303 59.209262,2.418925 59.210766,2.421401 59.21073,2.424984 59.20951,2.425201 59.208508,2.425939 59.207359,2.428832 59.205812,2.431004 59.206001,2.433124 59.205507,2.436926 59.204365,2.439568 59.203724,2.441518 59.202755,2.442879 59.201744,2.443246 59.20063,2.443311 59.199741,2.444589 59.199032,2.445428 59.198168,2.445088 59.197218,2.442682 59.197444)))' o.seed_from_wkt(wkt_multi, time=datetime.now(), number=200) self.assertEqual(len(o.elements_scheduled), 300) self.assertAlmostEqual( o.elements_scheduled.lat.max(), 64.36, 2) self.assertAlmostEqual( o.elements_scheduled.lat.min(), 59.18, 2) @unittest.skipIf(has_ogr is False, 'OGR library needed to read shapefiles') def test_seed_shapefile(self): o = OceanDrift(loglevel=20) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=100, layername=None, featurenum=[2, 4], time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 100) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=300, layername=None, featurenum=None, time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 400) #@unittest.skipIf(has_ogr is False, # 'GDAL library needed to read shapefiles') #def test_write_geotiff(self): # o = OceanDrift(loglevel=20) # o.seed_elements(lon=4, lat=60, time=datetime(2016, 1, 1)) # o.run(steps=3) # o.write_geotiff('geotiff.tif') def test1_seed_single_point_over_time(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements(2.0, 61.0, radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 5) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) def test2_seed_elements(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements([2.0, 5.0, 3.0], [61.0, 60.0, 62.0], radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 9) def test3_run_import(self): """Import output file from previous test, and check elements""" self.o = OceanDrift(loglevel=20) self.o.io_import_file('unittest.nc') self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 5) def test4_cleaning(self): """Cleaning up""" os.remove('unittest.nc') def test_temporal_seed(self): self.o = OceanDrift(loglevel=20) self.o.fallback_values['x_sea_water_velocity'] = 1 self.o.fallback_values['land_binary_mask'] = 0 # Seed elements on a grid at regular time interval start_time = datetime(2016,9,16) time_step = timedelta(hours=6) num_steps = 10 lon = 4.4 lat = 60.0 for i in range(num_steps+1): self.o.seed_elements(lon, lat, radius=0, number=2, time=start_time + i*time_step) # Running model self.o.run(steps=20, time_step=3600, outfile='temporal_seed.nc') self.o = OceanDrift(loglevel=20) # Check that data imported is properly masked self.o.io_import_file('temporal_seed.nc') self.assertTrue(self.o.history['lon'].max() < 1000) self.assertTrue(self.o.history['lon'].min() > -1000) self.assertTrue(self.o.history['lon'].mask[5,5]) self.assertFalse(self.o.history['lon'].mask[1,1]) os.remove('temporal_seed.nc') def test_vertical_mixing(self): # Export to file only at end o1 = PelagicEggDrift(loglevel=20) # Profiles and vertical mixing norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o1.add_reader([norkyst]) o1.fallback_values['x_wind'] = 8 o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.1, 63.3, radius=1000, number=100, time=norkyst.start_time) o1.set_config('turbulentmixing:timestep', 20.) # seconds o1.run(steps=20, time_step=300, time_step_output=1800, export_buffer_length=10, outfile='verticalmixing.nc') self.assertAlmostEqual(o1.history['z'].min(), -38.1, 1) self.assertAlmostEqual(o1.history['z'].max(), 0.0, 1) os.remove('verticalmixing.nc') def test_export_step_interval(self): # Export to file only at end o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o1.add_reader(norkyst) o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o1.run(steps=40) # Export to file during simulation o2 = OceanDrift(loglevel=20) o2.add_reader(norkyst) o2.fallback_values['land_binary_mask'] = 0 o2.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o2.run(steps=40, export_buffer_length=6, outfile='export_step_interval.nc') self.assertIsNone(np.testing.assert_array_equal( o1.history['lon'].compressed(), o2.history['lon'].compressed())) # Finally check when steps is multiple of export_buffer_length o3 = OceanDrift(loglevel=20) o3.add_reader(norkyst) o3.fallback_values['land_binary_mask'] = 0 o3.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o3.run(steps=42) # Export to file during simulation o4 = OceanDrift(loglevel=20) o4.add_reader(norkyst) o4.fallback_values['land_binary_mask'] = 0 o4.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o4.run(steps=42, export_buffer_length=6, outfile='export_step_interval.nc') self.assertIsNone(np.testing.assert_array_equal( o3.history['lon'].compressed(), o4.history['lon'].compressed())) os.remove('export_step_interval.nc') def test_buffer_length_stranding(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader( llcrnrlon=4.5, llcrnrlat=60.1, urcrnrlon=6.0, urcrnrlat=60.4) o1.add_reader([landmask]) o1.fallback_values['x_sea_water_velocity'] = 0.8 # onshore drift o1.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o1.run(steps=100, time_step=900, time_step_output=3600, export_buffer_length=10) # Without buffer o2 = OceanDrift(loglevel=30) o2.add_reader([landmask]) o2.fallback_values['x_sea_water_velocity'] = 0.8 # onshore drift o2.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o2.run(steps=100, time_step=900, time_step_output=3600, outfile='test_buffer_length_stranding.nc') self.assertIsNone(np.testing.assert_array_equal( o1.history['lon'].compressed(), o2.history['lon'].compressed())) self.assertIsNone(np.testing.assert_array_almost_equal( o1.history['status'].compressed(), o2.history['status'].compressed())) os.remove('test_buffer_length_stranding.nc') def test_output_time_step(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader( llcrnrlon=4.5, llcrnrlat=60.0, urcrnrlon=5.2, urcrnrlat=60.5) o1.add_reader([landmask, norkyst]) o1.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=30) o2.add_reader([landmask, norkyst]) o2.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100,25)) self.assertEqual(o2.history.shape, (100,13)) # Check that start and end conditions (longitudes) are idential self.assertIsNone(np.testing.assert_array_equal( o1.history['lon'][:,24].compressed(), o2.history['lon'][:,12].compressed())) self.assertIsNone(np.testing.assert_array_equal( o1.history['lon'][:,0].compressed(), o2.history['lon'][:,0].compressed())) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertIsNone(np.testing.assert_array_equal( o2i.history['lon'][:,12].compressed(), o2.history['lon'][:,12].compressed())) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated()) def test_time_step_config(self): # Default o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 3600) self.assertEqual(o.time_step_output.total_seconds(), 3600) # Setting time_step o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2, time_step=1800) self.assertEqual(o.time_step.total_seconds(), 1800) # Setting time_step and time_step_output o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=4, lat=60, time=datetime.now()) o.run(steps=2, time_step=1800, time_step_output=3600) self.assertEqual(o.time_step.total_seconds(), 1800) self.assertEqual(o.time_step_output.total_seconds(), 3600) # time_step from config o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=4, lat=60, time=datetime.now()) o.set_config('general:time_step_minutes', 15) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 900) self.assertEqual(o.time_step_output.total_seconds(), 900) # time_step and time_step_output from config o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=4, lat=60, time=datetime.now()) o.set_config('general:time_step_minutes', 15) o.set_config('general:time_step_output_minutes', 120) o.run(steps=2) self.assertEqual(o.time_step.total_seconds(), 900) self.assertEqual(o.time_step_output.total_seconds(), 7200) def test_reader_boundary(self): # Check that the element outside reader coverage is # not deactivated if fallback value exist o = OceanDrift() nordic3d = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') lon = [12.0, 12.0] lat = [70.0, 70.5] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 2) self.assertEqual(o.num_elements_deactivated(), 0) # Check that the outside element is deactivated, # if no fallback value exists o = OceanDrift() del o.fallback_values['x_sea_water_velocity'] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) @pytest.mark.slow def test_reader_order(self): # Check that we get the same output indepenently of reader order o = OceanDrift(loglevel=50) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') arome = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') landmask = reader_global_landmask.Reader(extent = [2, 59.8, 6, 61]) lon=4.; lat=60. # First run o.add_reader([landmask, norkyst, arome]) o.seed_elements(lon, lat, time=norkyst.start_time) o.run(steps=30) # Second run # Check that we get almost identical results with other projection o1 = OceanDrift(loglevel=50) o1.add_reader([norkyst, arome, landmask]) o1.seed_elements(lon, lat, time=norkyst.start_time) o1.run(steps=30) np.testing.assert_array_almost_equal( o.elements.lon, o1.elements.lon, 2) np.testing.assert_array_almost_equal( o.elements.lat, o1.elements.lat, 2) # Third run # Check that this is identical to run 1 if projection set equal o2 = OceanDrift(loglevel=50) o2.add_reader([norkyst, arome, landmask]) o2.seed_elements(lon, lat, time=norkyst.start_time) o2.set_projection(landmask.proj4) o2.run(steps=30) np.testing.assert_array_almost_equal( o.elements.lon, o2.elements.lon, decimal=3) def test_seed_seafloor(self): o = OpenOil3D(loglevel=30) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') # Adding reader as lazy, to test seafloor seeding o.add_readers_from_list([o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc']) o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z='seafloor', time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -94.0, 1) # After some rising def test_seed_above_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 o.add_reader([reader_norkyst]) lon = 4.5; lat = 62.0 # Seed elements 50 meters above seafloor: o.seed_elements(lon, lat, z='seafloor+50', time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -101.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -44.3, 1) # After some rising def test_seed_below_reader_coverage(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.add_reader([reader_norkyst]) lon = 5.0; lat = 64.0 o.seed_elements(lon, lat, z=-350, time=reader_norkyst.start_time, density=1000) #o.set_config('turbulentmixing:TSprofiles', True) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[-1,0], -291.7, 1) # After some rising def test_seed_below_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z=-5000, time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -94.0, 1) # After some rising def test_seed_below_seafloor_deactivating(self): o = OpenOil3D(loglevel=50) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z=[-5000, -100], time=reader_norkyst.start_time, density=1000, number=2) o.set_config('drift:lift_to_seafloor', False) # This time we deactivate o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertEqual(o.num_elements_total(), 2) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) self.assertAlmostEqual(z[0,1], -100, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,1], -35.7, 1) # After some rising def test_lift_above_seafloor(self): # See an element at some depth, and progapate towards coast # (shallower water) and check that it is not penetrating seafloor o = OceanDrift3D(loglevel=30, proj4='+proj=merc') o.max_speed = 100 reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') reader_norkyst.buffer = 200 o.add_reader([reader_norkyst], variables='sea_floor_depth_below_sea_level') o.fallback_values['x_sea_water_velocity'] = 100 # Pure eastward motion o.fallback_values['y_sea_water_velocity'] = 0 o.fallback_values['land_binary_mask'] = 0 o.seed_elements(3.0, 62.0, z=-200, time=reader_norkyst.start_time) o.set_config('processes:turbulentmixing', False) o.run(steps=26, time_step=30) seafloor_depth, status = o.get_property('sea_floor_depth_below_sea_level') z, status = o.get_property('z') # Uncomment to plot #import matplotlib.pyplot as plt #plt.plot(-seafloor_depth, label='Seafloor depth') #plt.plot(z, label='Element depth') #plt.legend(loc='best') #plt.show() # Check that element has not penetrated seafloor self.assertFalse(o.elements.z < -o.environment.sea_floor_depth_below_sea_level) self.assertIsNone(np.testing.assert_array_almost_equal( o.elements.z, -160.06, 1)) def test_seed_on_land(self): o = OceanDrift(loglevel=0) o.seed_elements(lon=9, lat=60, time=datetime.now(), number=100) outfile='out.nc' with self.assertRaises(ValueError): o.run(steps=4, time_step=1800, time_step_output=3600, outfile=outfile) os.remove(outfile) #o.write_netcdf_density_map(outfile) #os.remove(outfile) def test_retirement(self): o = OceanDrift(loglevel=0) o.set_config('drift:max_age_seconds', 5000) o.fallback_values['x_sea_water_velocity'] = .5 o.fallback_values['y_sea_water_velocity'] = .3 o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=0, lat=60, number=10, time=[datetime.now(), datetime.now() + timedelta(seconds=6000)]) o.run(time_step=1000, duration=timedelta(seconds=7000)) self.assertEqual(o.num_elements_deactivated(), 5) def test_outside_domain(self): o = OceanDrift(loglevel=50) reader_osc_x = reader_oscillating.Reader( 'x_sea_water_velocity', amplitude=1, zero_time=datetime.now()) reader_osc_y = reader_oscillating.Reader( 'y_sea_water_velocity', amplitude=1, zero_time=datetime.now()) o.add_reader([reader_osc_x, reader_osc_y]) o.set_config('drift:deactivate_east_of', 2.1) o.set_config('drift:deactivate_west_of', 1.9) o.set_config('drift:deactivate_south_of', 59.9) o.set_config('drift:deactivate_north_of', 60.1) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon=2, lat=60, number=1000, time=datetime.now(), radius=10000) o.run(duration=timedelta(hours=5)) self.assertEqual(o.num_elements_deactivated(), 768) self.assertEqual(o.num_elements_active(), 232) def test_seed_time_backwards_run(self): o = OceanDrift(loglevel=20) o.set_config('drift:max_age_seconds', 2000) o.fallback_values['x_sea_water_velocity'] = .5 o.fallback_values['y_sea_water_velocity'] = .3 o.fallback_values['land_binary_mask'] = 0 time = [datetime(2018,1,1,i) for i in range(10)] o.seed_elements(lon=0, lat=60, time=time) o.seed_elements(lon=1, lat=60, time=datetime(2018,1,1,7)) o.run(end_time=datetime(2018,1,1,2), time_step=-1800) self.assertEqual(o.num_elements_scheduled(), 3) self.assertEqual(o.num_elements_active(), 8) self.assertEqual(o.steps_calculation, 14) def test_oil_mixed_to_seafloor(self): o = OpenOil3D(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader(norkyst) o.set_config('processes:evaporation', False) o.fallback_values['x_wind'] = 25 o.fallback_values['y_wind'] = 0 o.fallback_values['land_binary_mask'] = 0 o.fallback_values['ocean_vertical_diffusivity'] = 0.9 o.seed_elements(lon=5.38, lat=62.77, time=norkyst.start_time, number=100, radius=5000) o.run(end_time=norkyst.end_time) self.assertEqual(o.num_elements_active(), 100) def test_unseeded_elements(self): o = PlastDrift() # Seeding elements for 12 hours, but running only 6 time = datetime(2019, 8, 30, 12) o.seed_elements(lon=4.85, lat=60, number=10, time=[time, time + timedelta(hours=6)], origin_marker=7) o.seed_elements(lon=4.75, lat=60, number=10, time=[time, time + timedelta(hours=6)], origin_marker=8) o.fallback_values['land_binary_mask'] = 0 o.fallback_values['y_sea_water_velocity'] = 1 o.run(duration=timedelta(hours=3)) self.assertEqual(o.history.shape[0], 10) self.assertEqual(o.history.shape[1], 4) self.assertEqual(o.history['origin_marker'].min(), 7) self.assertEqual(o.history['origin_marker'].max(), 8)
from opendrift.readers import reader_basemap_landmask from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') time = reader_norkyst.start_time reader_norkyst.interpolation = 'linearND' reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=4, llcrnrlat=59.9, urcrnrlon=5.5, urcrnrlat=61.5, resolution='h') o.add_reader([reader_norkyst, reader_basemap]) lon = 4.5; lat = 60.0; # First run, with Euler scheme: o.set_config('drift:scheme', 'euler') o.seed_elements(lon, lat, radius=0, number=1, time=time) o.run(steps=66*2, time_step=1800) # Second run, with Runge-Kutta scheme: o2 = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information o2.add_reader([reader_norkyst, reader_basemap]) o2.set_config('drift:scheme', 'runge-kutta') o2.seed_elements(lon, lat, radius=0, number=1, time=time) o2.run(steps=66*2, time_step=1800) # Animate and compare the two runs
from opendrift.readers import reader_ROMS_native from opendrift.readers import reader_oscillating from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=0) # Set loglevel to 0 for debug information # Adding nordic reader for coastline reader_nordic = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') reader_nordic.variables = ['land_binary_mask'] reader_osc = reader_oscillating.Reader('x_sea_water_velocity', amplitude=1, zero_time=reader_nordic.start_time) o.add_reader([reader_osc]) # Oscillating east-west current component o.fallback_values['y_sea_water_velocity'] = .2 # Adding northwards drift o.set_config('general:basemap_resolution', 'i') ########################################################## # Try different options: 'previous', 'stranding', 'none' o.set_config('general:coastline_action', 'previous') ########################################################## time = reader_osc.zero_time lon = 12.2; lat = 67.7 o.seed_elements(lon, lat, radius=5000, number=15, time=time) o.run(steps=36*4, time_step=900)
# Demonstrating how the spatial resolution of # fields from a reader mey be reduced from datetime import datetime, timedelta import matplotlib.pyplot as plt from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift lon = 4.9; lat = 60.0 o = OceanDrift() reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') time = reader_norkyst.start_time o.add_reader([reader_norkyst]) o.seed_elements(lon, lat, radius=1000, number=1000, time=time) o.run(steps=20) # Store final field of x-component of current original_current = reader_norkyst.var_block_after["['y_sea_water_velocity', 'x_sea_water_velocity']"].data_dict['x_sea_water_velocity'].copy() # For the second run, the NorKyst currents are convolved with a kernel, # effectively lowering the spatial resolution. # <reader>.convolve may also be given as an array (kernel) directly N = 10 # Convolusion kernel size reader_norkyst.convolve = N # Using convolution kernel for second run o2 = OceanDrift() o2.add_reader([reader_norkyst]) o2.seed_elements(lon, lat, radius=1000, number=1000, time=time) o2.run(steps=20)
#!/usr/bin/env python """ Advection schemes ================= Illustrating the difference between Euler and Runge-Kutta propagation schemes, using an idealised (analytical) eddy current field. """ from datetime import datetime, timedelta from opendrift.readers import reader_ArtificialOceanEddy from opendrift.models.oceandrift import OceanDrift fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) runs = [] leg = [] for scheme in ['euler', 'runge-kutta', 'runge-kutta4']: for time_step in [1800, 3600 * 3]: leg.append(scheme + ', T=%.1fh' % (time_step / 3600.)) print(leg[-1]) o = OceanDrift(loglevel=50) o.fallback_values['land_binary_mask'] = 0 o.set_config('drift:scheme', scheme) o.add_reader(fake_eddy) o.seed_elements(lon=2.0, lat=63.0, time=datetime.utcnow()) o.set_config('drift:vertical_mixing', False) o.run(duration=timedelta(days=9), time_step=time_step) runs.append(o) runs[0].plot(compare=runs[1:], legend=leg, fast=True, buffer=.3)
def test_plot(tmpdir): anifile = os.path.join(tmpdir, 'anim.mp4') plotfile = os.path.join(tmpdir, 'plot.png') #anifile = None #plotfile = None o = OceanDrift(loglevel=30) rn = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o.add_reader(rn) o.seed_elements(lon=4.8, lat=60.0, number=10, radius=1000, time=rn.start_time) o.run(steps=5) # Making figures/animations o.plot(filename=plotfile, fast=True, background=['x_sea_water_velocity', 'y_sea_water_velocity']) o.animation(color='lat', filename=anifile, show_trajectories=True, fast=True) o.animation(density=True, filename=anifile, show_trajectories=True, fast=True) o.animation(filename=anifile, show_trajectories=True, fast=True) o.animation(filename=anifile, fast=True, background=['x_sea_water_velocity', 'y_sea_water_velocity']) o.plot(filename=plotfile, fast=True, linecolor='lat') o.plot(filename=plotfile, fast=False) # Second run for comparison o2 = OceanDrift(loglevel=30) o2.add_reader(rn) o2.fallback_values['x_wind'] = 15 # Adding wind o2.fallback_values['y_wind'] = 0 o2.seed_elements(lon=4.8, lat=60.0, number=10, radius=1000, time=rn.start_time) o2.run(steps=5) o.animation(filename=anifile, compare=o2, fast=True, legend=['No wind', '10 m/s wind']) o.plot(filename=plotfile, compare=o2, fast=True, legend=['No wind', '10 m/s wind']) # Check that files have been written assert os.path.exists(anifile) assert os.path.exists(plotfile)
ROMS native reader ================================== """ import numpy as np from opendrift.readers import reader_ROMS_native from opendrift.models.oceandrift import OceanDrift o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information #%% # Creating and adding reader for Nordic 4km current dataset nordic_native = reader_ROMS_native.Reader( o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') o.add_reader(nordic_native) #%% # Seed elements at defined positions, depth and time o.seed_elements(lon=12.0, lat=68.3, radius=0, number=10, z=np.linspace(0, -150, 10), time=nordic_native.start_time) #%% # Running model o.run(time_step=3600) #%%
o = OceanDrift(loglevel=20) # Set loglevel to 0 for debug information # Norkyst #reader_norkyst = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/sea/norkyst800m/1h/aggregate_be') reader_norkyst = reader_netCDF_CF_generic.Reader( o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') #reader_norkyst = reader_netCDF_CF_generic.Reader('test_data/16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') # Landmask reader_landmask = reader_global_landmask.Reader(llcrnrlon=3.5, llcrnrlat=59.9, urcrnrlon=5.5, urcrnrlat=61.2) o.add_reader([reader_landmask, reader_norkyst]) # Seeding particles in a checkerboard pattern di = 5 # Horizontal number of particles per square dj = 5 # Vertical number of particles per square lons = np.linspace(3.5, 5.0, 100) lats = np.linspace(60, 61, 100) ii = np.arange(len(lons)) // di jj = np.arange(len(lats)) // dj ii, jj = np.meshgrid(ii, jj) board = (ii + jj) % 2 > 0 lons, lats = np.meshgrid(lons, lats) lons = lons[board].ravel()
from opendrift.readers import reader_netCDF_CF_generic from opendrift.models.oceandrift import OceanDrift o = OceanDrift() # Basic drift model suitable for passive tracers or drifters ####################### # Preparing Readers ####################### reader_current = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') reader_wind = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') o.add_reader([reader_current, reader_wind]) ####################### # Seeding elements ####################### # Elements are moved with the ocean current, in addition to a fraction of # the wind speed (wind_drift_factor). This factor depends on the properties # of the elements. Typical empirical values are: # - 0.035 (3.5 %) for oil and iSphere driftes # - 0.01 (1 %) for CODE drifters partly submerged ~0.5 m # As there are large uncertainties, it makes sence to provide a statistical # distribution of wind_drift_factors # Using a constant value for all elements: #wind_drift_factor = 0.03
class TestRun(unittest.TestCase): """Tests for (non-scalar) LagrangianArray""" def make_OceanDrift_object(self): self.o = OceanDrift(loglevel=30) self.fake_eddy = reader_ArtificialOceanEddy.Reader(2, 62) self.o.use_block = False self.reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=-1.5, llcrnrlat=59, urcrnrlon=7, urcrnrlat=64, resolution='c') self.o.add_reader([self.fake_eddy, self.reader_basemap]) def test_seed(self): """Test seeding""" o = OceanDrift(loglevel=20) number = 3 lonvec = np.linspace(2, 5, number) latvec = np.linspace(60, 61, number) o.seed_elements(lonvec, latvec, number=number, time=datetime(2015, 1, 1, 12, 5, 17)) #time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.num_elements_active(), 0) self.assertEqual(o.num_elements_activated(), 0) self.assertEqual(o.num_elements_deactivated(), 0) self.assertEqual(o.num_elements_total(), number) def test_seed_outside_coverage(self): """Test seeding""" o = OpenOil3D(loglevel=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4, llcrnrlat=60, urcrnrlon=6, urcrnrlat=64, resolution='c', projection='merc') o.add_reader([basemap, norkyst]) o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.seed_elements(5, 63, number=5, time=norkyst.start_time - 24*timedelta(hours=24)) with self.assertRaises(ValueError): o.run(steps=3, time_step=timedelta(minutes=15)) def test_runge_kutta(self): number = 50 # With Euler o = OceanDrift3D(loglevel=20, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.add_reader([norkyst]) z=-40*np.random.rand(number) o.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o.run(steps=4*3, time_step=timedelta(minutes=15)) # With Runge-Kutta o2 = OceanDrift3D(loglevel=20, seed=0) o2.fallback_values['land_binary_mask'] = 0 o2.add_reader([norkyst]) z=-40*np.random.rand(number) o2.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o2.set_config('drift:scheme', 'runge-kutta') o2.run(steps=4*3, time_step=timedelta(minutes=15)) # And finally repeating the initial run to check that indetical o3 = OceanDrift3D(loglevel=20, seed=0) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o3.fallback_values['land_binary_mask'] = 0 o3.add_reader([norkyst]) z=-40*np.random.rand(number) o3.seed_elements(5, 62.5, number=number, radius=5000, z=z, time=norkyst.start_time) o3.run(steps=4*3, time_step=timedelta(minutes=15)) # Check that we get some difference with Runge-Kutta: self.assertAlmostEqual((o2.elements.lon-o.elements.lon).max(), 0.0015, 3) # Check that runs with Euler are identical self.assertEqual((o3.elements.lon-o.elements.lon).max(), 0) def test_seed_polygon(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=datetime(2015, 1, 1, 12, 5, 17) o.seed_within_polygon(lonvec, latvec, number=number, time=time, wind_drift_factor=.09) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time) self.assertAlmostEqual(o.elements_scheduled.wind_drift_factor, .09) def test_seed_polygon_timespan(self): o = OceanDrift(loglevel=20) number = 10 lonvec = np.array([2, 3, 3, 2]) latvec = np.array([60, 60, 61, 61]) time=[datetime(2015, 1, 1, 12, 5, 17), datetime(2015, 1, 1, 18, 5, 17)] o.seed_within_polygon(lonvec, latvec, number=number, time=time) self.assertEqual(o.num_elements_scheduled(), number) self.assertEqual(o.elements_scheduled_time[0], time[0]) self.assertEqual(o.elements_scheduled_time[-1], time[-1]) @unittest.skipIf(has_ogr is False, 'OGR library needed to read shapefiles') def test_seed_shapefile(self): o = OceanDrift(loglevel=20) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=100, layername=None, featurenum=[2, 4], time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 100) o.seed_from_shapefile(o.test_data_folder() + 'shapefile_spawning_areas/Torsk.shp', number=300, layername=None, featurenum=None, time=datetime.now()) self.assertEqual(len(o.elements_scheduled), 400) #@unittest.skipIf(has_ogr is False, # 'GDAL library needed to read shapefiles') #def test_write_geotiff(self): # o = OceanDrift(loglevel=20) # o.seed_elements(lon=4, lat=60, time=datetime(2016, 1, 1)) # o.run(steps=3) # o.write_geotiff('geotiff.tif') def test1_seed_single_point_over_time(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements(2.0, 61.0, radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 5) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) def test2_seed_elements(self): """Test a model run""" self.make_OceanDrift_object() self.o.seed_elements([2.0, 5.0, 3.0], [61.0, 60.0, 62.0], radius=0, number=9, time=[datetime(2015, 1, 1), datetime(2015, 1, 3)]) # Check that 6 elements are scheduled, but none seeded self.assertEqual(self.o.num_elements_scheduled(), 9) self.assertEqual(self.o.num_elements_active(), 0) self.assertEqual(self.o.num_elements_activated(), 0) self.assertEqual(self.o.num_elements_deactivated(), 0) self.assertEqual(self.o.num_elements_total(), 9) # Run simulation self.o.run(steps=30, outfile='unittest.nc') # Check that 1 element is deactivated (stranded), # 1 yet not seeded and 4 active self.assertEqual(self.o.num_elements_scheduled(), 4) self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 9) def test3_run_import(self): """Import output file from previous test, and check elements""" self.o = OceanDrift(loglevel=20) self.o.io_import_file('unittest.nc') self.assertEqual(self.o.num_elements_active(), 4) self.assertEqual(self.o.num_elements_activated(), 5) self.assertEqual(self.o.num_elements_deactivated(), 1) self.assertEqual(self.o.num_elements_total(), 5) def test4_cleaning(self): """Cleaning up""" os.remove('unittest.nc') def test_temporal_seed(self): self.o = OceanDrift(loglevel=20) self.o.fallback_values['x_sea_water_velocity'] = 1 self.o.fallback_values['land_binary_mask'] = 0 # Seed elements on a grid at regular time interval start_time = datetime(2016,9,16) time_step = timedelta(hours=6) num_steps = 10 lon = 4.4 lat = 60.0 for i in range(num_steps+1): self.o.seed_elements(lon, lat, radius=0, number=2, time=start_time + i*time_step) # Running model self.o.run(steps=20, time_step=3600, outfile='temporal_seed.nc') self.o = OceanDrift(loglevel=20) # Check that data imported is properly masked self.o.io_import_file('temporal_seed.nc') self.assertTrue(self.o.history['lon'].max() < 1000) self.assertTrue(self.o.history['lon'].min() > -1000) self.assertTrue(self.o.history['lon'].mask[5,5]) self.assertFalse(self.o.history['lon'].mask[1,1]) os.remove('temporal_seed.nc') def test_vertical_mixing(self): # Export to file only at end o1 = PelagicEggDrift(loglevel=20) # Profiles and vertical mixing norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o1.add_reader([norkyst]) o1.fallback_values['x_wind'] = 8 o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.1, 63.3, radius=1000, number=100, time=norkyst.start_time) o1.set_config('turbulentmixing:timestep', 20.) # seconds o1.set_config('turbulentmixing:verticalresolution', 1.) # m o1.run(steps=20, time_step=300, time_step_output=1800, export_buffer_length=10, outfile='verticalmixing.nc') self.assertAlmostEqual(o1.history['z'].min(), -31.9, 1) self.assertAlmostEqual(o1.history['z'].max(), 0.0, 1) os.remove('verticalmixing.nc') def test_export_step_interval(self): # Export to file only at end o1 = OceanDrift(loglevel=20) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') o1.add_reader(norkyst) o1.fallback_values['land_binary_mask'] = 0 o1.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o1.run(steps=40) # Export to file during simulation o2 = OceanDrift(loglevel=20) o2.add_reader(norkyst) o2.fallback_values['land_binary_mask'] = 0 o2.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o2.run(steps=40, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) # Finally check when steps is multiple of export_buffer_length o3 = OceanDrift(loglevel=20) o3.add_reader(norkyst) o3.fallback_values['land_binary_mask'] = 0 o3.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o3.run(steps=42) # Export to file during simulation o4 = OceanDrift(loglevel=20) o4.add_reader(norkyst) o4.fallback_values['land_binary_mask'] = 0 o4.seed_elements(4.25, 60.2, radius=1000, number=10, time=norkyst.start_time) o4.run(steps=42, export_buffer_length=6, outfile='export_step_interval.nc') self.assertItemsEqual(o3.history['lon'].compressed(), o4.history['lon'].compressed()) os.remove('export_step_interval.nc') def test_buffer_length_stranding(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4.5, llcrnrlat=60.1, urcrnrlon=6.0, urcrnrlat=60.4, resolution='c', projection='merc') o1.add_reader([basemap]) o1.fallback_values['x_sea_water_velocity'] = 0.8 # onshore drift o1.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o1.run(steps=100, time_step=900, time_step_output=3600, export_buffer_length=10) # Without buffer o2 = OceanDrift(loglevel=30) o2.add_reader([basemap]) o2.fallback_values['x_sea_water_velocity'] = 0.8 # onshore drift o2.seed_elements(4.8, 60.2, radius=5000, number=100, time=norkyst.start_time) o2.run(steps=100, time_step=900, time_step_output=3600, outfile='test_buffer_length_stranding.nc') self.assertItemsEqual(o1.history['lon'].compressed(), o2.history['lon'].compressed()) self.assertItemsEqual(o1.history['status'].compressed(), o2.history['status'].compressed()) os.remove('test_buffer_length_stranding.nc') def test_output_time_step(self): o1 = OceanDrift(loglevel=30) norkyst = reader_netCDF_CF_generic.Reader(o1.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=4.5, llcrnrlat=60.0, urcrnrlon=5.2, urcrnrlat=60.5, resolution='i', projection='merc') o1.add_reader([basemap, norkyst]) o1.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o1.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=30), outfile='test_time_step30.nc') # Check length of time array and output array time = o1.get_time_array()[0] self.assertEqual(o1.history.shape[1], len(time)) self.assertEqual(o1.start_time, time[0]) self.assertEqual(o1.time, time[-1]) # Second run, with larger output time step o2 = OceanDrift(loglevel=30) o2.add_reader([basemap, norkyst]) o2.seed_elements(4.96, 60.1, radius=3000, number=100, time=norkyst.start_time) o2.run(duration=timedelta(hours=12), time_step=timedelta(minutes=30), time_step_output=timedelta(minutes=60), outfile='test_time_step60.nc') self.assertEqual(o1.history.shape, (100,25)) self.assertEqual(o2.history.shape, (100,13)) # Check that start and end conditions (longitudes) are idential self.assertItemsEqual(o1.history['lon'][:,24].compressed(), o2.history['lon'][:,12].compressed()) self.assertItemsEqual(o1.history['lon'][:,0].compressed(), o2.history['lon'][:,0].compressed()) # Check that also run imported from file is identical o1i = OceanDrift(loglevel=20) o1i.io_import_file('test_time_step30.nc') o2i = OceanDrift(loglevel=20) o2i.io_import_file('test_time_step60.nc') os.remove('test_time_step30.nc') os.remove('test_time_step60.nc') self.assertItemsEqual(o2i.history['lon'][:,12].compressed(), o2.history['lon'][:,12].compressed()) # Check number of activated elements self.assertEqual(o1.num_elements_total(), o2.num_elements_total()) self.assertEqual(o1.num_elements_total(), o1i.num_elements_total()) self.assertEqual(o1.num_elements_total(), o2i.num_elements_total()) # Check number of deactivated elements self.assertEqual(o1.num_elements_deactivated(), o2.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o1i.num_elements_deactivated()) self.assertEqual(o1.num_elements_deactivated(), o2i.num_elements_deactivated()) def test_reader_boundary(self): # Check that the element outside reader coverage is # not deactivated if fallback value exist o = OceanDrift() nordic3d = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') lon = [12.0, 12.0] lat = [70.0, 70.5] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 2) self.assertEqual(o.num_elements_deactivated(), 0) # Check that the outside element is deactivated, # if no fallback value exists o = OceanDrift() del o.fallback_values['x_sea_water_velocity'] o.add_reader(nordic3d) o.fallback_values['land_binary_mask'] = 0 o.seed_elements(lon, lat, number=2, radius=0, time=nordic3d.start_time) o.run(steps=2, time_step=3600) self.assertEqual(o.num_elements_active(), 1) self.assertEqual(o.num_elements_deactivated(), 1) def test_reader_order(self): # Check that we get the same output indepenently of reader order o = OceanDrift(loglevel=50) norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') arome = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') basemap = reader_basemap_landmask.Reader( llcrnrlon=2, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='c', projection='merc') lon=4.; lat=60. # First run o.add_reader([basemap, norkyst, arome]) o.seed_elements(lon, lat, time=norkyst.start_time) o.run(steps=30) # Second run # Check that we get almost identical results with other projection o1 = OceanDrift(loglevel=50) o1.add_reader([norkyst, arome, basemap]) o1.seed_elements(lon, lat, time=norkyst.start_time) o1.run(steps=30) self.assertAlmostEqual(o.elements.lon, o1.elements.lon, 2) self.assertAlmostEqual(o.elements.lat, o1.elements.lat, 2) # Third run # Check that this is identical to run 1 if projection set equal o2 = OceanDrift(loglevel=50) o2.add_reader([norkyst, arome, basemap]) o2.seed_elements(lon, lat, time=norkyst.start_time) o2.set_projection(basemap.proj4) o2.run(steps=30) self.assertEqual(o.elements.lon, o2.elements.lon) def test_seed_seafloor(self): o = OpenOil3D(loglevel=30) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 o.add_reader([reader_norkyst]) lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z='seafloor', time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -91.3, 1) # After some rising def test_seed_above_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 o.add_reader([reader_norkyst]) lon = 4.5; lat = 62.0 # Seed elements 50 meters above seafloor: o.seed_elements(lon, lat, z='seafloor+50', time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.run(steps=3, time_step=300, time_step_output=300) #o.plot_property('z') z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -101.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -41.7, 1) # After some rising def test_seed_below_reader_coverage(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.add_reader([reader_norkyst]) lon = 5.0; lat = 64.0 o.seed_elements(lon, lat, z=-350, time=reader_norkyst.start_time, density=1000) #o.set_config('turbulentmixing:TSprofiles', True) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[-1,0], -289.2, 1) # After some rising def test_seed_below_seafloor(self): o = OpenOil3D(loglevel=20) reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') o.add_reader([reader_norkyst]) o.fallback_values['land_binary_mask'] = 0 o.fallback_values['x_wind'] = 0 o.fallback_values['y_wind'] = 0 o.fallback_values['x_sea_water_velocity'] = 0 o.fallback_values['y_sea_water_velocity'] = 0 lon = 4.5; lat = 62.0 o.seed_elements(lon, lat, z=-5000, time=reader_norkyst.start_time, density=1000) o.set_config('processes:turbulentmixing', True) o.set_config('turbulentmixing:verticalresolution', 1) # m o.set_config('turbulentmixing:timestep', 1) # s o.set_config('input:spill:droplet_diameter_min_subsea', 0.005) o.set_config('input:spill:droplet_diameter_max_subsea', 0.005) o.run(steps=3, time_step=300, time_step_output=300) z, status = o.get_property('z') self.assertAlmostEqual(z[0,0], -151.7, 1) # Seeded at seafloor depth self.assertAlmostEqual(z[-1,0], -91.3, 1) # After some rising def test_lift_above_seafloor(self): # See an element at some depth, and progapate towards coast # (shallower water) and check that it is not penetrating seafloor o = OceanDrift3D(loglevel=30, proj4='+proj=merc') o.max_speed = 100 reader_norkyst = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') reader_norkyst.buffer = 200 o.add_reader([reader_norkyst], variables='sea_floor_depth_below_sea_level') o.fallback_values['x_sea_water_velocity'] = 100 # Pure eastward motion o.fallback_values['y_sea_water_velocity'] = 0 o.fallback_values['land_binary_mask'] = 0 o.seed_elements(3.0, 62.0, z=-200, time=reader_norkyst.start_time) o.set_config('processes:turbulentmixing', False) o.run(steps=26, time_step=30) seafloor_depth, status = o.get_property('sea_floor_depth_below_sea_level') z, status = o.get_property('z') # Uncomment to plot #import matplotlib.pyplot as plt #plt.plot(-seafloor_depth, label='Seafloor depth') #plt.plot(z, label='Element depth') #plt.legend(loc='best') #plt.show() # Check that element has not penetrated seafloor self.assertFalse(o.elements.z < -o.environment.sea_floor_depth_below_sea_level) self.assertAlmostEqual(o.elements.z, -160.06, 1) def test_seed_on_land(self): o = OceanDrift(loglevel=0) o.set_config('general:basemap_resolution', 'c') o.seed_elements(lon=9, lat=60, time=datetime.now(), number=100) outfile='out.nc' with self.assertRaises(ValueError): o.run(steps=4, time_step=1800, time_step_output=3600, outfile=outfile) os.remove(outfile)
####################### # Preparing Readers ####################### reader_current = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/norkyst800_subset_16Nov2015.nc') reader_wind = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '16Nov2015_NorKyst_z_surface/arome_subset_16Nov2015.nc') # Landmask (Basemap) reader_basemap = reader_basemap_landmask.Reader( llcrnrlon=4, llcrnrlat=59.8, urcrnrlon=6, urcrnrlat=61, resolution='h', projection='merc') o.add_reader([reader_basemap, reader_current, reader_wind]) ####################### # Seeding elements ####################### # Elements are moved with the ocean current, in addition to a fraction of # the wind speed (wind_drift_factor). This factor depends on the properties # of the elements. Typical empirical values are: # - 0.035 (3.5 %) for oil and iSphere driftes # - 0.01 (1 %) for CODE drifters partly submerged ~0.5 m # As there are large uncertainties, it makes sence to provide a statistical # distribution of wind_drift_factors # Using a constant value for all elements: #wind_drift_factor = 0.03
#!/usr/bin/env python from datetime import timedelta import numpy as np from opendrift.models.oceandrift import OceanDrift from opendrift.readers import reader_netCDF_CF_generic # Drift simulation using 10 member ensemble wind data # from MEPS model of MET Norway o = OceanDrift() r = reader_netCDF_CF_generic.Reader('http://thredds.met.no/thredds/dodsC/meps25files/meps_allmembers_extracted_2_5km_latest.nc') o.add_reader(r) #o.set_config('general:basemap_resolution', 'c') o.seed_elements(lat=60, lon=4.8, time=r.start_time, radius=1000, number=10000) o.run(duration=timedelta(hours=50), time_step=3600) # Ensemble members are recycled among the 10000 particles ensemble_number = np.remainder(o.history['ID'], 10) + 1 o.animation(filename='wind_drift_ensemble.mp4', color=ensemble_number, clabel='Ensemble number')