コード例 #1
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def test_contains_object(sample_model_fcn):
    '''
    Test that we can find all contained object types with a model.
    '''
    model = sample_model_weathering(sample_model_fcn, test_oil)

    gnome_map = model.map = gnome.map.GnomeMap()  # make it all water

    rel_time = model.spills[0].get('release_time')
    model.start_time = rel_time - timedelta(hours=1)
    model.duration = timedelta(days=1)

    water, wind = Water(), constant_wind(1., 0)
    model.environment += [water, wind]

    et = floating(substance=model.spills[0].get('substance').name)
    sp = point_line_release_spill(500, (0, 0, 0),
                                  rel_time + timedelta(hours=1),
                                  element_type=et,
                                  amount=100,
                                  units='tons')
    rel = sp.release
    initializers = et.initializers
    model.spills += sp

    movers = [m for m in model.movers]

    evaporation = Evaporation()
    skim_start = sp.get('release_time') + timedelta(hours=1)
    skimmer = Skimmer(.5 * sp.amount,
                      units=sp.units,
                      efficiency=0.3,
                      active_start=skim_start,
                      active_stop=skim_start + timedelta(hours=1))
    burn = burn_obj(sp)
    disp_start = skim_start + timedelta(hours=1)
    dispersion = ChemicalDispersion(0.1,
                                    active_start=disp_start,
                                    active_stop=disp_start +
                                    timedelta(hours=1))

    model.weatherers += [evaporation, dispersion, burn, skimmer]

    renderer = Renderer(images_dir='junk', size=(400, 300))
    model.outputters += renderer

    for o in (gnome_map, sp, rel, et, water, wind, evaporation, dispersion,
              burn, skimmer, renderer):
        assert model.contains_object(o.id)

    for o in initializers:
        assert model.contains_object(o.id)

    for o in movers:
        assert model.contains_object(o.id)
コード例 #2
0
def model(sample_model):
    model = sample_model['model']
    model.make_default_refs = True
    rel_start_pos = sample_model['release_start_pos']
    rel_end_pos = sample_model['release_end_pos']

    model.cache_enabled = True
    model.uncertain = False
    model.environment += Water(311.15)

    print 'adding a Weatherer'
    model.environment += constant_wind(1.0, 0.0)

    N = 10  # a line of ten points
    line_pos = np.zeros((N, 3), dtype=np.float64)
    line_pos[:, 0] = np.linspace(rel_start_pos[0], rel_end_pos[0], N)
    line_pos[:, 1] = np.linspace(rel_start_pos[1], rel_end_pos[1], N)

    # print start_points
    model.duration = timedelta(hours=6)
    end_time = model.start_time + timedelta(hours=1)
    spill = point_line_release_spill(1000,
                                     start_position=rel_start_pos,
                                     release_time=model.start_time,
                                     end_release_time=end_time,
                                     end_position=rel_end_pos,
                                     substance=test_oil,
                                     amount=1000,
                                     units='kg')
    model.spills += spill

    # figure out mid-run save for weathering_data attribute, then add this in
    rel_time = model.spills[0].get('release_time')
    skim_start = rel_time + timedelta(hours=1)
    amount = model.spills[0].amount
    units = model.spills[0].units
    skimmer = Skimmer(.3 * amount,
                      units=units,
                      efficiency=0.3,
                      active_start=skim_start,
                      active_stop=skim_start + timedelta(hours=1))
    # thickness = 1m so area is just 20% of volume
    volume = spill.get_mass() / spill.get('substance').get_density()
    burn = Burn(0.2 * volume, 1.0, active_start=skim_start, efficiency=0.9)
    c_disp = ChemicalDispersion(.1,
                                efficiency=0.5,
                                active_start=skim_start,
                                active_stop=skim_start + timedelta(hours=1))

    model.weatherers += [Evaporation(), c_disp, burn, skimmer]

    model.outputters += WeatheringOutput()
    model.rewind()

    return model
