示例#1
0
    def test_zero_efficiency(self):
        '''
            tests efficiency.
            - If burn2 efficiency is 0.0 and burn1 efficiency is 1.0,
              then burn2_amount/burn1_amount = 0.0
            - Also checks the burn duration is not effected by efficiency

            The burn duration for both will be the same since efficiency only
            effects the amount of oil burned. The rate at which the oil/water
            mixture goes down to 2mm only depends on fractional water content.
        '''
        self.spill.num_elements = 500
        area = (0.5 * self.volume) / 1.
        eff = 0.0
        water = self.weatherers[0].water

        burn1 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn2 = Burn(area, 1., active_range, efficiency=eff, water=water)

        self._weather_elements_helper(burn1)
        amount_burn1 = self.sc.mass_balance['burned']

        with raises(Exception):
            self._weather_elements_helper(burn2)

        amount_burn2 = self.sc.mass_balance['burned']

        assert np.isclose(amount_burn2 / amount_burn1, eff)
        assert burn1.active_range == burn2.active_range
示例#2
0
    def test_update_from_dict(self):
        '''
        test that the update_from_dict correctly sets efficiency to None
        if it is dropped from json payload if user chose compute from wind
        '''
        self.burn.wind = constant_wind(5, 0)
        json_ = self.burn.serialize()
        assert self.burn.efficiency is not None
        del json_['efficiency']

        dict_ = Burn.deserialize(json_)
        dict_['wind'] = self.burn.wind
        assert 'wind' in dict_
        self.burn.update_from_dict(dict_)
        assert self.burn.efficiency is None

        json_['efficiency'] = .4

        # make sure None for wind doesn't break it
        dict_['wind'] = None
        dict_ = Burn.deserialize(json_)
        self.burn.update_from_dict(dict_)
        assert self.burn.efficiency == json_['efficiency']

        # update area/thickness
        st = self.burn.active_stop
        self.burn.thickness *= 2
        assert self.burn.active_stop > st

        # burn duration just depents on thickness - not area
        st = self.burn.active_stop
        self.burn.area *= 2
        assert self.burn.active_stop == st
示例#3
0
    def test_update_active_start(self):
        '''
        active stop should be updated if we update active start or thickness
        '''
        burn = Burn(self.area,
                    self.thick,
                    active_range=(active_start, InfDateTime('inf')),
                    name='test_burn',
                    on=False)   # this is ignored!

        # use burn constant for test - it isn't stored anywhere
        duration = ((uc.convert('Length', burn.thickness_units, 'm',
                                burn.thickness) -
                     burn._min_thickness) /
                    burn._burn_constant)

        assert (burn.active_range[1] ==
                burn.active_range[0] + timedelta(seconds=duration))

        # after changing active start, active stop should still match the
        # duration.
        burn.active_range = (burn.active_range[0] + timedelta(days=1),
                             burn.active_range[1])
        assert (burn.active_range[1] ==
                burn.active_range[0] + timedelta(seconds=duration))
示例#4
0
    def test_efficiency(self):
        '''
            tests efficiency.
            - If burn2 efficiency is 0.7 and burn1 efficiency is 1.0,
              then burn2_amount/burn1_amount = 0.7
            - Also checks the burn duration is not effected by efficiency

            The burn duration for both will be the same since efficiency only
            effects the amount of oil burned. The rate at which the oil/water
            mixture goes down to 2mm only depends on fractional water content.
        '''
        self.spill.set('num_elements', 500)
        area = (0.5 * self.volume) / 1.
        eff = 0.7
        burn1 = Burn(area, 1., active_start, efficiency=1.0)
        burn2 = Burn(area, 1., active_start, efficiency=eff)

        self._weather_elements_helper(burn1)
        amount_burn1 = self.sc.mass_balance['burned']
        self._weather_elements_helper(burn2)
        amount_burn2 = self.sc.mass_balance['burned']

        assert np.isclose(amount_burn2 / amount_burn1, eff)
        assert burn1.active_start == burn2.active_start
        assert burn1.active_stop == burn2.active_stop
