コード例 #1
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_mover_api():
    '''
    Test the API methods for adding and removing movers to the model.
    '''
    start_time = datetime(2012, 1, 1, 0, 0)

    model = Model()
    model.duration = timedelta(hours=12)
    model.time_step = timedelta(hours=1)
    model.start_time = start_time

    mover_1 = SimpleMover(velocity=(1., -1., 0.))
    mover_2 = SimpleMover(velocity=(1., -1., 0.))
    mover_3 = SimpleMover(velocity=(1., -1., 0.))
    mover_4 = SimpleMover(velocity=(1., -1., 0.))

    # test our add object methods

    model.movers += mover_1
    model.movers += mover_2

    # test our get object methods

    assert model.movers[mover_1.id] == mover_1
    assert model.movers[mover_2.id] == mover_2
    with raises(KeyError):
        temp = model.movers['Invalid']
        print temp

    # test our iter and len object methods
    assert len(model.movers) == 2
    assert len([m for m in model.movers]) == 2
    for (m1, m2) in zip(model.movers, [mover_1, mover_2]):
        assert m1 == m2

    # test our add objectlist methods
    model.movers += [mover_3, mover_4]
    assert [m for m in model.movers] == [mover_1, mover_2, mover_3, mover_4]

    # test our remove object methods
    del model.movers[mover_3.id]
    assert [m for m in model.movers] == [mover_1, mover_2, mover_4]

    with raises(KeyError):
        # our key should also be gone after the delete
        temp = model.movers[mover_3.id]
        print temp

    # test our replace method
    model.movers[mover_2.id] = mover_3
    assert [m for m in model.movers] == [mover_1, mover_3, mover_4]
    assert model.movers[mover_3.id] == mover_3

    with raises(KeyError):
        # our key should also be gone after the delete
        temp = model.movers[mover_2.id]
        print temp
コード例 #2
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_callback_add_mover():
    'Test callback after add mover'
    units = 'meter per second'

    model = Model()
    model.start_time = datetime(2012, 1, 1, 0, 0)
    model.duration = timedelta(hours=10)
    model.time_step = timedelta(hours=1)

    # start_loc = (1.0, 2.0, 0.0)  # random non-zero starting points

    # add Movers
    model.movers += SimpleMover(velocity=(1., -1., 0.))
    series = np.array((model.start_time, (10, 45)),
                      dtype=datetime_value_2d).reshape((1, ))
    model.movers += WindMover(Wind(timeseries=series, units=units))

    # this should create a Wind object
    new_wind = Wind(timeseries=series, units=units)
    model.environment += new_wind
    assert new_wind in model.environment
    assert len(model.environment) == 2

    tide_ = Tide(filename=testdata['CatsMover']['tide'])

    d_file = testdata['CatsMover']['curr']
    model.movers += CatsMover(d_file, tide=tide_)

    model.movers += CatsMover(d_file)

    for mover in model.movers:
        assert mover.active_start == inf_datetime.InfDateTime('-inf')
        assert mover.active_stop == inf_datetime.InfDateTime('inf')

        if hasattr(mover, 'wind'):
            assert mover.wind in model.environment

        if hasattr(mover, 'tide'):
            if mover.tide is not None:
                assert mover.tide in model.environment

    # Add a mover with user defined active_start / active_stop values
    # - these should not be updated

    active_on = model.start_time + timedelta(hours=1)
    active_off = model.start_time + timedelta(hours=4)
    custom_mover = SimpleMover(velocity=(1., -1., 0.),
                               active_start=active_on,
                               active_stop=active_off)
    model.movers += custom_mover

    assert model.movers[custom_mover.id].active_start == active_on
    assert model.movers[custom_mover.id].active_stop == active_off