コード例 #3
0
ファイル: test_model.py プロジェクト: satcomlabs/PyGnome
def chemical_disperson_obj(spill, delay_hours=1, duration=1):
    '''
    apply chemical dispersion to 10% of spill
    '''
    rel_time = spill.get('release_time')
    disp_start = rel_time + timedelta(hours=delay_hours)

    return ChemicalDispersion(.1,
                              active_start=disp_start,
                              active_stop=(disp_start +
                                           timedelta(hours=duration)),
                              efficiency=0.3)
コード例 #4
0
def test_weatherer_sort():
    '''
    Sample model with weatherers - only tests sorting of weathereres. The
    Model will likely not run
    '''
    model = Model()

    skimmer = Skimmer(100, 'kg', efficiency=0.3,
                      active_start=datetime(2014, 1, 1, 0, 0),
                      active_stop=datetime(2014, 1, 1, 0, 3))
    burn = Burn(100, 1, active_start=datetime(2014, 1, 1, 0, 0))
    c_disp = ChemicalDispersion(.3,
                                active_start=datetime(2014, 1, 1, 0, 0),
                                active_stop=datetime(2014, 1, 1, 0, 3),
                                efficiency=0.2)
    weatherers = [Emulsification(),
                  Evaporation(Water(),
                              constant_wind(1, 0)),
                  burn,
                  c_disp,
                  skimmer]

    exp_order = [weatherers[ix] for ix in (3, 4, 2, 1, 0)]

    model.environment += [Water(), constant_wind(5, 0), Waves()]
    model.weatherers += weatherers

    # WeatheringData and FayGravityViscous automatically get added to
    # weatherers. Only do assertion on weatherers contained in list above
    assert model.weatherers.values()[:len(exp_order)] != exp_order

    model.setup_model_run()

    assert model.weatherers.values()[:len(exp_order)] == exp_order

    # check second time around order is kept
    model.rewind()
    assert model.weatherers.values()[:len(exp_order)] == exp_order

    # Burn, ChemicalDispersion are at same sorting level so appending
    # another Burn to the end of the list will sort it to be just after
    # ChemicalDispersion so index 2
    burn = Burn(50, 1, active_start=datetime(2014, 1, 1, 0, 0))
    exp_order.insert(3, burn)

    model.weatherers += exp_order[3]  # add this and check sorting still works
    assert model.weatherers.values()[:len(exp_order)] != exp_order

    model.setup_model_run()

    assert model.weatherers.values()[:len(exp_order)] == exp_order
コード例 #5
0
ファイル: test_cleanup.py プロジェクト: shhw2019/noaa_pyGnome
    def test_set_efficiency(self):
        '''
        for wave height > 6.4 m, efficiency goes to 0
        '''
        # make wind large so efficiency goes to 0
        waves = Waves(constant_wind(0, 0), water=Water())
        c_disp = ChemicalDispersion(self.spill_pct, active_range, waves=waves)
        pts = np.array([[0, 0], [0, 0]])
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert c_disp.efficiency == 1.0

        c_disp.efficiency = 0
        waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0))
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert np.all(c_disp.efficiency == 0)
コード例 #6
0
    def test_set_efficiency(self):
        '''
        for wave height > 6.4 m, efficiency goes to 0
        '''
        # make wind large so efficiency goes to 0
        waves = Waves(constant_wind(0, 0), water=Water())
        c_disp = ChemicalDispersion(self.spill_pct,
                                    active_start,
                                    active_stop,
                                    waves=waves)
        c_disp._set_efficiency(self.spill.release_time)
        assert c_disp.efficiency == 1.0

        c_disp.efficiency = None
        waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0))
        c_disp._set_efficiency(self.spill.release_time)
        assert c_disp.efficiency == 0