示例#5
0
    def test_update_from_dict(self):
        '''
        test that the update_from_dict correctly sets efficiency to None
        if it is dropped from json payload if user chose compute from wind
        '''
        self.burn.wind = constant_wind(5, 0)
        json_ = self.burn.serialize()
        assert self.burn.efficiency is not None
        del json_['efficiency']

        dict_ = Burn.deserialize(json_)
        dict_['wind'] = self.burn.wind
        assert 'wind' in dict_
        self.burn.update_from_dict(dict_)
        assert self.burn.efficiency is None

        json_['efficiency'] = .4

        # make sure None for wind doesn't break it
        dict_['wind'] = None
        dict_ = Burn.deserialize(json_)
        self.burn.update_from_dict(dict_)
        assert self.burn.efficiency == json_['efficiency']

        # update area/thickness
        st = self.burn.active_stop
        self.burn.thickness *= 2
        assert self.burn.active_stop > st

        # burn duration just depents on thickness - not area
        st = self.burn.active_stop
        self.burn.area *= 2
        assert self.burn.active_stop == st
示例#6
0
    def test_elements_weather_faster_with_frac_water(self):
        '''
        Tests that avg_water_frac > 0 weathers faster
        '''
        self.spill.num_elements = 500
        area = (0.5 * self.volume) / 1.
        water = self.weatherers[0].water

        burn1 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn2 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn3 = Burn(area, 1., active_range, efficiency=1.0, water=water)

        self._weather_elements_helper(burn1)
        self._weather_elements_helper(burn2, avg_frac_water=0.3)
        self._weather_elements_helper(burn3, avg_frac_water=0.5)

        print "frac_water", 1.0, "burn_duration", \
            round((burn1.active_range[1] - burn1.active_range[0])
                  .total_seconds())
        print "frac_water", 0.3, "burn_duration", \
            round((burn2.active_range[1] - burn2.active_range[0])
                  .total_seconds())
        print "frac_water", 0.9, "burn_duration", \
            round((burn3.active_range[1] - burn3.active_range[0])
                  .total_seconds())
        assert (burn1.active_range[1] - burn1.active_range[0] <
                burn2.active_range[1] - burn2.active_range[0] <
                burn3.active_range[1] - burn3.active_range[0])
示例#7
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
示例#8
0
def burn_obj(spill, delay_hours=1.5):
    rel_time = spill.get('release_time')
    burn_start = rel_time + timedelta(hours=delay_hours)
    volume = spill.get_mass() / spill.get('substance').get_density()
    thick = 1  # in meters
    area = (0.2 * volume) / thick

    return Burn(area, thick, active_start=burn_start)
示例#9
0
    def test_weather_elements(self, thick, avg_frac_water, units):
        '''
        weather elements and test. frac_water is 0. Test thickness in units
        other than 'm'.

        1) tests the expected burned mass equals 'burned' amount stored in
           mass_balance
        2) also tests the mass_remaining is consistent with what we expect
        3) tests the mass of LEs set for burn equals the mass of oil given
           avg_frac_water and the thickness, and area. Since we cannot have
           a fraction of an LE, the difference should be within the mass of
           one LE.

        Also sets the 'frac_water' to 0.5 for one of the tests just to ensure
        it works.
        '''
        self.spill.set('num_elements', 500)
        thick_si = uc.convert('Length', units, 'm', thick)
        area = (0.5 * self.volume)/thick_si
        burn = Burn(area, thick, active_start, thickness_units=units,
                    efficiency=1.0)

        # return the initial value of burn._oil_thickness - this is starting
        # thickness of the oil
        self._weather_elements_helper(burn, avg_frac_water)

        # following should finally hold true for entire run
        assert np.allclose(amount, self.sc.mass_balance['burned'] +
                           self.sc['mass'].sum(), atol=1e-6)

        # want mass of oil thickness * area gives volume of oil-water so we
        # need to scale this by (1 - avg_frac_water)
        exp_burned = ((thick_si - burn._min_thickness) * (1 - avg_frac_water) *
                      burn.area * self.op.get_density())
        assert np.isclose(self.sc.mass_balance['burned'], exp_burned)

        mask = self.sc['fate_status'] & fate.burn == fate.burn

        # given LEs are discrete elements, we cannot add a fraction of an LE
        mass_per_le = self.sc['init_mass'][mask][0]
        exp_init_oil_mass = (burn.area * thick_si * (1 - avg_frac_water) *
                             self.op.get_density())
        assert (self.sc['init_mass'][mask].sum() - exp_init_oil_mass <
                mass_per_le and
                self.sc['init_mass'][mask].sum() - exp_init_oil_mass >= 0.0)

        exp_mass_remain = (burn._oilwater_thickness * (1 - avg_frac_water) *
                           burn.area * self.op.get_density())
        mass_remain_for_burn_LEs = self.sc['mass'][mask].sum()
        # since we don't adjust the thickness anymore need to use min_thick
        min_thick = .002
        exp_mass_remain = min_thick * (1 - avg_frac_water) * burn.area * self.op.get_density()
        assert np.allclose(exp_mass_remain, mass_remain_for_burn_LEs)

        duration = (burn.active_stop-burn.active_start).total_seconds()/3600
        print ('Current Thickness: {0:.3f}, '
               'Duration (hrs): {1:.3f}').format(burn._oilwater_thickness,
                                                 duration)