コード例 #3
0
def test_simple_run_with_image_output_uncertainty(tmpdir):
    '''
    Pretty much all this tests is that the model will run and output images
    '''
    images_dir = tmpdir.mkdir('Test_images2').strpath

    if os.path.isdir(images_dir):
        shutil.rmtree(images_dir)
    os.mkdir(images_dir)

    start_time = datetime(2012, 9, 15, 12, 0)

    # the land-water map
    gmap = gnome.map.MapFromBNA(testdata['MapFromBNA']['testmap'],
                                refloat_halflife=6)  # hours
    renderer = gnome.outputters.Renderer(testdata['MapFromBNA']['testmap'],
                                         images_dir, size=(400, 300))

    model = Model(start_time=start_time,
                  time_step=timedelta(minutes=15), duration=timedelta(hours=1),
                  map=gmap,
                  uncertain=True, cache_enabled=False,
                  )

    model.outputters += renderer
    a_mover = SimpleMover(velocity=(1., -1., 0.))
    model.movers += a_mover

    N = 10  # a line of ten points
    start_points = np.zeros((N, 3), dtype=np.float64)
    start_points[:, 0] = np.linspace(-127.1, -126.5, N)
    start_points[:, 1] = np.linspace(47.93, 48.1, N)
    # print start_points

    release = SpatialRelease(start_position=start_points,
                             release_time=start_time)

    model.spills += Spill(release)

    # model.add_spill(spill)

    model.start_time = release.release_time

    # image_info = model.next_image()

    model.uncertain = True
    num_steps_output = 0
    while True:
        try:
            image_info = model.step()
            num_steps_output += 1
            print image_info
        except StopIteration:
            print 'Done with the model run'
            break

    # there is the zeroth step, too.
    calculated_steps = (model.duration.total_seconds() / model.time_step) + 1
    assert num_steps_output == calculated_steps
コード例 #4
0
def sample_model():
    """
    sample model with no outputter and no spills. Use this as a template for
    fixtures to add spills
    Uses:
        sample_data/MapBounds_Island.bna
        Contains: gnome.movers.SimpleMover(velocity=(1.0, -1.0, 0.0))
        duration is 1 hour with 15min intervals so 5 timesteps total,
        including initial condition,
        model is uncertain and cache is not enabled
        No spills or outputters defined

    To use:
        add a spill and run

    :returns: It returns a dict -
        {'model':model,
         'release_start_pos':start_points,
         'release_end_pos':end_points}
        The release_start_pos and release_end_pos can be used by test to define
        the spill's 'start_position' and 'end_position'
    """

    release_time = datetime(2012, 9, 15, 12, 0)

    # the image output map

    mapfile = os.path.join(os.path.dirname(__file__), 'sample_data',
                           'MapBounds_Island.bna')

    # the land-water map

    map_ = MapFromBNA(mapfile, refloat_halflife=06)  # seconds

    model = Model(
        time_step=timedelta(minutes=15),
        start_time=release_time,
        duration=timedelta(hours=1),
        map=map_,
        uncertain=True,
        cache_enabled=False,
    )

    model.movers += SimpleMover(velocity=(1., -1., 0.0))

    model.uncertain = True

    start_points = np.zeros((3, ), dtype=np.float64)
    end_points = np.zeros((3, ), dtype=np.float64)

    start_points[:] = (-127.1, 47.93, 0)
    end_points[:] = (-126.5, 48.1, 0)

    return {
        'model': model,
        'release_start_pos': start_points,
        'release_end_pos': end_points,
    }
コード例 #5
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_release_end_of_step(duration):
    '''
    - Tests that elements released at end of step are recorded with their
      initial conditions with correct timestamp
    - Also tests the age is set correctly.
    todo: write separate test for checking age
    '''
    model = Model(time_step=timedelta(minutes=15),
                  duration=timedelta(hours=duration))

    end_release_time = model.start_time + model.duration
    model.spills += point_line_release_spill(10, (0.0, 0.0, 0.0),
                                             model.start_time,
                                             end_release_time=end_release_time)

    model.movers += SimpleMover(velocity=(1., -1., 0.0))

    print '\n---------------------------------------------'
    print 'model_start_time: {0}'.format(model.start_time)

    prev_rel = len(model.spills.LE('positions'))
    for step in model:
        new_particles = len(model.spills.LE('positions')) - prev_rel
        if new_particles > 0:
            assert np.all(
                model.spills.LE('positions')[-new_particles:, :] == 0)
            assert np.all(model.spills.LE('age')[-new_particles:] == 0)
            # assert np.all(model.spills.LE('age')[-new_particles:] ==
            #            (model.model_time + timedelta(seconds=model.time_step)
            #             - model.start_time).seconds)

        if prev_rel > 0:
            assert np.all(model.spills.LE('positions')[:prev_rel, :2] != 0)
            assert np.all(model.spills.LE('age')[:prev_rel] >= model.time_step)

        prev_rel = len(model.spills.LE('positions'))

        print('current_time_stamp: {0}'.format(
            model.spills.LE('current_time_stamp')))
        print 'particle ID: {0}'.format(model.spills.LE('id'))
        print 'positions: \n{0}'.format(model.spills.LE('positions'))
        print 'age: \n{0}'.format(model.spills.LE('age'))
        print 'just ran: %s' % step
        print 'particles released: %s' % new_particles
        print '---------------------------------------------'

    print '\n==============================================='