コード例 #7
0
ファイル: test_cleanup.py プロジェクト: liuy0813/PyGnome
    def test_set_efficiency(self):
        '''
        for wave height > 6.4 m, efficiency goes to 0
        '''
        # make wind large so efficiency goes to 0
        waves = Waves(constant_wind(0, 0), water=Water())
        c_disp = ChemicalDispersion(self.spill_pct,
                                    active_start,
                                    active_stop,
                                    waves=waves)
        c_disp._set_efficiency(self.spill.get('release_time'))
        assert c_disp.efficiency == 1.0

        c_disp.efficiency = None
        waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0))
        c_disp._set_efficiency(self.spill.get('release_time'))
        assert c_disp.efficiency == 0
コード例 #8
0
ファイル: test_cleanup.py プロジェクト: NOAA-ORR-ERD/PyGnome
    def test_set_efficiency(self):
        '''
        for wave height > 6.4 m, efficiency goes to 0
        '''
        # make wind large so efficiency goes to 0
        waves = Waves(constant_wind(0, 0), water=Water())
        c_disp = ChemicalDispersion(self.spill_pct,
                                    active_range,
                                    waves=waves)
        pts = np.array([[0, 0], [0, 0]])
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert c_disp.efficiency == 1.0

        c_disp.efficiency = 0
        waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0))
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert np.all(c_disp.efficiency == 0)
コード例 #9
0
ファイル: test_cleanup.py プロジェクト: shhw2019/noaa_pyGnome
class TestChemicalDispersion(ObjForTests):
    (sc, weatherers) = ObjForTests.mk_test_objs()
    spill = sc.spills[0]
    op = spill.substance
    spill_pct = 0.2  # 20%
    c_disp = ChemicalDispersion(spill_pct, active_range, efficiency=0.3)

    def test_prepare_for_model_run(self):
        '''
        test efficiency gets set correctly
        '''
        self.prepare_test_objs()

        assert 'chem_dispersed' not in self.sc.mass_balance

        self.c_disp.prepare_for_model_run(self.sc)
        assert self.sc.mass_balance['chem_dispersed'] == 0.0

    def test_set_efficiency(self):
        '''
        for wave height > 6.4 m, efficiency goes to 0
        '''
        # make wind large so efficiency goes to 0
        waves = Waves(constant_wind(0, 0), water=Water())
        c_disp = ChemicalDispersion(self.spill_pct, active_range, waves=waves)
        pts = np.array([[0, 0], [0, 0]])
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert c_disp.efficiency == 1.0

        c_disp.efficiency = 0
        waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0))
        c_disp._set_efficiency(pts, self.spill.release_time)
        assert np.all(c_disp.efficiency == 0)

    @mark.parametrize("efficiency", (0.5, 1.0))
    def test_prepare_for_model_step(self, efficiency):
        '''
        updated: efficiency now does impact the mass of LEs marked as
                 having been sprayed. precent_sprayed also impacts the
                 mass of LEs marked as disperse.
        '''
        self.reset_and_release()
        self.c_disp.efficiency = efficiency

        assert np.all(self.sc['fate_status'] == fate.surface_weather)

        self.c_disp.prepare_for_model_run(self.sc)
        self.c_disp.prepare_for_model_step(self.sc, time_step, active_start)
        d_mass = self.sc['mass'][self.sc['fate_status'] == fate.disperse].sum()

        assert d_mass == (self.c_disp.fraction_sprayed *
                          self.spill.get_mass() * efficiency)
        exp_mass = (self.spill.get_mass() * self.c_disp.fraction_sprayed *
                    efficiency)
        assert d_mass - exp_mass < self.sc['mass'][0]

    @mark.parametrize("frac_water", (0.5, 0.0))
    def test__update_LE_status_codes(self, frac_water):
        '''
        efficiency does not impact the mass of LEs marked as having been
        sprayed. precent_sprayed determines percent of LEs marked as disperse.
        '''
        self.reset_and_release()
        self.sc['frac_water'][:] = frac_water
        assert np.all(self.sc['fate_status'] == fate.surface_weather)

        self.c_disp.prepare_for_model_run(self.sc)
        self.c_disp.prepare_for_model_step(self.sc, time_step, active_start)
        d_mass = self.sc['mass'][self.sc['fate_status'] == fate.disperse].sum()

        assert d_mass == self.c_disp.fraction_sprayed * self.spill.get_mass()
        exp_mass = self.spill.get_mass() * self.c_disp.fraction_sprayed
        assert d_mass - exp_mass < self.sc['mass'][0]

    @mark.parametrize("efficiency", (1.0, 0.7))
    def test_weather_elements(self, efficiency):
        self.prepare_test_objs()
        self.c_disp.efficiency = efficiency
        self.c_disp.prepare_for_model_run(self.sc)

        assert self.sc.mass_balance['chem_dispersed'] == 0.0

        model_time = self.spill.release_time
        while (model_time <
               self.c_disp.active_range[1] + timedelta(seconds=time_step)):
            amt_disp = self.sc.mass_balance['chem_dispersed']
            self.release_elements(time_step, model_time)
            self.step(self.c_disp, time_step, model_time)

            if not self.c_disp.active:
                assert self.sc.mass_balance['chem_dispersed'] == amt_disp
            else:
                assert self.sc.mass_balance['chem_dispersed'] > amt_disp

            model_time += timedelta(seconds=time_step)

        assert np.allclose(amount,
                           self.sc.mass_balance['chem_dispersed'] +
                           self.sc['mass'].sum(),
                           atol=1e-6)
        assert np.allclose(
            self.sc.mass_balance['chem_dispersed'] / self.spill.get_mass(),
            self.c_disp.fraction_sprayed * efficiency)