示例#10
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
示例#11
0
    def test_units_exception(self, area_units, thickness_units):
        ''' tests incorrect units raises exception '''
        with raises(uc.InvalidUnitError):
            self.burn.area_units = "in"

        with raises(uc.InvalidUnitError):
            self.burn.thickness_units = "m^2"

        with raises(uc.InvalidUnitError):
            Burn(10, 1, datetime.now(), area_units=area_units,
                 thickness_units=thickness_units)
示例#12
0
    def test_elements_weather_faster_with_frac_water(self):
        '''
        Tests that avg_water_frac > 0 weathers faster
        '''
        self.spill.set('num_elements', 500)
        area = (0.5 * self.volume) / 1.
        burn1 = Burn(area, 1., active_start, efficiency=1.0)
        burn2 = Burn(area, 1., active_start, efficiency=1.0)
        burn3 = Burn(area, 1., active_start, efficiency=1.0)

        self._weather_elements_helper(burn1)
        self._weather_elements_helper(burn2, avg_frac_water=0.3)
        self._weather_elements_helper(burn3, avg_frac_water=0.5)

        print "frac_water", 1.0, "burn_duration", \
            round((burn1.active_stop - burn1.active_start).total_seconds())
        print "frac_water", 0.3, "burn_duration", \
            round((burn2.active_stop - burn2.active_start).total_seconds())
        print "frac_water", 0.9, "burn_duration", \
            round((burn3.active_stop - burn3.active_start).total_seconds())
        assert (burn1.active_stop - burn1.active_start < burn2.active_stop -
                burn2.active_start < burn3.active_stop - burn3.active_start)
示例#13
0
    def test_init(self):
        '''
        active stop is ignored if set by user
        '''
        burn = Burn(self.area,
                    self.thick,
                    active_range=(active_start, InfDateTime('inf')),
                    name='test_burn',
                    on=False)  # this is ignored!

        # use burn constant for test - it isn't stored anywhere
        duration = (
            uc.convert('Length', burn.thickness_units, 'm', burn.thickness) -
            burn._min_thickness) / burn._burn_constant

        assert (burn.active_range[1] == burn.active_range[0] +
                timedelta(seconds=duration))
        assert burn.name == 'test_burn'
        assert not burn.on
示例#14
0
    RandomVerticalMover(),
    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.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):