コード例 #6
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_simple_run_rewind():
    '''
    Pretty much all this tests is that the model will run
    and the seed is set during first run, then set correctly
    after it is rewound and run again
    '''

    start_time = datetime(2012, 9, 15, 12, 0)

    model = Model()

    model.map = gnome.map.GnomeMap()
    a_mover = SimpleMover(velocity=(1., 2., 0.))

    model.movers += a_mover
    assert len(model.movers) == 1

    spill = point_line_release_spill(num_elements=10,
                                     start_position=(0., 0., 0.),
                                     release_time=start_time)

    model.spills += spill
    assert len(model.spills) == 1

    # model.add_spill(spill)

    model.start_time = spill.release.release_time

    # test iterator
    for step in model:
        print 'just ran time step: %s' % model.current_time_step
        assert step['step_num'] == model.current_time_step

    pos = np.copy(model.spills.LE('positions'))

    # rewind and run again:
    print 'rewinding'
    model.rewind()

    # test iterator is repeatable
    for step in model:
        print 'just ran time step: %s' % model.current_time_step
        assert step['step_num'] == model.current_time_step

    assert np.all(model.spills.LE('positions') == pos)
コード例 #7
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_callback_add_mover_midrun():
    'Test callback after add mover called midway through the run'
    model = Model()
    model.start_time = datetime(2012, 1, 1, 0, 0)
    model.duration = timedelta(hours=10)
    model.time_step = timedelta(hours=1)

    # start_loc = (1.0, 2.0, 0.0)  # random non-zero starting points

    # model = setup_simple_model()

    for i in range(2):
        model.step()

    assert model.current_time_step > -1

    # now add another mover and make sure model rewinds
    model.movers += SimpleMover(velocity=(2., -2., 0.))
    assert model.current_time_step == -1
コード例 #8
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_simple_run_with_map():
    '''
    pretty much all this tests is that the model will run
    '''

    start_time = datetime(2012, 9, 15, 12, 0)

    model = Model()

    model.map = gnome.map.MapFromBNA(testdata['MapFromBNA']['testmap'],
                                     refloat_halflife=6)  # hours
    a_mover = SimpleMover(velocity=(1., 2., 0.))

    model.movers += a_mover
    assert len(model.movers) == 1

    spill = point_line_release_spill(num_elements=10,
                                     start_position=(0., 0., 0.),
                                     release_time=start_time)

    model.spills += spill
    assert len(model.spills) == 1
    model.start_time = spill.release.release_time

    # test iterator
    for step in model:
        print 'just ran time step: %s' % step
        assert step['step_num'] == model.current_time_step

    # reset and run again
    model.reset()

    # test iterator is repeatable
    for step in model:
        print 'just ran time step: %s' % step
        assert step['step_num'] == model.current_time_step
