def test_avoid_repeated_grids(): lon_g0 = np.linspace(0, 1000, 11, dtype=np.float32) lat_g0 = np.linspace(0, 1000, 11, dtype=np.float32) time_g0 = np.linspace(0, 1000, 2, dtype=np.float64) grid_0 = RectilinearZGrid(lon_g0, lat_g0, time=time_g0) lon_g1 = np.linspace(0, 1000, 21, dtype=np.float32) lat_g1 = np.linspace(0, 1000, 21, dtype=np.float32) time_g1 = np.linspace(0, 1000, 2, dtype=np.float64) grid_1 = RectilinearZGrid(lon_g1, lat_g1, time=time_g1) u_data = np.zeros((lon_g0.size, lat_g0.size, time_g0.size), dtype=np.float32) u_field = Field('U', u_data, grid=grid_0, transpose=True) v_data = np.zeros((lon_g1.size, lat_g1.size, time_g1.size), dtype=np.float32) v_field = Field('V', v_data, grid=grid_1, transpose=True) temp0_field = Field('temp', u_data, lon=lon_g0, lat=lat_g0, time=time_g0, transpose=True) other_fields = {} other_fields['temp'] = temp0_field field_set = FieldSet(u_field, v_field, fields=other_fields) assert field_set.gridset.size == 2 assert field_set.U.grid is field_set.temp.grid assert field_set.V.grid is not field_set.U.grid
def test_fieldset_defer_loading_with_diff_time_origin(tmpdir, fail, filename='test_parcels_defer_loading'): filepath = tmpdir.join(filename) data0, dims0 = generate_fieldset(10, 10, 1, 10) dims0['time'] = np.arange(0, 10, 1) * 3600 fieldset_out = FieldSet.from_data(data0, dims0) fieldset_out.U.grid.time_origin = TimeConverter(np.datetime64('2018-04-20')) fieldset_out.V.grid.time_origin = TimeConverter(np.datetime64('2018-04-20')) data1, dims1 = generate_fieldset(10, 10, 1, 10) if fail: dims1['time'] = np.arange(0, 10, 1) * 3600 else: dims1['time'] = np.arange(0, 10, 1) * 1800 + (24+25)*3600 if fail: Wtime_origin = TimeConverter(np.datetime64('2018-04-22')) else: Wtime_origin = TimeConverter(np.datetime64('2018-04-18')) gridW = RectilinearZGrid(dims1['lon'], dims1['lat'], dims1['depth'], dims1['time'], time_origin=Wtime_origin) fieldW = Field('W', np.zeros(data1['U'].shape), grid=gridW) fieldset_out.add_field(fieldW) fieldset_out.write(filepath) fieldset = FieldSet.from_parcels(filepath, extra_fields={'W': 'W'}) assert fieldset.U.creation_log == 'from_parcels' pset = ParticleSet.from_list(fieldset, pclass=JITParticle, lon=[0.5], lat=[0.5], depth=[0.5], time=[datetime.datetime(2018, 4, 20, 1)]) pset.execute(AdvectionRK4_3D, runtime=delta(hours=4), dt=delta(hours=1))
def test_fieldKh_Brownian(mesh, mode, xdim=200, ydim=100, kh_zonal=100, kh_meridional=50): mesh_conversion = 1/1852./60 if mesh is 'spherical' else 1 fieldset = zeros_fieldset(mesh=mesh, xdim=xdim, ydim=ydim, mesh_conversion=mesh_conversion) vec = np.linspace(-1e5*mesh_conversion, 1e5*mesh_conversion, 2) grid = RectilinearZGrid(lon=vec, lat=vec, mesh=mesh) fieldset.add_field(Field('Kh_zonal', kh_zonal*np.ones((2, 2)), grid=grid)) fieldset.add_field(Field('Kh_meridional', kh_meridional*np.ones((2, 2)), grid=grid)) npart = 1000 runtime = delta(days=1) random.seed(1234) pset = ParticleSet(fieldset=fieldset, pclass=ptype[mode], lon=np.zeros(npart), lat=np.zeros(npart)) pset.execute(pset.Kernel(BrownianMotion2D), runtime=runtime, dt=delta(hours=1)) expected_std_lon = np.sqrt(2*kh_zonal*mesh_conversion**2*runtime.total_seconds()) expected_std_lat = np.sqrt(2*kh_meridional*mesh_conversion**2*runtime.total_seconds()) lats = np.array([p.lat for p in pset]) lons = np.array([p.lon for p in pset]) tol = 200*mesh_conversion # effectively 200 m errors assert np.allclose(np.std(lats), expected_std_lat, atol=tol) assert np.allclose(np.std(lons), expected_std_lon, atol=tol) assert np.allclose(np.mean(lons), 0, atol=tol) assert np.allclose(np.mean(lats), 0, atol=tol)
def test_fieldKh_SpatiallyVaryingBrownianMotion(mesh, mode, xdim=200, ydim=100): """Test SpatiallyVaryingDiffusion on a non-uniform diffusivity field with a linear gradient in one direction""" mesh_conversion = 1/1852./60 if mesh == 'spherical' else 1 fieldset = zeros_fieldset(mesh=mesh, xdim=xdim, ydim=ydim, mesh_conversion=mesh_conversion) Kh = np.zeros((ydim, xdim), dtype=np.float32) for x in range(xdim): Kh[:, x] = np.tanh(fieldset.U.lon[x]/fieldset.U.lon[-1]*10.)*xdim/2.+xdim/2. + 100. grid = RectilinearZGrid(lon=fieldset.U.lon, lat=fieldset.U.lat, mesh=mesh) fieldset.add_field(Field('Kh_zonal', Kh, grid=grid)) fieldset.add_field(Field('Kh_meridional', Kh, grid=grid)) npart = 100 runtime = delta(days=1) random.seed(1234) pset = ParticleSet(fieldset=fieldset, pclass=ptype[mode], lon=np.zeros(npart), lat=np.zeros(npart)) pset.execute(pset.Kernel(SpatiallyVaryingBrownianMotion2D), runtime=runtime, dt=delta(hours=1)) lats = np.array([p.lat for p in pset]) lons = np.array([p.lon for p in pset]) tol = 2000*mesh_conversion # effectively 2000 m errors (because of low numbers of particles) assert np.allclose(np.mean(lons), 0, atol=tol) assert np.allclose(np.mean(lats), 0, atol=tol) assert(stats.skew(lons) > stats.skew(lats))
def test_time_format_in_grid(): lon = np.linspace(0, 1, 2, dtype=np.float32) lat = np.linspace(0, 1, 2, dtype=np.float32) time = np.array([np.datetime64('2000-01-01')] * 2) RectilinearZGrid(lon, lat, time=time)
def test_multi_structured_grids(mode): def temp_func(lon, lat): return 20 + lat / 1000. + 2 * np.sin(lon * 2 * np.pi / 5000.) a = 10000 b = 10000 # Grid 0 xdim_g0 = 201 ydim_g0 = 201 # Coordinates of the test fieldset (on A-grid in deg) lon_g0 = np.linspace(0, a, xdim_g0, dtype=np.float32) lat_g0 = np.linspace(0, b, ydim_g0, dtype=np.float32) time_g0 = np.linspace(0., 1000., 2, dtype=np.float64) grid_0 = RectilinearZGrid(lon_g0, lat_g0, time=time_g0) # Grid 1 xdim_g1 = 51 ydim_g1 = 51 # Coordinates of the test fieldset (on A-grid in deg) lon_g1 = np.linspace(0, a, xdim_g1, dtype=np.float32) lat_g1 = np.linspace(0, b, ydim_g1, dtype=np.float32) time_g1 = np.linspace(0., 1000., 2, dtype=np.float64) grid_1 = RectilinearZGrid(lon_g1, lat_g1, time=time_g1) u_data = np.ones((lon_g0.size, lat_g0.size, time_g0.size), dtype=np.float32) u_data = 2 * u_data u_field = Field('U', u_data, grid=grid_0, transpose=True) temp0_data = np.empty((lon_g0.size, lat_g0.size, time_g0.size), dtype=np.float32) for i in range(lon_g0.size): for j in range(lat_g0.size): temp0_data[i, j, :] = temp_func(lon_g0[i], lat_g0[j]) temp0_field = Field('temp0', temp0_data, grid=grid_0, transpose=True) v_data = np.zeros((lon_g1.size, lat_g1.size, time_g1.size), dtype=np.float32) v_field = Field('V', v_data, grid=grid_1, transpose=True) temp1_data = np.empty((lon_g1.size, lat_g1.size, time_g1.size), dtype=np.float32) for i in range(lon_g1.size): for j in range(lat_g1.size): temp1_data[i, j, :] = temp_func(lon_g1[i], lat_g1[j]) temp1_field = Field('temp1', temp1_data, grid=grid_1, transpose=True) other_fields = {} other_fields['temp0'] = temp0_field other_fields['temp1'] = temp1_field field_set = FieldSet(u_field, v_field, fields=other_fields) def sampleTemp(particle, fieldset, time, dt): # Note that fieldset.temp is interpolated at time=time+dt. # Indeed, sampleTemp is called at time=time, but the result is written # at time=time+dt, after the Kernel update particle.temp0 = fieldset.temp0[time + dt, particle.lon, particle.lat, particle.depth] particle.temp1 = fieldset.temp1[time + dt, particle.lon, particle.lat, particle.depth] class MyParticle(ptype[mode]): temp0 = Variable('temp0', dtype=np.float32, initial=20.) temp1 = Variable('temp1', dtype=np.float32, initial=20.) pset = ParticleSet.from_list(field_set, MyParticle, lon=[3001], lat=[5001]) pset.execute(AdvectionRK4 + pset.Kernel(sampleTemp), runtime=1, dt=1) assert np.allclose(pset.particles[0].temp0, pset.particles[0].temp1, atol=1e-3)
def test_multi_structured_grids(pset_mode, mode): def temp_func(lon, lat): return 20 + lat / 1000. + 2 * np.sin(lon * 2 * np.pi / 5000.) a = 10000 b = 10000 # Grid 0 xdim_g0 = 201 ydim_g0 = 201 # Coordinates of the test fieldset (on A-grid in deg) lon_g0 = np.linspace(0, a, xdim_g0, dtype=np.float32) lat_g0 = np.linspace(0, b, ydim_g0, dtype=np.float32) time_g0 = np.linspace(0., 1000., 2, dtype=np.float64) grid_0 = RectilinearZGrid(lon_g0, lat_g0, time=time_g0) # Grid 1 xdim_g1 = 51 ydim_g1 = 51 # Coordinates of the test fieldset (on A-grid in deg) lon_g1 = np.linspace(0, a, xdim_g1, dtype=np.float32) lat_g1 = np.linspace(0, b, ydim_g1, dtype=np.float32) time_g1 = np.linspace(0., 1000., 2, dtype=np.float64) grid_1 = RectilinearZGrid(lon_g1, lat_g1, time=time_g1) u_data = np.ones((lon_g0.size, lat_g0.size, time_g0.size), dtype=np.float32) u_data = 2 * u_data u_field = Field('U', u_data, grid=grid_0, transpose=True) temp0_data = np.empty((lon_g0.size, lat_g0.size, time_g0.size), dtype=np.float32) for i in range(lon_g0.size): for j in range(lat_g0.size): temp0_data[i, j, :] = temp_func(lon_g0[i], lat_g0[j]) temp0_field = Field('temp0', temp0_data, grid=grid_0, transpose=True) v_data = np.zeros((lon_g1.size, lat_g1.size, time_g1.size), dtype=np.float32) v_field = Field('V', v_data, grid=grid_1, transpose=True) temp1_data = np.empty((lon_g1.size, lat_g1.size, time_g1.size), dtype=np.float32) for i in range(lon_g1.size): for j in range(lat_g1.size): temp1_data[i, j, :] = temp_func(lon_g1[i], lat_g1[j]) temp1_field = Field('temp1', temp1_data, grid=grid_1, transpose=True) other_fields = {} other_fields['temp0'] = temp0_field other_fields['temp1'] = temp1_field field_set = FieldSet(u_field, v_field, fields=other_fields) def sampleTemp(particle, fieldset, time): # Note that fieldset.temp is interpolated at time=time+dt. # Indeed, sampleTemp is called at time=time, but the result is written # at time=time+dt, after the Kernel update particle.temp0 = fieldset.temp0[time + particle.dt, particle.depth, particle.lat, particle.lon] particle.temp1 = fieldset.temp1[time + particle.dt, particle.depth, particle.lat, particle.lon] class MyParticle(ptype[mode]): temp0 = Variable('temp0', dtype=np.float32, initial=20.) temp1 = Variable('temp1', dtype=np.float32, initial=20.) pset = pset_type[pset_mode]['pset'].from_list(field_set, MyParticle, lon=[3001], lat=[5001], repeatdt=1) pset.execute(AdvectionRK4 + pset.Kernel(sampleTemp), runtime=3, dt=1) # check if particle xi and yi are different for the two grids # assert np.all([pset.xi[i, 0] != pset.xi[i, 1] for i in range(3)]) # assert np.all([pset.yi[i, 0] != pset.yi[i, 1] for i in range(3)]) assert np.alltrue([pset[i].xi[0] != pset[i].xi[1] for i in range(3)]) assert np.alltrue([pset[i].yi[0] != pset[i].yi[1] for i in range(3)]) # advect without updating temperature to test particle deletion pset.remove_indices(np.array([1])) pset.execute(AdvectionRK4, runtime=1, dt=1) assert np.alltrue([np.isclose(p.temp0, p.temp1, atol=1e-3) for p in pset])