示例#15
0
class TestBurn(ObjForTests):
    '''
    Define a default object
    default units are SI
    '''
    (sc, weatherers) = ObjForTests.mk_test_objs()
    spill = sc.spills[0]
    op = spill.substance
    volume = spill.get_mass() / op.density_at_temp(spill.water.temperature)

    thick = 1
    area = (0.5 * volume) / thick

    # test with non SI units
    burn = Burn(area,
                thick,
                active_range,
                area_units='km^2',
                thickness_units='km',
                efficiency=1.0)

    def test_init(self):
        '''
        active stop is ignored if set by user
        '''
        burn = Burn(self.area,
                    self.thick,
                    active_range=(active_start, InfDateTime('inf')),
                    name='test_burn',
                    on=False)  # this is ignored!

        # use burn constant for test - it isn't stored anywhere
        duration = (
            uc.convert('Length', burn.thickness_units, 'm', burn.thickness) -
            burn._min_thickness) / burn._burn_constant

        assert (burn.active_range[1] == burn.active_range[0] +
                timedelta(seconds=duration))
        assert burn.name == 'test_burn'
        assert not burn.on

    def test_update_active_start(self):
        '''
        active stop should be updated if we update active start or thickness
        '''
        burn = Burn(self.area,
                    self.thick,
                    active_range=(active_start, InfDateTime('inf')),
                    name='test_burn',
                    on=False)  # this is ignored!

        # use burn constant for test - it isn't stored anywhere
        duration = (
            (uc.convert('Length', burn.thickness_units, 'm', burn.thickness) -
             burn._min_thickness) / burn._burn_constant)

        assert (burn.active_range[1] == burn.active_range[0] +
                timedelta(seconds=duration))

        # after changing active start, active stop should still match the
        # duration.
        burn.active_range = (burn.active_range[0] + timedelta(days=1),
                             burn.active_range[1])
        assert (burn.active_range[1] == burn.active_range[0] +
                timedelta(seconds=duration))

    @mark.parametrize(("area_units", "thickness_units"), [("m", "in"),
                                                          ("m^2", "l")])
    def test_units_exception(self, area_units, thickness_units):
        ''' tests incorrect units raises exception '''
        with raises(uc.InvalidUnitError):
            self.burn.area_units = "in"

        with raises(uc.InvalidUnitError):
            self.burn.thickness_units = "m^2"

        with raises(uc.InvalidUnitError):
            Burn(10,
                 1, (datetime.now(), InfDateTime('inf')),
                 area_units=area_units,
                 thickness_units=thickness_units)

    def test_prepare_for_model_run(self):
        ''' check _oilwater_thickness, _burn_duration is reset'''
        self.burn._oilwater_thickness = 0.002  # reached terminal thickness
        self.burn.prepare_for_model_run(self.sc)
        assert (self.burn._oilwater_thickness == uc.convert(
            'Length', self.burn.thickness_units, 'm', self.burn.thickness))

    def test_prepare_for_model_step(self):
        '''
        once thickness reaches _min_thickness, test the mover becomes inactive
        if mover is off, it is also inactive
        '''
        self.burn.prepare_for_model_run(self.sc)
        self._oil_thickness = 0.002
        self.burn.prepare_for_model_step(self.sc, time_step, rel_time)
        assert not self.burn._active

        # turn it off
        self.burn.on = False
        self.burn.prepare_for_model_step(self.sc, time_step, rel_time)
        assert not self.burn._active

    def _weather_elements_helper(self, burn, avg_frac_water=0.0):
        '''
        refactored model run from test_weather_elements to this helper function
        It is also used by next test:
        test_elements_weather_slower_with_frac_water
        '''
        self.prepare_test_objs()

        model_time = rel_time
        burn.prepare_for_model_run(self.sc)

        # once burn becomes active, sc.mass_balance['burned'] > 0.0 and
        # burn becomes inactive once
        # burn._oil_thickness == burn._min_thickness
        step_num = 0
        while ((model_time > burn.active_range[0] and burn.active)
               or self.sc.mass_balance['burned'] == 0.0):

            num_rel = self.release_elements(time_step, model_time)
            if num_rel > 0:
                self.sc['frac_water'][:] = avg_frac_water

            self.step(burn, time_step, model_time)
            dt = timedelta(seconds=time_step)
            if (model_time + dt <= burn.active_range[0]
                    or model_time >= burn.active_range[1]):
                # if model_time + dt == burn.active start, then start the burn
                # in next step
                assert not burn.active
            else:
                assert burn.active

            model_time += dt
            step_num += 1

            if step_num > 100:
                # none of the tests take that long, so break it
                msg = "Test took more than 100 iterations for Burn, check test"
                raise Exception(msg)
                break

        # check that active stop is being correctly set
        assert InfDateTime('inf') > burn.active_range[1]
        print '\nCompleted steps: {0:2}'.format(step_num)

    @mark.parametrize(("thick", "avg_frac_water", "units"), [(0.003, 0, 'm'),
                                                             (1, 0, 'm'),
                                                             (1, 0.3, 'm'),
                                                             (100, 0.3, 'cm')])
    def test_weather_elements(self, thick, avg_frac_water, units):
        '''
        weather elements and test. frac_water is 0. Test thickness in units
        other than 'm'.

        1) tests the expected burned mass equals 'burned' amount stored in
           mass_balance
        2) also tests the mass_remaining is consistent with what we expect
        3) tests the mass of LEs set for burn equals the mass of oil given
           avg_frac_water and the thickness, and area. Since we cannot have
           a fraction of an LE, the difference should be within the mass of
           one LE.

        Also sets the 'frac_water' to 0.5 for one of the tests just to ensure
        it works.
        '''
        self.spill.num_elements = 500
        print 'starting num_elements = ', self.spill.num_elements
        print 'time_step = ', time_step

        thick_si = uc.convert('Length', units, 'm', thick)
        area = (0.5 * self.volume) / thick_si
        water = self.weatherers[0].water

        burn = Burn(area,
                    thick,
                    active_range,
                    thickness_units=units,
                    efficiency=1.0,
                    water=water)

        # return the initial value of burn._oil_thickness - this is starting
        # thickness of the oil
        self._weather_elements_helper(burn, avg_frac_water)

        # following should finally hold true for entire run
        v = self.sc.mass_balance['burned'] + self.sc['mass'].sum()
        assert np.allclose(amount, v, atol=1e-6)

        # want mass of oil thickness * area gives volume of oil-water so we
        # need to scale this by (1 - avg_frac_water)
        exp_burned = ((thick_si - burn._min_thickness) * burn.area *
                      (1 - avg_frac_water) *
                      self.op.density_at_temp(water.temperature))
        assert np.isclose(self.sc.mass_balance['burned'], exp_burned)

        mask = self.sc['fate_status'] & fate.burn == fate.burn

        # given LEs are discrete elements, we cannot add a fraction of an LE
        mass_per_le = self.sc['init_mass'][mask][0]
        exp_init_oil_mass = (burn.area * thick_si * (1 - avg_frac_water) *
                             self.op.density_at_temp(water.temperature))
        assert (
            self.sc['init_mass'][mask].sum() - exp_init_oil_mass < mass_per_le
            and self.sc['init_mass'][mask].sum() - exp_init_oil_mass >= 0.0)

        mass_remain_for_burn_LEs = self.sc['mass'][mask].sum()

        duration = (
            (burn.active_range[1] - burn.active_range[0]).total_seconds() /
            3600)
        print('Current Thickness: {0:.3f}, '
              'Duration (hrs): {1:.3f}').format(burn._oilwater_thickness,
                                                duration)

        exp_mass_remain = (burn._oilwater_thickness * burn.area *
                           (1 - avg_frac_water) *
                           self.op.density_at_temp(water.temperature))
        # since we don't adjust the thickness anymore need to use min_thick
        min_thick = .002
        exp_mass_remain = (min_thick * burn.area * (1.0 - avg_frac_water) *
                           self.op.density_at_temp(water.temperature))

        assert np.allclose(exp_mass_remain,
                           mass_remain_for_burn_LEs,
                           rtol=0.001)

    def test_elements_weather_faster_with_frac_water(self):
        '''
        Tests that avg_water_frac > 0 weathers faster
        '''
        self.spill.num_elements = 500
        area = (0.5 * self.volume) / 1.
        water = self.weatherers[0].water

        burn1 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn2 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn3 = Burn(area, 1., active_range, efficiency=1.0, water=water)

        self._weather_elements_helper(burn1)
        self._weather_elements_helper(burn2, avg_frac_water=0.3)
        self._weather_elements_helper(burn3, avg_frac_water=0.5)

        print "frac_water", 1.0, "burn_duration", \
            round((burn1.active_range[1] - burn1.active_range[0])
                  .total_seconds())
        print "frac_water", 0.3, "burn_duration", \
            round((burn2.active_range[1] - burn2.active_range[0])
                  .total_seconds())
        print "frac_water", 0.9, "burn_duration", \
            round((burn3.active_range[1] - burn3.active_range[0])
                  .total_seconds())
        assert (burn1.active_range[1] - burn1.active_range[0] <
                burn2.active_range[1] - burn2.active_range[0] <
                burn3.active_range[1] - burn3.active_range[0])

    def test_efficiency(self):
        '''
            tests efficiency.
            - If burn2 efficiency is 0.7 and burn1 efficiency is 1.0,
              then burn2_amount/burn1_amount = 0.7
            - Also checks the burn duration is not effected by efficiency

            The burn duration for both will be the same since efficiency only
            effects the amount of oil burned. The rate at which the oil/water
            mixture goes down to 2mm only depends on fractional water content.
        '''
        self.spill.num_elements = 500
        area = (0.5 * self.volume) / 1.
        eff = 0.7
        water = self.weatherers[0].water

        burn1 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn2 = Burn(area, 1., active_range, efficiency=eff, water=water)

        self._weather_elements_helper(burn1)
        amount_burn1 = self.sc.mass_balance['burned']
        self._weather_elements_helper(burn2)
        amount_burn2 = self.sc.mass_balance['burned']

        assert np.isclose(amount_burn2 / amount_burn1, eff)
        assert burn1.active_range == burn2.active_range

    def test_zero_efficiency(self):
        '''
            tests efficiency.
            - If burn2 efficiency is 0.0 and burn1 efficiency is 1.0,
              then burn2_amount/burn1_amount = 0.0
            - Also checks the burn duration is not effected by efficiency

            The burn duration for both will be the same since efficiency only
            effects the amount of oil burned. The rate at which the oil/water
            mixture goes down to 2mm only depends on fractional water content.
        '''
        self.spill.num_elements = 500
        area = (0.5 * self.volume) / 1.
        eff = 0.0
        water = self.weatherers[0].water

        burn1 = Burn(area, 1., active_range, efficiency=1.0, water=water)
        burn2 = Burn(area, 1., active_range, efficiency=eff, water=water)

        self._weather_elements_helper(burn1)
        amount_burn1 = self.sc.mass_balance['burned']

        with raises(Exception):
            self._weather_elements_helper(burn2)

        amount_burn2 = self.sc.mass_balance['burned']

        assert np.isclose(amount_burn2 / amount_burn1, eff)
        assert burn1.active_range == burn2.active_range