コード例 #9
0
def make_model(images_dir=os.path.join(base_dir, 'images')):
    print 'initializing the model'

    # set up the modeling environment
    start_time = datetime(2016, 9, 23, 0, 0)
    model = Model(start_time=start_time,
                  duration=timedelta(days=2),
                  time_step=30 * 60,
                  uncertain=False)

    print 'adding the map'
    model.map = GnomeMap()  # this is a "water world -- no land anywhere"

    # renderere is only top-down view on 2d -- but it's something
    renderer = Renderer(output_dir=images_dir,
                        image_size=(1024, 768),
                        output_timestep=timedelta(hours=1),
                        )
    renderer.viewport = ((196.14, 71.89), (196.18, 71.93))

    print 'adding outputters'
    model.outputters += renderer

    # Also going to write the results out to a netcdf file
    netcdf_file = os.path.join(base_dir, 'script_arctic_plume.nc')
    scripting.remove_netcdf(netcdf_file)

    model.outputters += NetCDFOutput(netcdf_file,
                                     which_data='most',
                                     # output most of the data associated with the elements
                                     output_timestep=timedelta(hours=2))

    print "adding Horizontal and Vertical diffusion"

    # Horizontal Diffusion
    model.movers += RandomMover(diffusion_coef=500)
    # vertical diffusion (different above and below the mixed layer)
    model.movers += RandomMover3D(vertical_diffusion_coef_above_ml=5,
                                        vertical_diffusion_coef_below_ml=.11,
                                        mixed_layer_depth=10)

    print 'adding Rise Velocity'
    # droplets rise as a function of their density and radius
    model.movers += TamocRiseVelocityMover()

    print 'adding a circular current and eastward current'
    fn = 'hycom_glb_regp17_2016092300_subset.nc'
    fn_ice = 'hycom-cice_ARCu0.08_046_2016092300_subset.nc'
    iconc = IceConcentration.from_netCDF(filename=fn_ice)
    ivel = IceVelocity.from_netCDF(filename=fn_ice, grid = iconc.grid)
    ic = IceAwareCurrent.from_netCDF(ice_concentration = iconc, ice_velocity= ivel, filename=fn)

    model.movers += PyCurrentMover(current = ic)
    model.movers += SimpleMover(velocity=(0., 0., 0.))
    model.movers += constant_wind_mover(20, 315, units='knots')

    # Now to add in the TAMOC "spill"
    print "Adding TAMOC spill"

    model.spills += tamoc_spill.TamocSpill(release_time=start_time,
                                        start_position=(196.16, 71.91, 40.0),
                                        num_elements=1000,
                                        end_release_time=start_time + timedelta(days=1),
                                        name='TAMOC plume',
                                        TAMOC_interval=None,  # how often to re-run TAMOC
                                        )

    model.spills[0].data_sources['currents'] = ic

    return model
コード例 #10
0
def make_model(images_dir=os.path.join(base_dir, 'images')):
    print 'initializing the model'

    start_time = datetime(2004, 12, 31, 13, 0)
    model = Model(start_time=start_time,
                  duration=timedelta(days=3),
                  time_step=30 * 60,
                  uncertain=False)

    print 'adding the map'
    model.map = GnomeMap()

    # draw_ontop can be 'uncertain' or 'forecast'
    # 'forecast' LEs are in black, and 'uncertain' are in red
    # default is 'forecast' LEs draw on top
    renderer = Renderer(
        output_dir=images_dir,
        # size=(800, 600),
        output_timestep=timedelta(hours=1),
        draw_ontop='uncertain')
    renderer.viewport = ((-76.5, 37.), (-75.8, 38.))

    print 'adding outputters'
    model.outputters += renderer

    netcdf_file = os.path.join(base_dir, 'script_plume.nc')
    scripting.remove_netcdf(netcdf_file)

    model.outputters += NetCDFOutput(netcdf_file,
                                     which_data='most',
                                     output_timestep=timedelta(hours=2))

    print 'adding two spills'
    # Break the spill into two spills, first with the larger droplets
    # and second with the smaller droplets.
    # Split the total spill volume (100 m^3) to have most
    # in the larger droplet spill.
    # Smaller droplets start at a lower depth than larger

    wd = WeibullDistribution(alpha=1.8, lambda_=.00456,
                             min_=.0002)  # 200 micron min
    end_time = start_time + timedelta(hours=24)
    # spill = point_line_release_spill(num_elements=10,
    #                                  amount=90,  # default volume_units=m^3
    #                                  units='m^3',
    #                                  start_position=(-76.126872, 37.680952,
    #                                                  1700),
    #                                  release_time=start_time,
    #                                  end_release_time=end_time,
    #                                  element_type=plume(distribution=wd,
    #                                                     density=600)
    #                                  )

    spill = subsurface_plume_spill(
        num_elements=10,
        start_position=(-76.126872, 37.680952, 1700),
        release_time=start_time,
        distribution=wd,
        amount=90,  # default volume_units=m^3
        units='m^3',
        end_release_time=end_time,
        density=600)

    model.spills += spill

    wd = WeibullDistribution(alpha=1.8, lambda_=.00456,
                             max_=.0002)  # 200 micron max
    spill = point_line_release_spill(
        num_elements=10,
        amount=90,
        units='m^3',
        start_position=(-76.126872, 37.680952, 1800),
        release_time=start_time,
        element_type=plume(distribution=wd, substance_name='oil_crude'))
    model.spills += spill

    print 'adding a RandomMover:'
    model.movers += RandomMover(diffusion_coef=50000)

    print 'adding a RiseVelocityMover:'
    model.movers += RiseVelocityMover()

    print 'adding a RandomVerticalMover:'
    model.movers += RandomVerticalMover(vertical_diffusion_coef_above_ml=5,
                                        vertical_diffusion_coef_below_ml=.11,
                                        mixed_layer_depth=10)

    # print 'adding a wind mover:'

    # series = np.zeros((2, ), dtype=gnome.basic_types.datetime_value_2d)
    # series[0] = (start_time, (30, 90))
    # series[1] = (start_time + timedelta(hours=23), (30, 90))

    # wind = Wind(timeseries=series, units='knot')
    #
    # default is .4 radians
    # w_mover = gnome.movers.WindMover(wind, uncertain_angle_scale=0)
    #
    # model.movers += w_mover

    print 'adding a simple mover:'
    s_mover = SimpleMover(velocity=(0.0, -.3, 0.0))
    model.movers += s_mover

    return model
