In some oceanographic applications, you may want to advect particles using a combination of different velocity data sets. For example, particles at the surface are transported by a combination of geostrophic, Ekman and Stokes flow. And often, these flows are not even on the same grid.
One option would be to write a
Kernel that computes the movement of particles due to each of these flows. However, in Parcels it is possible to directly combine different flows (without interpolation) and feed them into the built-in
AdvectionRK4 kernel. For that, we use so-called
This tutorial shows how to use these
SummedField with a very idealised example. We start by importing the relevant modules.
%matplotlib inline from parcels import Field, FieldSet, ParticleSet, JITParticle, plotTrajectoriesFile, AdvectionRK4 import numpy as np
Now, let's first define a zonal and meridional velocity field on a 1kmx1km grid with a flat mesh. The zonal velocity is uniform and 1 m/s, and the meridional velocity is zero everywhere.
xdim, ydim = (10, 20) U = Field('U', np.ones((ydim, xdim), dtype=np.float32), lon=np.linspace(0., 1e3, xdim, dtype=np.float32), lat=np.linspace(0., 1e3, ydim, dtype=np.float32)) V = Field('V', np.zeros((ydim, xdim), dtype=np.float32), grid=U.grid) fieldset = FieldSet(U, V)
We then run a particle and plot its trajectory
pset = ParticleSet(fieldset, pclass=JITParticle, lon=, lat=) output_file = pset.ParticleFile(name='FieldListParticle_adv.nc', outputdt=1) pset.execute(AdvectionRK4, runtime=10, dt=1, output_file=output_file) plotTrajectoriesFile('FieldListParticle_adv.nc');
INFO: Compiled JITParticleAdvectionRK4 ==> /var/folders/r2/8593q8z93kd7t4j9kbb_f7p00000gr/T/parcels-504/95f68bdd3e2c61236f4287b88f438342.so 100% (10.0 of 10.0) |####################| Elapsed Time: 0:00:00 Time: 0:00:00
The trajectory plot shows a particle moving eastward on the 1 m/s flow, as expected
Now, let's define another set of velocities (
Ustokes, Vstokes) on a different, higher-resolution grid. This flow is southwestward at -0.2 m/s in each direction.
Note that it is very important to specify the
fieldtype of the fields, as Parcels will otherwise not perform the unit conversion correctly.
gf = 10 # factor by which the resolution of this grid is higher than of the original one. Ustokes = Field('Ustokes', -0.2*np.ones((ydim*gf, xdim*gf), dtype=np.float32), lon=np.linspace(0., 1e3, xdim*gf, dtype=np.float32), lat=np.linspace(0., 1e3, ydim*gf, dtype=np.float32), fieldtype='U') Vstokes = Field('Vstokes', -0.2*np.ones((ydim*gf, xdim*gf), dtype=np.float32), grid=Ustokes.grid, fieldtype='V')
Now comes the trick of the
SummedFields. We can simply define a new
FieldSet with a summation of different
Fields, as in
fieldset = FieldSet(U=U+Ustokes, V=V+Vstokes)
And if we then run the particle again and plot its trajectory, we see that it moves slightly southward too (and less far eastward), because of the Stokes drift.
pset = ParticleSet(fieldset, pclass=JITParticle, lon=, lat=) output_file = pset.ParticleFile(name='FieldListParticle_adv_stokes.nc', outputdt=1) pset.execute(AdvectionRK4, runtime=10, dt=1, output_file=output_file) plotTrajectoriesFile('FieldListParticle_adv_stokes.nc');
INFO: Compiled JITParticleAdvectionRK4 ==> /var/folders/r2/8593q8z93kd7t4j9kbb_f7p00000gr/T/parcels-504/8ba0de8db83dec9865083d5c33acfdb2.so 100% (10.0 of 10.0) |####################| Elapsed Time: 0:00:00 Time: 0:00:00
What happens under the hood is that each
Field in the
SummedField is interpolated separately to the particle location, and that the different velocities are added in each step of the RK4 advection. So
SummedFields are effortless to users
SummedFields work for any type of
Field, not only for velocities. Any call to a
Field interpolation (
fieldset.fld[time, lon, lat, depth]) will return the sum of all
Fields in the list if
fld is a