示例#16
0
def make_model(images_dir=os.path.join(base_dir, 'images')):
    print 'initializing the model'

    start_time = datetime(2012, 9, 15, 12, 0)
    mapfile = get_datafile(os.path.join(base_dir, './LongIslandSoundMap.BNA'))

    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=False, cache_enabled=False)

    print 'adding a spill'
    et = floating_weathering(substance='FUEL OIL NO.6')
    spill = point_line_release_spill(num_elements=1000,
                                     start_position=(-72.419992,
                                                     41.202120, 0.0),
                                     release_time=start_time,
                                     amount=1000,
                                     units='kg',
                                     element_type=et)
    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, (10, 45))
    series[1] = (start_time + timedelta(hours=18), (10, 90))
    series[2] = (start_time + timedelta(hours=30), (10, 135))
    series[3] = (start_time + timedelta(hours=42), (10, 180))
    series[4] = (start_time + timedelta(hours=54), (10, 225))

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

    print 'adding a cats mover:'
    curr_file = get_datafile(os.path.join(base_dir, r"./LI_tidesWAC.CUR"))
    tide_file = get_datafile(os.path.join(base_dir, r"./CLISShio.txt"))

    c_mover = CatsMover(curr_file, tide=Tide(tide_file))
    model.movers += c_mover

    model.environment += c_mover.tide

    print 'adding Weatherers'
    water_env = Water(311.15)
    model.environment += water_env
    model.weatherers += [Evaporation(water_env, wind),
                         Dispersion(),
                         Burn(),
                         Skimmer()]

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

    return model