コード例 #11
0
from gnome.movers import RandomMover


l_spills = [point_line_release_spill(10, (0, 0, 0),
                                     datetime.now().replace(microsecond=0),
                                     name='sp1'),
            point_line_release_spill(15, (0, 0, 0),
                                     datetime.now().replace(microsecond=0),
                                     name='sp2'),
            point_line_release_spill(20, (0, 0, 0),
                                     datetime.now().replace(microsecond=0),
                                     name='sp3'),
            point_line_release_spill(5, (0, 0, 0),
                                     datetime.now().replace(microsecond=0),
                                     name='sp4')]
l_mv = [SimpleMover(velocity=(1, 2, 3)), RandomMover()]


def define_mdl(test=0):
    '''
    WebAPI will update/replace nested objects so do that for the test as well
    Setup some test cases:

    0 - empty model w/ no changes
    1 - model with l_mv and l_spills but no changes
    2 - empty model but add l_mv and l_spills to json_ so it changed
    3 - add l_mv and l_spills to model, then delete some elements and update
    via json
    '''
    def get_json(mdl):
        json_ = mdl.serialize()
コード例 #12
0
# For WindMover test_save_load in test_wind_mover
g_objects = (
    GridCurrent.from_netCDF(testdata['GridCurrentMover']['curr_tri']),
    Tide(testdata['CatsMover']['tide']),
    Wind(filename=testdata['ComponentMover']['wind']),
    Wind(timeseries=(sec_to_date(24 * 60 * 60), (0, 0)), units='mps'),
    Water(temperature=273),
    RandomMover(),
    CatsMover(testdata['CatsMover']['curr']),
    CatsMover(testdata['CatsMover']['curr'],
              tide=Tide(testdata['CatsMover']['tide'])),
    ComponentMover(testdata['ComponentMover']['curr']),
    ComponentMover(testdata['ComponentMover']['curr'],
                   wind=Wind(filename=testdata['ComponentMover']['wind'])),
    RandomMover3D(),
    SimpleMover(velocity=(10.0, 10.0, 0.0)),
    map.MapFromBNA(testdata['MapFromBNA']['testmap'], 6),
    NetCDFOutput(os.path.join(base_dir, u'xtemp.nc')),
    Renderer(testdata['Renderer']['bna_sample'],
             os.path.join(base_dir, 'output_dir')),
    WeatheringOutput(),
    spill.PointLineRelease(release_time=datetime.now(),
                           num_elements=10,
                           start_position=(0, 0, 0)),
    spill.point_line_release_spill(10, (0, 0, 0), datetime.now()),
    spill.substance.Substance(windage_range=(0.05, 0.07)),
    spill.substance.GnomeOil(test_oil, windage_range=(0.05, 0.07)),
    spill.substance.NonWeatheringSubstance(windage_range=(0.05, 0.07)),
    Skimmer(amount=100,
            efficiency=0.3,
            active_range=(datetime(2014, 1, 1, 0,
コード例 #13
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_all_movers(start_time, release_delay, duration):
    '''
    Tests that all the movers at least can be run

    Add new ones as they come along!
    '''

    model = Model()
    model.time_step = timedelta(hours=1)
    model.duration = timedelta(seconds=model.time_step * duration)
    model.start_time = start_time
    start_loc = (1., 2., 0.)  # random non-zero starting points

    # a spill - release after 5 timesteps

    release_time = (start_time +
                    timedelta(seconds=model.time_step * release_delay))
    model.spills += point_line_release_spill(num_elements=10,
                                             start_position=start_loc,
                                             release_time=release_time)

    # the land-water map
    model.map = gnome.map.GnomeMap()  # the simplest of maps

    # simple mover
    model.movers += SimpleMover(velocity=(1., -1., 0.))
    assert len(model.movers) == 1

    # random mover
    model.movers += RandomMover(diffusion_coef=100000)
    assert len(model.movers) == 2

    # wind mover
    series = np.array((start_time, (10, 45)), dtype=datetime_value_2d).reshape(
        (1, ))
    model.movers += WindMover(Wind(timeseries=series,
                                   units='meter per second'))
    assert len(model.movers) == 3

    # CATS mover
    model.movers += CatsMover(testdata['CatsMover']['curr'])
    assert len(model.movers) == 4

    # run the model all the way...
    num_steps_output = 0
    for step in model:
        num_steps_output += 1
        print 'running step:', step

    # test release happens correctly for all cases
    if release_delay < duration:
        # at least one get_move has been called after release
        assert np.all(model.spills.LE('positions')[:, :2] != start_loc[:2])
    elif release_delay == duration:
        # particles are released after last step so no motion,
        # only initial _state
        assert np.all(model.spills.LE('positions') == start_loc)
    else:
        # release_delay > duration so nothing released though model ran
        assert len(model.spills.LE('positions')) == 0

    # there is the zeroth step, too.
    calculated_steps = (model.duration.total_seconds() / model.time_step) + 1
    assert num_steps_output == calculated_steps
コード例 #14
0
def make_model(images_dir=os.path.join(base_dir, 'images')):
    print 'initializing the model'

    # set up the modeling environment
    start_time = datetime(2004, 12, 31, 13, 0)
    model = Model(start_time=start_time,
                  duration=timedelta(days=3),
                  time_step=30 * 60,
                  uncertain=False)

    print 'adding the map'
    model.map = GnomeMap()  # this is a "water world -- no land anywhere"

    # renderere is only top-down view on 2d -- but it's something
    renderer = Renderer(
        output_dir=images_dir,
        size=(1024, 768),
        output_timestep=timedelta(hours=1),
    )
    renderer.viewport = ((-.15, -.35), (.15, .35))

    print 'adding outputters'
    model.outputters += renderer

    # Also going to write the results out to a netcdf file
    netcdf_file = os.path.join(base_dir, 'script_plume.nc')
    scripting.remove_netcdf(netcdf_file)

    model.outputters += NetCDFOutput(
        netcdf_file,
        which_data='most',
        # output most of the data associated with the elements
        output_timestep=timedelta(hours=2))

    print "adding Horizontal and Vertical diffusion"

    # Horizontal Diffusion
    # model.movers += RandomMover(diffusion_coef=5)
    # vertical diffusion (different above and below the mixed layer)
    model.movers += RandomVerticalMover(vertical_diffusion_coef_above_ml=5,
                                        vertical_diffusion_coef_below_ml=.11,
                                        mixed_layer_depth=10)

    print 'adding Rise Velocity'
    # droplets rise as a function of their density and radius
    model.movers += RiseVelocityMover()

    print 'adding a circular current and eastward current'
    # This is .3 m/s south
    model.movers += PyCurrentMover(current=vg,
                                   default_num_method='Trapezoid',
                                   extrapolate=True)
    model.movers += SimpleMover(velocity=(0., -0.1, 0.))

    # Now to add in the TAMOC "spill"
    print "Adding TAMOC spill"

    model.spills += tamoc_spill.TamocSpill(
        release_time=start_time,
        start_position=(0, 0, 1000),
        num_elements=1000,
        end_release_time=start_time + timedelta(days=1),
        name='TAMOC plume',
        TAMOC_interval=None,  # how often to re-run TAMOC
    )

    return model