コード例 #10
0
                           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,
                                   0), datetime(2014, 1, 1, 4, 0)),
            units='kg'),
    Burn(area=100,
         thickness=1,
         active_range=(datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)),
         efficiency=.9),
    ChemicalDispersion(fraction_sprayed=.2,
                       active_range=(datetime(2014, 1, 1, 0,
                                              0), datetime(2014, 1, 1, 4, 0)),
                       efficiency=.3),
    # todo: ask Caitlin how to fix
    # movers.RiseVelocityMover(),
    # todo: This is incomplete - no _schema for
    #       SpatialRelease, GeoJson
    # spill.SpatialRelease(datetime.now(), ((0, 0, 0), (1, 2, 0))),
    TrajectoryGeoJsonOutput(),
)


@pytest.mark.parametrize("obj", g_objects)
def test_serial_deserial(saveloc_, obj):
    'test save/load functionality'
    json_ = obj.serialize()
    obj2 = obj.__class__.deserialize(json_)
コード例 #11
0
def make_model(uncertain=False, geojson_output=False):
    print 'initializing the model'

    start_time = datetime(2012, 9, 15, 12, 0)
    mapfile = testdata["lis"]["map"]

    gnome_map = MapFromBNA(mapfile, refloat_halflife=6)  # hours

    # # the image output renderer
    # global renderer

    # one hour timestep
    model = Model(start_time=start_time,
                  duration=timedelta(hours=48),
                  time_step=3600,
                  map=gnome_map,
                  uncertain=uncertain,
                  cache_enabled=False)

    print 'adding a spill'
    spill = point_line_release_spill(num_elements=1000,
                                     start_position=(-72.419992, 41.202120,
                                                     0.0),
                                     release_time=start_time,
                                     amount=1000,
                                     substance=test_oil,
                                     units='kg')
    spill.amount_uncertainty_scale = 1.0
    model.spills += spill

    print 'adding a RandomMover:'
    model.movers += RandomMover(diffusion_coef=500000, uncertain_factor=2)

    print 'adding a wind mover:'
    series = np.zeros((5, ), dtype=datetime_value_2d)
    series[0] = (start_time, (20, 45))
    series[1] = (start_time + timedelta(hours=18), (20, 90))
    series[2] = (start_time + timedelta(hours=30), (20, 135))
    series[3] = (start_time + timedelta(hours=42), (20, 180))
    series[4] = (start_time + timedelta(hours=54), (20, 225))

    wind = Wind(timeseries=series, units='m/s', speed_uncertainty_scale=0.05)
    model.movers += WindMover(wind)

    print 'adding a cats mover:'
    c_mover = CatsMover(testdata["lis"]["cats_curr"],
                        tide=Tide(testdata["lis"]["cats_tide"]))
    model.movers += c_mover

    model.environment += c_mover.tide

    print 'adding Weatherers'
    rel_time = model.spills[0].get('release_time')
    skim_start = rel_time + timedelta(hours=4)
    amount = spill.amount
    units = spill.units

    # define skimmer/burn cleanup options
    skimmer = Skimmer(0.3 * amount,
                      units=units,
                      efficiency=0.3,
                      active_start=skim_start,
                      active_stop=skim_start + timedelta(hours=4))
    # thickness = 1m so area is just 20% of volume
    volume = spill.get_mass() / spill.get('substance').get_density()
    burn = Burn(0.2 * volume, 1.0, active_start=skim_start, efficiency=.9)
    c_disp = ChemicalDispersion(0.1,
                                efficiency=0.5,
                                active_start=skim_start,
                                active_stop=skim_start + timedelta(hours=1))

    water_env = Water(311.15)
    model.environment += water_env
    model.weatherers += [Evaporation(water_env, wind), c_disp, burn, skimmer]

    print 'adding outputters'
    model.outputters += WeatheringOutput()

    if geojson_output:
        model.outputters += TrajectoryGeoJsonOutput()

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

    start_time = datetime(2015, 5, 14, 0, 0)

    # 1 day of data in file
    # 1/2 hr in seconds
    model = Model(start_time=start_time,
                  duration=timedelta(days=1.75),
                  time_step=60 * 60,
                  uncertain=True)

    #     mapfile = get_datafile(os.path.join(base_dir, './ak_arctic.bna'))
    #
    #     print 'adding the map'
    #     model.map = MapFromBNA(mapfile, refloat_halflife=1)  # seconds
    #
    #     # 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(mapfile, images_dir, size=(800, 600),
    #                         output_timestep=timedelta(hours=2),
    #                         draw_ontop='forecast')
    #
    #     print 'adding outputters'
    #     model.outputters += renderer

    model.outputters += WeatheringOutput()

    netcdf_file = os.path.join(base_dir, 'script_weatherers.nc')
    scripting.remove_netcdf(netcdf_file)
    model.outputters += NetCDFOutput(netcdf_file,
                                     which_data='all',
                                     output_timestep=timedelta(hours=1))

    print 'adding a spill'
    # for now subsurface spill stays on initial layer
    # - will need diffusion and rise velocity
    # - wind doesn't act
    # - start_position = (-76.126872, 37.680952, 5.0),
    end_time = start_time + timedelta(hours=24)
    spill = point_line_release_spill(
        num_elements=100,
        start_position=(-164.791878561, 69.6252597267, 0.0),
        release_time=start_time,
        end_release_time=end_time,
        amount=1000,
        substance='ALASKA NORTH SLOPE (MIDDLE PIPELINE)',
        units='bbl')

    # set bullwinkle to .303 to cause mass goes to zero bug at 24 hours (when continuous release ends)
    spill.element_type._substance._bullwinkle = .303
    model.spills += spill

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

    print 'adding a wind mover:'

    series = np.zeros((2, ), dtype=datetime_value_2d)
    series[0] = (start_time, (20, 0))
    series[1] = (start_time + timedelta(hours=23), (20, 0))

    wind2 = Wind(timeseries=series, units='knot')

    w_mover = WindMover(wind)
    model.movers += w_mover

    print 'adding weatherers and cleanup options:'

    # define skimmer/burn cleanup options
    skim1_start = start_time + timedelta(hours=15.58333)
    skim2_start = start_time + timedelta(hours=16)
    units = spill.units
    skimmer1 = Skimmer(80,
                       units=units,
                       efficiency=0.36,
                       active_start=skim1_start,
                       active_stop=skim1_start + timedelta(hours=8))
    skimmer2 = Skimmer(120,
                       units=units,
                       efficiency=0.2,
                       active_start=skim2_start,
                       active_stop=skim2_start + timedelta(hours=12))

    burn_start = start_time + timedelta(hours=36)
    burn = Burn(1000., .1, active_start=burn_start, efficiency=.2)

    chem_start = start_time + timedelta(hours=24)
    c_disp = ChemicalDispersion(0.5,
                                efficiency=0.4,
                                active_start=chem_start,
                                active_stop=chem_start + timedelta(hours=8))

    model.environment += [Water(280.928), wind, waves]

    model.weatherers += Evaporation(water, wind)
    model.weatherers += Emulsification(waves)
    model.weatherers += NaturalDispersion(waves, water)
    model.weatherers += skimmer1
    model.weatherers += skimmer2
    model.weatherers += burn
    model.weatherers += c_disp

    return model
