def test_mover_api(): ''' Test the API methods for adding and removing movers to the model. ''' start_time = datetime(2012, 1, 1, 0, 0) model = Model() model.duration = timedelta(hours=12) model.time_step = timedelta(hours=1) model.start_time = start_time mover_1 = SimpleMover(velocity=(1., -1., 0.)) mover_2 = SimpleMover(velocity=(1., -1., 0.)) mover_3 = SimpleMover(velocity=(1., -1., 0.)) mover_4 = SimpleMover(velocity=(1., -1., 0.)) # test our add object methods model.movers += mover_1 model.movers += mover_2 # test our get object methods assert model.movers[mover_1.id] == mover_1 assert model.movers[mover_2.id] == mover_2 with raises(KeyError): temp = model.movers['Invalid'] print temp # test our iter and len object methods assert len(model.movers) == 2 assert len([m for m in model.movers]) == 2 for (m1, m2) in zip(model.movers, [mover_1, mover_2]): assert m1 == m2 # test our add objectlist methods model.movers += [mover_3, mover_4] assert [m for m in model.movers] == [mover_1, mover_2, mover_3, mover_4] # test our remove object methods del model.movers[mover_3.id] assert [m for m in model.movers] == [mover_1, mover_2, mover_4] with raises(KeyError): # our key should also be gone after the delete temp = model.movers[mover_3.id] print temp # test our replace method model.movers[mover_2.id] = mover_3 assert [m for m in model.movers] == [mover_1, mover_3, mover_4] assert model.movers[mover_3.id] == mover_3 with raises(KeyError): # our key should also be gone after the delete temp = model.movers[mover_2.id] print temp
def test_callback_add_mover(): 'Test callback after add mover' units = 'meter per second' model = Model() model.start_time = datetime(2012, 1, 1, 0, 0) model.duration = timedelta(hours=10) model.time_step = timedelta(hours=1) # start_loc = (1.0, 2.0, 0.0) # random non-zero starting points # add Movers model.movers += SimpleMover(velocity=(1., -1., 0.)) series = np.array((model.start_time, (10, 45)), dtype=datetime_value_2d).reshape((1, )) model.movers += WindMover(Wind(timeseries=series, units=units)) # this should create a Wind object new_wind = Wind(timeseries=series, units=units) model.environment += new_wind assert new_wind in model.environment assert len(model.environment) == 2 tide_ = Tide(filename=testdata['CatsMover']['tide']) d_file = testdata['CatsMover']['curr'] model.movers += CatsMover(d_file, tide=tide_) model.movers += CatsMover(d_file) for mover in model.movers: assert mover.active_start == inf_datetime.InfDateTime('-inf') assert mover.active_stop == inf_datetime.InfDateTime('inf') if hasattr(mover, 'wind'): assert mover.wind in model.environment if hasattr(mover, 'tide'): if mover.tide is not None: assert mover.tide in model.environment # Add a mover with user defined active_start / active_stop values # - these should not be updated active_on = model.start_time + timedelta(hours=1) active_off = model.start_time + timedelta(hours=4) custom_mover = SimpleMover(velocity=(1., -1., 0.), active_start=active_on, active_stop=active_off) model.movers += custom_mover assert model.movers[custom_mover.id].active_start == active_on assert model.movers[custom_mover.id].active_stop == active_off
def test_simple_run_with_image_output_uncertainty(tmpdir): ''' Pretty much all this tests is that the model will run and output images ''' images_dir = tmpdir.mkdir('Test_images2').strpath if os.path.isdir(images_dir): shutil.rmtree(images_dir) os.mkdir(images_dir) start_time = datetime(2012, 9, 15, 12, 0) # the land-water map gmap = gnome.map.MapFromBNA(testdata['MapFromBNA']['testmap'], refloat_halflife=6) # hours renderer = gnome.outputters.Renderer(testdata['MapFromBNA']['testmap'], images_dir, size=(400, 300)) model = Model(start_time=start_time, time_step=timedelta(minutes=15), duration=timedelta(hours=1), map=gmap, uncertain=True, cache_enabled=False, ) model.outputters += renderer a_mover = SimpleMover(velocity=(1., -1., 0.)) model.movers += a_mover N = 10 # a line of ten points start_points = np.zeros((N, 3), dtype=np.float64) start_points[:, 0] = np.linspace(-127.1, -126.5, N) start_points[:, 1] = np.linspace(47.93, 48.1, N) # print start_points release = SpatialRelease(start_position=start_points, release_time=start_time) model.spills += Spill(release) # model.add_spill(spill) model.start_time = release.release_time # image_info = model.next_image() model.uncertain = True num_steps_output = 0 while True: try: image_info = model.step() num_steps_output += 1 print image_info except StopIteration: print 'Done with the model run' break # there is the zeroth step, too. calculated_steps = (model.duration.total_seconds() / model.time_step) + 1 assert num_steps_output == calculated_steps
def sample_model(): """ sample model with no outputter and no spills. Use this as a template for fixtures to add spills Uses: sample_data/MapBounds_Island.bna Contains: gnome.movers.SimpleMover(velocity=(1.0, -1.0, 0.0)) duration is 1 hour with 15min intervals so 5 timesteps total, including initial condition, model is uncertain and cache is not enabled No spills or outputters defined To use: add a spill and run :returns: It returns a dict - {'model':model, 'release_start_pos':start_points, 'release_end_pos':end_points} The release_start_pos and release_end_pos can be used by test to define the spill's 'start_position' and 'end_position' """ release_time = datetime(2012, 9, 15, 12, 0) # the image output map mapfile = os.path.join(os.path.dirname(__file__), 'sample_data', 'MapBounds_Island.bna') # the land-water map map_ = MapFromBNA(mapfile, refloat_halflife=06) # seconds model = Model( time_step=timedelta(minutes=15), start_time=release_time, duration=timedelta(hours=1), map=map_, uncertain=True, cache_enabled=False, ) model.movers += SimpleMover(velocity=(1., -1., 0.0)) model.uncertain = True start_points = np.zeros((3, ), dtype=np.float64) end_points = np.zeros((3, ), dtype=np.float64) start_points[:] = (-127.1, 47.93, 0) end_points[:] = (-126.5, 48.1, 0) return { 'model': model, 'release_start_pos': start_points, 'release_end_pos': end_points, }
def test_release_end_of_step(duration): ''' - Tests that elements released at end of step are recorded with their initial conditions with correct timestamp - Also tests the age is set correctly. todo: write separate test for checking age ''' model = Model(time_step=timedelta(minutes=15), duration=timedelta(hours=duration)) end_release_time = model.start_time + model.duration model.spills += point_line_release_spill(10, (0.0, 0.0, 0.0), model.start_time, end_release_time=end_release_time) model.movers += SimpleMover(velocity=(1., -1., 0.0)) print '\n---------------------------------------------' print 'model_start_time: {0}'.format(model.start_time) prev_rel = len(model.spills.LE('positions')) for step in model: new_particles = len(model.spills.LE('positions')) - prev_rel if new_particles > 0: assert np.all( model.spills.LE('positions')[-new_particles:, :] == 0) assert np.all(model.spills.LE('age')[-new_particles:] == 0) # assert np.all(model.spills.LE('age')[-new_particles:] == # (model.model_time + timedelta(seconds=model.time_step) # - model.start_time).seconds) if prev_rel > 0: assert np.all(model.spills.LE('positions')[:prev_rel, :2] != 0) assert np.all(model.spills.LE('age')[:prev_rel] >= model.time_step) prev_rel = len(model.spills.LE('positions')) print('current_time_stamp: {0}'.format( model.spills.LE('current_time_stamp'))) print 'particle ID: {0}'.format(model.spills.LE('id')) print 'positions: \n{0}'.format(model.spills.LE('positions')) print 'age: \n{0}'.format(model.spills.LE('age')) print 'just ran: %s' % step print 'particles released: %s' % new_particles print '---------------------------------------------' print '\n==============================================='
def test_simple_run_rewind(): ''' Pretty much all this tests is that the model will run and the seed is set during first run, then set correctly after it is rewound and run again ''' start_time = datetime(2012, 9, 15, 12, 0) model = Model() model.map = gnome.map.GnomeMap() a_mover = SimpleMover(velocity=(1., 2., 0.)) model.movers += a_mover assert len(model.movers) == 1 spill = point_line_release_spill(num_elements=10, start_position=(0., 0., 0.), release_time=start_time) model.spills += spill assert len(model.spills) == 1 # model.add_spill(spill) model.start_time = spill.release.release_time # test iterator for step in model: print 'just ran time step: %s' % model.current_time_step assert step['step_num'] == model.current_time_step pos = np.copy(model.spills.LE('positions')) # rewind and run again: print 'rewinding' model.rewind() # test iterator is repeatable for step in model: print 'just ran time step: %s' % model.current_time_step assert step['step_num'] == model.current_time_step assert np.all(model.spills.LE('positions') == pos)
def test_callback_add_mover_midrun(): 'Test callback after add mover called midway through the run' model = Model() model.start_time = datetime(2012, 1, 1, 0, 0) model.duration = timedelta(hours=10) model.time_step = timedelta(hours=1) # start_loc = (1.0, 2.0, 0.0) # random non-zero starting points # model = setup_simple_model() for i in range(2): model.step() assert model.current_time_step > -1 # now add another mover and make sure model rewinds model.movers += SimpleMover(velocity=(2., -2., 0.)) assert model.current_time_step == -1
def test_simple_run_with_map(): ''' pretty much all this tests is that the model will run ''' start_time = datetime(2012, 9, 15, 12, 0) model = Model() model.map = gnome.map.MapFromBNA(testdata['MapFromBNA']['testmap'], refloat_halflife=6) # hours a_mover = SimpleMover(velocity=(1., 2., 0.)) model.movers += a_mover assert len(model.movers) == 1 spill = point_line_release_spill(num_elements=10, start_position=(0., 0., 0.), release_time=start_time) model.spills += spill assert len(model.spills) == 1 model.start_time = spill.release.release_time # test iterator for step in model: print 'just ran time step: %s' % step assert step['step_num'] == model.current_time_step # reset and run again model.reset() # test iterator is repeatable for step in model: print 'just ran time step: %s' % step assert step['step_num'] == model.current_time_step
def make_model(images_dir=os.path.join(base_dir, 'images')): print 'initializing the model' # set up the modeling environment start_time = datetime(2016, 9, 23, 0, 0) model = Model(start_time=start_time, duration=timedelta(days=2), time_step=30 * 60, uncertain=False) print 'adding the map' model.map = GnomeMap() # this is a "water world -- no land anywhere" # renderere is only top-down view on 2d -- but it's something renderer = Renderer(output_dir=images_dir, image_size=(1024, 768), output_timestep=timedelta(hours=1), ) renderer.viewport = ((196.14, 71.89), (196.18, 71.93)) print 'adding outputters' model.outputters += renderer # Also going to write the results out to a netcdf file netcdf_file = os.path.join(base_dir, 'script_arctic_plume.nc') scripting.remove_netcdf(netcdf_file) model.outputters += NetCDFOutput(netcdf_file, which_data='most', # output most of the data associated with the elements output_timestep=timedelta(hours=2)) print "adding Horizontal and Vertical diffusion" # Horizontal Diffusion model.movers += RandomMover(diffusion_coef=500) # vertical diffusion (different above and below the mixed layer) model.movers += RandomMover3D(vertical_diffusion_coef_above_ml=5, vertical_diffusion_coef_below_ml=.11, mixed_layer_depth=10) print 'adding Rise Velocity' # droplets rise as a function of their density and radius model.movers += TamocRiseVelocityMover() print 'adding a circular current and eastward current' fn = 'hycom_glb_regp17_2016092300_subset.nc' fn_ice = 'hycom-cice_ARCu0.08_046_2016092300_subset.nc' iconc = IceConcentration.from_netCDF(filename=fn_ice) ivel = IceVelocity.from_netCDF(filename=fn_ice, grid = iconc.grid) ic = IceAwareCurrent.from_netCDF(ice_concentration = iconc, ice_velocity= ivel, filename=fn) model.movers += PyCurrentMover(current = ic) model.movers += SimpleMover(velocity=(0., 0., 0.)) model.movers += constant_wind_mover(20, 315, units='knots') # Now to add in the TAMOC "spill" print "Adding TAMOC spill" model.spills += tamoc_spill.TamocSpill(release_time=start_time, start_position=(196.16, 71.91, 40.0), num_elements=1000, end_release_time=start_time + timedelta(days=1), name='TAMOC plume', TAMOC_interval=None, # how often to re-run TAMOC ) model.spills[0].data_sources['currents'] = ic return model
def make_model(images_dir=os.path.join(base_dir, 'images')): print 'initializing the model' start_time = datetime(2004, 12, 31, 13, 0) model = Model(start_time=start_time, duration=timedelta(days=3), time_step=30 * 60, uncertain=False) print 'adding the map' model.map = GnomeMap() # 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( output_dir=images_dir, # size=(800, 600), output_timestep=timedelta(hours=1), draw_ontop='uncertain') renderer.viewport = ((-76.5, 37.), (-75.8, 38.)) print 'adding outputters' model.outputters += renderer netcdf_file = os.path.join(base_dir, 'script_plume.nc') scripting.remove_netcdf(netcdf_file) model.outputters += NetCDFOutput(netcdf_file, which_data='most', output_timestep=timedelta(hours=2)) print 'adding two spills' # Break the spill into two spills, first with the larger droplets # and second with the smaller droplets. # Split the total spill volume (100 m^3) to have most # in the larger droplet spill. # Smaller droplets start at a lower depth than larger wd = WeibullDistribution(alpha=1.8, lambda_=.00456, min_=.0002) # 200 micron min end_time = start_time + timedelta(hours=24) # spill = point_line_release_spill(num_elements=10, # amount=90, # default volume_units=m^3 # units='m^3', # start_position=(-76.126872, 37.680952, # 1700), # release_time=start_time, # end_release_time=end_time, # element_type=plume(distribution=wd, # density=600) # ) spill = subsurface_plume_spill( num_elements=10, start_position=(-76.126872, 37.680952, 1700), release_time=start_time, distribution=wd, amount=90, # default volume_units=m^3 units='m^3', end_release_time=end_time, density=600) model.spills += spill wd = WeibullDistribution(alpha=1.8, lambda_=.00456, max_=.0002) # 200 micron max spill = point_line_release_spill( num_elements=10, amount=90, units='m^3', start_position=(-76.126872, 37.680952, 1800), release_time=start_time, element_type=plume(distribution=wd, substance_name='oil_crude')) model.spills += spill print 'adding a RandomMover:' model.movers += RandomMover(diffusion_coef=50000) print 'adding a RiseVelocityMover:' model.movers += RiseVelocityMover() print 'adding a RandomVerticalMover:' model.movers += RandomVerticalMover(vertical_diffusion_coef_above_ml=5, vertical_diffusion_coef_below_ml=.11, mixed_layer_depth=10) # print 'adding a wind mover:' # series = np.zeros((2, ), dtype=gnome.basic_types.datetime_value_2d) # series[0] = (start_time, (30, 90)) # series[1] = (start_time + timedelta(hours=23), (30, 90)) # wind = Wind(timeseries=series, units='knot') # # default is .4 radians # w_mover = gnome.movers.WindMover(wind, uncertain_angle_scale=0) # # model.movers += w_mover print 'adding a simple mover:' s_mover = SimpleMover(velocity=(0.0, -.3, 0.0)) model.movers += s_mover return model
from gnome.movers import RandomMover l_spills = [point_line_release_spill(10, (0, 0, 0), datetime.now().replace(microsecond=0), name='sp1'), point_line_release_spill(15, (0, 0, 0), datetime.now().replace(microsecond=0), name='sp2'), point_line_release_spill(20, (0, 0, 0), datetime.now().replace(microsecond=0), name='sp3'), point_line_release_spill(5, (0, 0, 0), datetime.now().replace(microsecond=0), name='sp4')] l_mv = [SimpleMover(velocity=(1, 2, 3)), RandomMover()] def define_mdl(test=0): ''' WebAPI will update/replace nested objects so do that for the test as well Setup some test cases: 0 - empty model w/ no changes 1 - model with l_mv and l_spills but no changes 2 - empty model but add l_mv and l_spills to json_ so it changed 3 - add l_mv and l_spills to model, then delete some elements and update via json ''' def get_json(mdl): json_ = mdl.serialize()
# For WindMover test_save_load in test_wind_mover g_objects = ( GridCurrent.from_netCDF(testdata['GridCurrentMover']['curr_tri']), Tide(testdata['CatsMover']['tide']), Wind(filename=testdata['ComponentMover']['wind']), Wind(timeseries=(sec_to_date(24 * 60 * 60), (0, 0)), units='mps'), Water(temperature=273), RandomMover(), CatsMover(testdata['CatsMover']['curr']), CatsMover(testdata['CatsMover']['curr'], tide=Tide(testdata['CatsMover']['tide'])), ComponentMover(testdata['ComponentMover']['curr']), ComponentMover(testdata['ComponentMover']['curr'], wind=Wind(filename=testdata['ComponentMover']['wind'])), RandomMover3D(), 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,
def test_all_movers(start_time, release_delay, duration): ''' Tests that all the movers at least can be run Add new ones as they come along! ''' model = Model() model.time_step = timedelta(hours=1) model.duration = timedelta(seconds=model.time_step * duration) model.start_time = start_time start_loc = (1., 2., 0.) # random non-zero starting points # a spill - release after 5 timesteps release_time = (start_time + timedelta(seconds=model.time_step * release_delay)) model.spills += point_line_release_spill(num_elements=10, start_position=start_loc, release_time=release_time) # the land-water map model.map = gnome.map.GnomeMap() # the simplest of maps # simple mover model.movers += SimpleMover(velocity=(1., -1., 0.)) assert len(model.movers) == 1 # random mover model.movers += RandomMover(diffusion_coef=100000) assert len(model.movers) == 2 # wind mover series = np.array((start_time, (10, 45)), dtype=datetime_value_2d).reshape( (1, )) model.movers += WindMover(Wind(timeseries=series, units='meter per second')) assert len(model.movers) == 3 # CATS mover model.movers += CatsMover(testdata['CatsMover']['curr']) assert len(model.movers) == 4 # run the model all the way... num_steps_output = 0 for step in model: num_steps_output += 1 print 'running step:', step # test release happens correctly for all cases if release_delay < duration: # at least one get_move has been called after release assert np.all(model.spills.LE('positions')[:, :2] != start_loc[:2]) elif release_delay == duration: # particles are released after last step so no motion, # only initial _state assert np.all(model.spills.LE('positions') == start_loc) else: # release_delay > duration so nothing released though model ran assert len(model.spills.LE('positions')) == 0 # there is the zeroth step, too. calculated_steps = (model.duration.total_seconds() / model.time_step) + 1 assert num_steps_output == calculated_steps
def make_model(images_dir=os.path.join(base_dir, 'images')): print 'initializing the model' # set up the modeling environment start_time = datetime(2004, 12, 31, 13, 0) model = Model(start_time=start_time, duration=timedelta(days=3), time_step=30 * 60, uncertain=False) print 'adding the map' model.map = GnomeMap() # this is a "water world -- no land anywhere" # renderere is only top-down view on 2d -- but it's something renderer = Renderer( output_dir=images_dir, size=(1024, 768), output_timestep=timedelta(hours=1), ) renderer.viewport = ((-.15, -.35), (.15, .35)) print 'adding outputters' model.outputters += renderer # Also going to write the results out to a netcdf file netcdf_file = os.path.join(base_dir, 'script_plume.nc') scripting.remove_netcdf(netcdf_file) model.outputters += NetCDFOutput( netcdf_file, which_data='most', # output most of the data associated with the elements output_timestep=timedelta(hours=2)) print "adding Horizontal and Vertical diffusion" # Horizontal Diffusion # model.movers += RandomMover(diffusion_coef=5) # vertical diffusion (different above and below the mixed layer) model.movers += RandomVerticalMover(vertical_diffusion_coef_above_ml=5, vertical_diffusion_coef_below_ml=.11, mixed_layer_depth=10) print 'adding Rise Velocity' # droplets rise as a function of their density and radius model.movers += RiseVelocityMover() print 'adding a circular current and eastward current' # This is .3 m/s south model.movers += PyCurrentMover(current=vg, default_num_method='Trapezoid', extrapolate=True) model.movers += SimpleMover(velocity=(0., -0.1, 0.)) # Now to add in the TAMOC "spill" print "Adding TAMOC spill" model.spills += tamoc_spill.TamocSpill( release_time=start_time, start_position=(0, 0, 1000), num_elements=1000, end_release_time=start_time + timedelta(days=1), name='TAMOC plume', TAMOC_interval=None, # how often to re-run TAMOC ) return model