def make_skimmer(spill, delay_hours=1, duration=2): 'make a skimmer for sample model tests' rel_time = spill.get('release_time') skim_start = rel_time + timedelta(hours=delay_hours) amount = spill.amount units = spill.units skimmer = Skimmer(.3 * amount, units=units, efficiency=0.3, active_start=skim_start, active_stop=skim_start + timedelta(hours=duration)) return skimmer
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)
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_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 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
class TestSkimmer(ObjForTests): (sc, weatherers) = ObjForTests.mk_test_objs() skimmer = Skimmer(amount, units='kg', efficiency=0.3, active_range=active_range, water=weatherers[0].water) def test_prepare_for_model_run(self): self.reset_and_release() self.skimmer.prepare_for_model_run(self.sc) assert self.sc.mass_balance['skimmed'] == 0. assert (self.skimmer._rate == ( self.skimmer.amount / (self.skimmer.active_range[1] - self.skimmer.active_range[0]).total_seconds())) @mark.parametrize( ("model_time", "active", "ts"), [ (active_range[0], True, time_step), (active_range[0] - timedelta(seconds=time_step / 3.), True, time_step * 2. / 3.), # between active start - active stop (active_range[0] + timedelta(seconds=time_step / 2.), True, time_step), # between active start - active stop (active_range[1], False, None), (active_range[1] - timedelta(seconds=time_step), True, time_step), # before active stop (active_range[1] - timedelta(seconds=time_step / 3.), True, time_step / 3.) # before active stop ]) def test_prepare_for_model_step(self, model_time, active, ts): ''' assert that the _timestep property is being set correctly. This is less than or equal to time_step specified by model. Since we define a rate object, this is just to ensure the amount Skimmed between the duration specified matches given a constant skim rate. ''' self.reset_and_release() self.skimmer.prepare_for_model_step(self.sc, time_step, model_time) assert self.skimmer.active is active if active: assert self.skimmer._timestep == ts mask = self.sc['fate_status'] & fate.skim == fate.skim assert mask.sum() > 0 @mark.parametrize("avg_frac_water", [0.0, 0.4]) def test_weather_elements(self, avg_frac_water): ''' Test only the mass removed due to Skimmer operation: 1) sc['mass'] + sc.mass_balance['skimmed'] = spill_amount 2) sc.mass_balance['skimmed']/skimmer.amount = skimmer.efficiency ''' self.prepare_test_objs() self.skimmer.prepare_for_model_run(self.sc) assert self.sc.mass_balance['skimmed'] == 0.0 model_time = rel_time while (model_time < self.skimmer.active_range[1] + timedelta(seconds=2 * time_step)): amt_skimmed = self.sc.mass_balance['skimmed'] num_rel = self.release_elements(time_step, model_time) if num_rel > 0: self.sc['frac_water'][:] = avg_frac_water self.step(self.skimmer, time_step, model_time) if not self.skimmer.active: assert self.sc.mass_balance['skimmed'] == amt_skimmed else: # check total amount removed at each timestep assert self.sc.mass_balance['skimmed'] > amt_skimmed model_time += timedelta(seconds=time_step) # check - useful for debugging issues with recursion assert np.isclose( amount, (self.sc.mass_balance['skimmed'] + self.sc['mass'].sum())) # following should finally hold true for entire run assert np.allclose(amount, self.sc.mass_balance['skimmed'] + self.sc['mass'].sum(), atol=1e-6) # efficiency decreased since only (1 - avg_frac_water) is the fraction # of oil collected by skimmer assert np.allclose(self.sc.mass_balance['skimmed'] / self.skimmer.amount, self.skimmer.efficiency * (1 - avg_frac_water), atol=1e-6)
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
SimpleMover(velocity=(10.0, 10.0, 0.0)), map.MapFromBNA(testdata['MapFromBNA']['testmap'], 6), NetCDFOutput(os.path.join(base_dir, u'xtemp.nc')), Renderer(testdata['Renderer']['bna_sample'], os.path.join(base_dir, 'output_dir')), WeatheringOutput(), spill.PointLineRelease(release_time=datetime.now(), num_elements=10, start_position=(0, 0, 0)), spill.point_line_release_spill(10, (0, 0, 0), datetime.now()), spill.substance.Substance(windage_range=(0.05, 0.07)), spill.substance.GnomeOil(test_oil, windage_range=(0.05, 0.07)), spill.substance.NonWeatheringSubstance(windage_range=(0.05, 0.07)), Skimmer(amount=100, efficiency=0.3, active_range=(datetime(2014, 1, 1, 0, 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))),
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(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
ComponentMover(testdata['ComponentMover']['curr']), ComponentMover(testdata['ComponentMover']['curr'], wind=Wind(filename=testdata['ComponentMover']['wind'])), 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(), )
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