コード例 #13
0
    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.elements.ElementType(substance=test_oil),
    Skimmer(100, 'kg', 0.3,
            (datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0))),
    Burn(100,
         1, (datetime(2014, 1, 1, 0, 0), InfDateTime('inf')),
         efficiency=.9),
    ChemicalDispersion(
        .2, (datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)),
        efficiency=.3),
    # todo: ask Caitlin how to fix
    # movers.RiseVelocityMover(),
    # todo: This is incomplete - no _schema for
    #       SpatialRelease, GeoJson
    # spill.SpatialRelease(datetime.now(), ((0, 0, 0), (1, 2, 0))),
    TrajectoryGeoJsonOutput(),
)


@pytest.mark.parametrize("obj", g_objects)
def test_serial_deserial(saveloc_, obj):
    'test save/load functionality'
    json_ = obj.serialize()
    obj2 = obj.__class__.deserialize(json_)
コード例 #14
0
def model(sample_model):
    model = sample_model['model']
    model.make_default_refs = True

    rel_start_pos = sample_model['release_start_pos']
    rel_end_pos = sample_model['release_end_pos']

    # model.cache_enabled = True # why use the cache -- it'll just slow things down!!!
    model.uncertain = False

    wind = constant_wind(1.0, 0.0)
    water = Water(311.15)
    model.environment += water

    waves = Waves(wind, water)
    model.environment += waves

    print "the environment:", model.environment

    start_time = model.start_time

    model.duration = timedelta(hours=12)
    end_time = start_time + timedelta(hours=1)
    spill = point_line_release_spill(100,
                                     start_position=rel_start_pos,
                                     release_time=start_time,
                                     end_release_time=start_time + hours(1),
                                     end_position=rel_end_pos,
                                     substance=test_oil,
                                     amount=1000,
                                     units='kg')
    model.spills += spill

    # figure out mid-run save for weathering_data attribute, then add this in
    # rel_time = model.spills[0].release_time

    skim_start = start_time + timedelta(hours=1)
    amount = model.spills[0].amount
    units = model.spills[0].units

    skimmer = Skimmer(.3 * amount,
                      units=units,
                      efficiency=0.3,
                      active_range=(skim_start,
                                    skim_start + hours(1)))

    # thickness = 1m so area is just 20% of volume
    volume = spill.get_mass() / spill.substance.density_at_temp()

    burn = Burn(0.2 * volume, 1.0,
                active_range=(skim_start, InfDateTime('inf')),
                efficiency=0.9)

    c_disp = ChemicalDispersion(.1, efficiency=0.5,
                                active_range=(skim_start,
                                              skim_start + timedelta(hours=1)),
                                waves=waves)

    model.weatherers += [Evaporation(),
                         c_disp,
                         burn,
                         skimmer]

    model.outputters += WeatheringOutput()
    model.rewind()

    return model