示例#17
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
示例#18
0
             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,
                                   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)
示例#19
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
示例#20
0
def make_model(uncertain=False, mode='gnome'):
    '''
    Create a model from the data in sample_data/boston_data
    It contains:
      - the GeoProjection
      - wind mover
      - random mover
      - cats shio mover
      - cats ossm mover
      - plain cats mover
    '''
    start_time = datetime(2013, 2, 13, 9, 0)
    model = Model(start_time=start_time,
                  duration=timedelta(days=2),
                  time_step=timedelta(minutes=30).total_seconds(),
                  uncertain=uncertain,
                  map=MapFromBNA(testdata['boston_data']['map'],
                                 refloat_halflife=1),
                  mode=mode)

    print 'adding a spill'
    start_position = (144.664166, 13.441944, 0.0)
    end_release_time = start_time + timedelta(hours=6)
    spill_amount = 1000.0
    spill_units = 'kg'
    model.spills += point_line_release_spill(num_elements=1000,
                                             start_position=start_position,
                                             release_time=start_time,
                                             end_release_time=end_release_time,
                                             amount=spill_amount,
                                             units=spill_units,
                                             substance=test_oil)
    spill = model.spills[-1]
    spill_volume = spill.get_mass() / spill.substance.density_at_temp()
    # need a scenario for SimpleMover
    # model.movers += SimpleMover(velocity=(1.0, -1.0, 0.0))

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

    print 'adding a wind mover:'

    series = np.zeros((2, ), dtype=datetime_value_2d)
    series[0] = (start_time, (5, 180))
    series[1] = (start_time + timedelta(hours=18), (5, 180))

    w_mover = WindMover(Wind(timeseries=series, units='m/s'))

    model.movers += w_mover
    model.environment += w_mover.wind

    print 'adding a cats shio mover:'

    c_mover = CatsMover(testdata['boston_data']['cats_curr2'],
                        tide=Tide(testdata['boston_data']['cats_shio']))

    # c_mover.scale_refpoint should automatically get set from tide object
    c_mover.scale = True  # default value
    c_mover.scale_value = -1

    # tide object automatically gets added by model
    model.movers += c_mover

    print 'adding a cats ossm mover:'

    c_mover = CatsMover(testdata['boston_data']['cats_curr2'],
                        tide=Tide(testdata['boston_data']['cats_ossm']))

    c_mover.scale = True  # but do need to scale (based on river stage)
    c_mover.scale_refpoint = (-70.65, 42.58333, 0.0)
    c_mover.scale_value = 1.

    print 'adding a cats mover:'

    c_mover = CatsMover(testdata['boston_data']['cats_curr3'])
    c_mover.scale = True  # but do need to scale (based on river stage)
    c_mover.scale_refpoint = (-70.78333, 42.39333, 0.0)

    # the scale factor is 0 if user inputs no sewage outfall effects
    c_mover.scale_value = .04
    model.movers += c_mover

    # TODO: seg faulting for component mover - comment test for now
    # print "adding a component mover:"
    # comp_mover = ComponentMover(testdata['boston_data']['component_curr1'],
    #                             testdata['boston_data']['component_curr2'],
    #                             w_mover.wind)
    # TODO: callback did not work correctly below - fix!
    # comp_mover = ComponentMover(component_file1,
    #                             component_file2,
    #                             Wind(timeseries=series, units='m/s'))

    # comp_mover.ref_point = (-70.855, 42.275)
    # comp_mover.pat1_angle = 315
    # comp_mover.pat1_speed = 19.44
    # comp_mover.pat1_speed_units = 1
    # comp_mover.pat1ScaleToValue = .138855
    # comp_mover.pat2_angle = 225
    # comp_mover.pat2_speed = 19.44
    # comp_mover.pat2_speed_units = 1
    # comp_mover.pat2ScaleToValue = .05121

    # model.movers += comp_mover

    print 'adding a Weatherer'
    model.environment += Water(311.15)
    skim_start = start_time + timedelta(hours=3)
    model.weatherers += [
        Evaporation(),
        Skimmer(spill_amount * .5,
                spill_units,
                efficiency=.3,
                active_range=(skim_start, skim_start + timedelta(hours=2))),
        Burn(0.2 * spill_volume,
             1.0, (skim_start, InfDateTime('inf')),
             efficiency=0.9)
    ]

    model.outputters += \
        CurrentJsonOutput(model.find_by_attr('_ref_as', 'current_movers',
                                             model.movers, allitems=True))

    return model
示例#21
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