Movers

Processes that change the position of the particles are termed “movers” in PyGNOME. These can include advection of the particles due to winds and currents, diffusive movement of particles due to unresolved (sub-grid scale) turbulent flow fields, and prescribed behavior of the particles (e.g. rise velocity of oil droplets). Many of the movers derive their data from Environment Objects, which represent the environment in which the model is running. The environment objects are queried for information (winds, currents) at the particle location in order to move the particle appropriately.

Some examples and common use cases are shown here. For comprehensive documentation see gnome.movers in the API Reference section.

Point Wind Mover

A gnome.movers.PointWindMover will act uniformly on elements anywhere in the domain (i.e. they have no spatial variability). These movers are tied to a Wind Object in the Environment Class.

For example, in that section, we saw how to create a simple spatially and temporally constant gnome.environment.Wind using a helper function in the gnome scripting module:

import gnome.scripting as gs
model = gs.Model(start_time="2023-03-03",
                 duration=gs.days(1),
                 time_step=gs.minutes(15)
                 )
wind = gs.constant_wind(10, 0, 'knots')

Now we create a gnome.movers.PointWindMover by passing the Wind Object to the Mover Class and adding it to the model:

w_mover = gs.PointWindMover(wind)
model.movers += w_mover

Even though we didn’t explicitly add the wind to the model environment, when the mover is added to the model, the wind object will also be added. Any weatherers subsequently added to the model will use that wind by default (see next section).

Some helper functions are available in gnome.scripting for creating wind movers. Many of these helper functions automatically create and add environment objects to the model. For example, to create a wind mover from a single point time series in a text file:

w_mover = gs.point_wind_mover_from_file('wind_file.txt')
model.movers += w_mover

The format of the text file is described in the GNOME File Formats section. Briefly, it has 3 header lines, followed by comma separated data. An example is given here with annotations in brackets at the end of the lines:

22NM W Forks WA *(Location name, can be blank)*
47.904000, -124.936000 *(Latitude, longitude, can be blank)*
knots *(Units, eg: knots,mph,kph,mps)*
3, 3, 2023, 12, 0, 14.00, 200 *(day, month, year, hour, minute, speed, direction)*
3, 3, 2023, 13, 0, 16.00, 190
3, 3, 2023, 14, 0, 16.00, 190

Gridded movers

An example of implementing a simple current mover with a uniform current was described in the scripting Overview. More commonly, currents used to move elements in GNOME originate from models on regular, curvilinear, or unstructured (triangular) grids, as output from oceanographic or meteorological models. Regardless of grid type, we use the gnome.movers.CurrentMover class.

Similarly, winds can be derived from gridded meteorological models using the gnome.movers.WindMover class.

These movers are tied to objects in the gnome.environment.Environment which were described more fully in the previous section. The primary supported format for gridded winds and currents is NetCDF. See the Gridded NetCDF formats section for more information.

Here’s an example of first building an environment object from a gridded wind:

fn = 'gridded_wind.nc'
wind = gs.GridWind.from_netCDF(filename=fn)
wind_mover = gs.WindMover(wind)
model.movers += wind_mover

The work flow is identical for adding a current. Alternatively, we could skip explicitly creating the environment object as the mover classes also have the “from_netCDF” method. For example:

fn = 'gridded_current.nc'
current_mover = gs.CurrentMover.from_netCDF(filename=fn)
model.movers += current_mover

In both cases, the corresponding environment object is also added to the model.

To use a current or wind in multiple files pass in a Python list with the file names:

file_list = ['day1.nc',
             'day2.nc',
             'day3.nc',
             'day4.nc',
             'day5.nc',
             'day6.nc',
             ]
current = gs.GridCurrent.from_netCDF(file_list)
current_mover = gs.CurrentMover(current=current)
model.movers += current_mover

The files must be in order and in netcdf3 format.

The default numerical method for the gridded movers is a 2nd-order Runge-Kutta. Other options are available by specifying the “default_num_method” when creating the mover object. For more information, see the gnome.movers.CurrentMover api documentation.

A note on 3D simulations

If a netCDF file contains currents at multiple depth levels along with 3-d grid information, the corresponding GridCurrent object will be built to include that information and full 3D simulations can be run. If only one depth level is included, it will be assumed to be the surface and used accordingly. Wind files should ideally only contain surface (assumed 10 m) winds.

Random movers

Randoms movers can be added to simulate both horizontal and vertical turbulent motions (for 3d simulations). Diffusion coefficients can be explicitly specified or default values will be used. For example:

import gnome.scripting as gs

random_mover = gs.RandomMover(diffusion_coef=10000) #in cm/s
model.movers += random_mover

#Or, for  a 3D simulation
random_mover_3d = gs.RandomMover3D(vertical_diffusion_coef_above_ml=10,vertical_diffusion_coef_below_ml=0.2,\
mixed_layer_depth=10, horizontal_diffusion_coef_above_ml=10000,\
horizontal_diffusion_coef_below_ml=100) #diffusion coefficients in cm/s, MLD in meters
model.movers += random_mover_3d

Rise velocity movers

The rise velocity mover depends on parameters specified when setting up a subsurface spill (see Spills). For example, the rise velocities can be calculated based on the droplet size for each element and the density of the specified oil. This information is associated with the spill object, hence creating a RiseVelocityMover is relatively simple.:

import gnome.scripting as gs

rise_vel_mover = gs.RiseVelocityMover()
model.movers += rise_vel_mover

A distribution of rise velocities can also be explicitly specified – again this is done when initializing the subsurface release. To make all elements have the same rise velocity, we specify a uniform distribution with the same value for high and low parameters. Various distributions are available in gnome.utilities.distributions.

Here’s a complete example where all elements will have a 1 m/s rise velocity:

import gnome.scripting as gs
from gnome.utilities.distributions import UniformDistribution

start_time = gs.asdatetime("2023-03-03")
model = gs.Model(start_time=start_time,
                 duration=gs.days(3),
                 time_step=60 * 15, #seconds
                 )
ud = UniformDistribution(1,1)
spill = gs.subsurface_spill(num_elements=1000,
                            start_position=(-144,48.5,-1000.0),
                            release_time=start_time,
                            distribution=ud,
                            distribution_type='rise_velocity',
                            end_release_time = start_time + gs.days(1),
                            amount=5000,
                            units='bbl',
                            name='My spill')
model.spills += spill

rise_vel_mover = gs.RiseVelocityMover()
model.movers += rise_vel_mover

model.full_run()

Ice modified movers

The presence of ice modifies the movement of the oil on the water surface. For example, in high ice concentrations, the oil may be encapsulated in the ice, and move with the ice drift velocity. To incorporate the presence of ice requires the creation of environment objects that include the relevant information (e.g., ice concentration and ice velocity along with currents and winds). We term these “IceAware” environment objects (see previous section for more detail). Once the environment objects have been created, movers can be created based on them using the same approach described above. For example:

ice_aware_current = gs.IceAwareCurrent.from_netCDF('file_with_currents_ice.nc')
ice_current_mover = gs.CurrentMover(ice_aware_current)

CATS Movers

CATS is a NOAA/ORR hydrodynamic model that is unlikley to be used by others. Documentation forthcoming. To see some examples for how to use CATS movers in a script see CATS currents.