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
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
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))
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
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_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
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)
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)
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
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)
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)
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
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):
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
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
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
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)
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
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
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