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 chemical_disperson_obj(spill, delay_hours=1, duration=1): ''' apply chemical dispersion to 10% of spill ''' rel_time = spill.get('release_time') disp_start = rel_time + timedelta(hours=delay_hours) return ChemicalDispersion(.1, active_start=disp_start, active_stop=(disp_start + timedelta(hours=duration)), efficiency=0.3)
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 test_set_efficiency(self): ''' for wave height > 6.4 m, efficiency goes to 0 ''' # make wind large so efficiency goes to 0 waves = Waves(constant_wind(0, 0), water=Water()) c_disp = ChemicalDispersion(self.spill_pct, active_range, waves=waves) pts = np.array([[0, 0], [0, 0]]) c_disp._set_efficiency(pts, self.spill.release_time) assert c_disp.efficiency == 1.0 c_disp.efficiency = 0 waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0)) c_disp._set_efficiency(pts, self.spill.release_time) assert np.all(c_disp.efficiency == 0)
def test_set_efficiency(self): ''' for wave height > 6.4 m, efficiency goes to 0 ''' # make wind large so efficiency goes to 0 waves = Waves(constant_wind(0, 0), water=Water()) c_disp = ChemicalDispersion(self.spill_pct, active_start, active_stop, waves=waves) c_disp._set_efficiency(self.spill.release_time) assert c_disp.efficiency == 1.0 c_disp.efficiency = None waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0)) c_disp._set_efficiency(self.spill.release_time) assert c_disp.efficiency == 0
def test_set_efficiency(self): ''' for wave height > 6.4 m, efficiency goes to 0 ''' # make wind large so efficiency goes to 0 waves = Waves(constant_wind(0, 0), water=Water()) c_disp = ChemicalDispersion(self.spill_pct, active_start, active_stop, waves=waves) c_disp._set_efficiency(self.spill.get('release_time')) assert c_disp.efficiency == 1.0 c_disp.efficiency = None waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0)) c_disp._set_efficiency(self.spill.get('release_time')) assert c_disp.efficiency == 0
class TestChemicalDispersion(ObjForTests): (sc, weatherers) = ObjForTests.mk_test_objs() spill = sc.spills[0] op = spill.substance spill_pct = 0.2 # 20% c_disp = ChemicalDispersion(spill_pct, active_range, efficiency=0.3) def test_prepare_for_model_run(self): ''' test efficiency gets set correctly ''' self.prepare_test_objs() assert 'chem_dispersed' not in self.sc.mass_balance self.c_disp.prepare_for_model_run(self.sc) assert self.sc.mass_balance['chem_dispersed'] == 0.0 def test_set_efficiency(self): ''' for wave height > 6.4 m, efficiency goes to 0 ''' # make wind large so efficiency goes to 0 waves = Waves(constant_wind(0, 0), water=Water()) c_disp = ChemicalDispersion(self.spill_pct, active_range, waves=waves) pts = np.array([[0, 0], [0, 0]]) c_disp._set_efficiency(pts, self.spill.release_time) assert c_disp.efficiency == 1.0 c_disp.efficiency = 0 waves.wind.timeseries = (waves.wind.timeseries[0]['time'], (100, 0)) c_disp._set_efficiency(pts, self.spill.release_time) assert np.all(c_disp.efficiency == 0) @mark.parametrize("efficiency", (0.5, 1.0)) def test_prepare_for_model_step(self, efficiency): ''' updated: efficiency now does impact the mass of LEs marked as having been sprayed. precent_sprayed also impacts the mass of LEs marked as disperse. ''' self.reset_and_release() self.c_disp.efficiency = efficiency assert np.all(self.sc['fate_status'] == fate.surface_weather) self.c_disp.prepare_for_model_run(self.sc) self.c_disp.prepare_for_model_step(self.sc, time_step, active_start) d_mass = self.sc['mass'][self.sc['fate_status'] == fate.disperse].sum() assert d_mass == (self.c_disp.fraction_sprayed * self.spill.get_mass() * efficiency) exp_mass = (self.spill.get_mass() * self.c_disp.fraction_sprayed * efficiency) assert d_mass - exp_mass < self.sc['mass'][0] @mark.parametrize("frac_water", (0.5, 0.0)) def test__update_LE_status_codes(self, frac_water): ''' efficiency does not impact the mass of LEs marked as having been sprayed. precent_sprayed determines percent of LEs marked as disperse. ''' self.reset_and_release() self.sc['frac_water'][:] = frac_water assert np.all(self.sc['fate_status'] == fate.surface_weather) self.c_disp.prepare_for_model_run(self.sc) self.c_disp.prepare_for_model_step(self.sc, time_step, active_start) d_mass = self.sc['mass'][self.sc['fate_status'] == fate.disperse].sum() assert d_mass == self.c_disp.fraction_sprayed * self.spill.get_mass() exp_mass = self.spill.get_mass() * self.c_disp.fraction_sprayed assert d_mass - exp_mass < self.sc['mass'][0] @mark.parametrize("efficiency", (1.0, 0.7)) def test_weather_elements(self, efficiency): self.prepare_test_objs() self.c_disp.efficiency = efficiency self.c_disp.prepare_for_model_run(self.sc) assert self.sc.mass_balance['chem_dispersed'] == 0.0 model_time = self.spill.release_time while (model_time < self.c_disp.active_range[1] + timedelta(seconds=time_step)): amt_disp = self.sc.mass_balance['chem_dispersed'] self.release_elements(time_step, model_time) self.step(self.c_disp, time_step, model_time) if not self.c_disp.active: assert self.sc.mass_balance['chem_dispersed'] == amt_disp else: assert self.sc.mass_balance['chem_dispersed'] > amt_disp model_time += timedelta(seconds=time_step) assert np.allclose(amount, self.sc.mass_balance['chem_dispersed'] + self.sc['mass'].sum(), atol=1e-6) assert np.allclose( self.sc.mass_balance['chem_dispersed'] / self.spill.get_mass(), self.c_disp.fraction_sprayed * efficiency)
start_position=(0, 0, 0)), spill.point_line_release_spill(10, (0, 0, 0), datetime.now()), spill.substance.Substance(windage_range=(0.05, 0.07)), spill.substance.GnomeOil(test_oil, windage_range=(0.05, 0.07)), spill.substance.NonWeatheringSubstance(windage_range=(0.05, 0.07)), Skimmer(amount=100, efficiency=0.3, active_range=(datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)), units='kg'), Burn(area=100, thickness=1, active_range=(datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)), efficiency=.9), ChemicalDispersion(fraction_sprayed=.2, active_range=(datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)), efficiency=.3), # todo: ask Caitlin how to fix # movers.RiseVelocityMover(), # todo: This is incomplete - no _schema for # SpatialRelease, GeoJson # spill.SpatialRelease(datetime.now(), ((0, 0, 0), (1, 2, 0))), TrajectoryGeoJsonOutput(), ) @pytest.mark.parametrize("obj", g_objects) def test_serial_deserial(saveloc_, obj): 'test save/load functionality' json_ = obj.serialize() obj2 = obj.__class__.deserialize(json_)
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
NetCDFOutput(os.path.join(base_dir, u'xtemp.nc')), Renderer(testdata['Renderer']['bna_sample'], os.path.join(base_dir, 'output_dir')), WeatheringOutput(), spill.PointLineRelease(release_time=datetime.now(), num_elements=10, start_position=(0, 0, 0)), spill.point_line_release_spill(10, (0, 0, 0), datetime.now()), spill.elements.ElementType(substance=test_oil), Skimmer(100, 'kg', 0.3, (datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0))), Burn(100, 1, (datetime(2014, 1, 1, 0, 0), InfDateTime('inf')), efficiency=.9), ChemicalDispersion( .2, (datetime(2014, 1, 1, 0, 0), datetime(2014, 1, 1, 4, 0)), efficiency=.3), # todo: ask Caitlin how to fix # movers.RiseVelocityMover(), # todo: This is incomplete - no _schema for # SpatialRelease, GeoJson # spill.SpatialRelease(datetime.now(), ((0, 0, 0), (1, 2, 0))), TrajectoryGeoJsonOutput(), ) @pytest.mark.parametrize("obj", g_objects) def test_serial_deserial(saveloc_, obj): 'test save/load functionality' json_ = obj.serialize() obj2 = obj.__class__.deserialize(json_)
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