def test_dissolution(oil, temp, num_elems, on): ''' Fuel Oil #6 does not exist... ''' et = floating(substance=oil) diss = Dissolution(waves) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et, num_elements=num_elems)[:2] print 'num spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount model_time = (sc.spills[0].get('release_time') + timedelta(seconds=time_step)) diss.on = on diss.prepare_for_model_run(sc) diss.initialize_data(sc, sc.num_released) diss.prepare_for_model_step(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) if on: print sc._data_arrays assert all(np.isclose(sc._data_arrays['partition_coeff'], 511.445)) assert sc.mass_balance['dissolution'] > 0 print "sc.mass_balance['dissolution']" print sc.mass_balance['dissolution'] else: assert 'dissolution' not in sc.mass_balance
def test_dissolution_k_ow(oil, temp, num_elems, k_ow, on): ''' Here we are testing that the molar averaged oil/water partition coefficient (K_ow) is getting calculated with reasonable values ''' et = floating(substance=oil) diss = Dissolution(waves) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et, num_elements=num_elems)[:2] print 'num spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount # we don't want to query the oil database, but get the sample oil assert sc.spills[0].element_type.substance.record.id is None model_time = (sc.spills[0].release_time + timedelta(seconds=time_step)) diss.on = on diss.prepare_for_model_run(sc) diss.initialize_data(sc, sc.num_released) diss.prepare_for_model_step(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) assert all(np.isclose(sc._data_arrays['partition_coeff'], k_ow))
def test_prepare_for_model_run(): 'test sort order for Dissolution weatherer' diss = Dissolution(waves, wind) (sc, _time_step) = weathering_data_arrays(diss.array_types, water)[:2] assert 'partition_coeff' in sc.data_arrays assert 'dissolution' not in sc.mass_balance diss.prepare_for_model_run(sc) assert 'dissolution' in sc.mass_balance
def test_prepare_for_model_run(): 'test sort order for Dissolution weatherer' et = floating(substance='ABU SAFAH') diss = Dissolution(waves) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et)[:2] assert 'partition_coeff' in sc.data_arrays assert 'dissolution' not in sc.mass_balance diss.prepare_for_model_run(sc) assert 'dissolution' in sc.mass_balance
def test_sort_order(): 'test sort order for Dissolution weatherer' wind = constant_wind(15., 0) waves = Waves(wind, Water()) diss = Dissolution(waves) assert weatherer_sort(diss) == 8
def test_prepare_for_model_run(): 'test sort order for Dissolution weatherer' et = floating(substance='oil_bahia') diss = Dissolution(waves) # we don't want to query the oil database, but get the sample oil assert et.substance.record.id is None (sc, _time_step) = weathering_data_arrays(diss.array_types, water, element_type=et)[:2] assert 'partition_coeff' in sc.data_arrays assert 'dissolution' not in sc.mass_balance diss.prepare_for_model_run(sc) assert 'dissolution' in sc.mass_balance
def test_init(): 'test initialization' wind = constant_wind(15., 0) waves = Waves(wind, Water()) diss = Dissolution(waves) print diss.array_types assert all([(at in diss.array_types) for at in ('mass', 'viscosity', 'density')])
def test_dissolution_droplet_size(oil, temp, num_elems, drop_size, on): ''' Here we are testing that the molar averaged oil/water partition coefficient (K_ow) is getting calculated with reasonable values ''' et = floating(substance=oil) disp = NaturalDispersion(waves, water) diss = Dissolution(waves) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et, num_elements=num_elems)[:2] print 'num_spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount, sc.spills[0].units model_time = (sc.spills[0] .release_time + timedelta(seconds=time_step)) print 'model_time = ', model_time print 'time_step = ', time_step # we don't want to query the oil database, but get the sample oil assert sc.spills[0].element_type.substance.record.id is None disp.on = on diss.on = on disp.prepare_for_model_run(sc) diss.prepare_for_model_run(sc) disp.initialize_data(sc, sc.num_released) diss.initialize_data(sc, sc.num_released) for i in range(3): disp.prepare_for_model_step(sc, time_step, model_time) diss.prepare_for_model_step(sc, time_step, model_time) disp.weather_elements(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) print 'droplet_avg_size:', sc._data_arrays['droplet_avg_size'] assert np.allclose(sc._data_arrays['droplet_avg_size'], drop_size[i])
def test_full_run_no_evap(sample_model_fcn2, oil, temp, expected_balance): ''' test dissolution outputs post step for a full run of model. Dump json for 'weathering_model.json' in dump directory ''' low_wind = constant_wind(1., 270, 'knots') low_waves = Waves(low_wind, Water(temp)) model = sample_model_weathering2(sample_model_fcn2, oil, temp) model.environment += [Water(temp), low_wind, low_waves] # model.weatherers += Evaporation(Water(temp), low_wind) model.weatherers += NaturalDispersion(low_waves, Water(temp)) model.weatherers += Dissolution(low_waves, low_wind) print ('Model start time: {}, Duration: {}, Time step: {}' .format(model.start_time, model.duration, model.time_step)) for sc in model.spills.items(): print '\nSpill dict keys: ', sc.__dict__.keys() print '\nSpill data arrays: ', sc._data_arrays print 'num spills:', len(sc.spills) print ('spill[0] amount: {} {} ({})' .format(sc.spills[0].amount, sc.spills[0].units, sc.spills[0].substance.name) ) original_amount = sc.spills[0].amount # set make_default_refs to True for objects contained in model after adding # objects to the model model.set_make_default_refs(True) model.setup_model_run() dissolved = [] for step_num, step in enumerate(model): for sc in model.spills.items(): if step['step_num'] > 0: assert (sc.mass_balance['dissolution'] > 0) assert (sc.mass_balance['natural_dispersion'] > 0) assert (sc.mass_balance['sedimentation'] > 0) dissolved.append(sc.mass_balance['dissolution']) print ('\n#Step: {}'.format(step_num)) print ("Dissolved: {0}". format(sc.mass_balance['dissolution'])) print ("Mass: {0}". format(sc._data_arrays['mass'])) print ("Mass Components: {0}". format(sc._data_arrays['mass_components'])) print ('Fraction dissolved after full run: {}' .format(dissolved[-1] / original_amount)) assert dissolved[0] == 0.0 assert np.isclose(dissolved[-1], expected_balance)
def test_serialize_deseriailize(): 'test serialize/deserialize for webapi' wind = constant_wind(15., 0) water = Water() waves = Waves(wind, water) diss = Dissolution(waves) json_ = diss.serialize() pp.pprint(json_) assert json_['waves'] == waves.serialize() # deserialize and ensure the dict's are correct d_ = Dissolution.deserialize(json_) assert d_['waves'] == Waves.deserialize(json_['waves']) d_['waves'] = waves diss.update_from_dict(d_) assert diss.waves is waves
def test_full_run(sample_model_fcn2, oil, temp, expected_balance): ''' test dissolution outputs post step for a full run of model. Dump json for 'weathering_model.json' in dump directory ''' model = sample_model_weathering2(sample_model_fcn2, oil, temp) model.environment += [Water(temp), wind, waves] model.weatherers += Evaporation() model.weatherers += NaturalDispersion() model.weatherers += Dissolution(waves, wind) for sc in model.spills.items(): print sc.__dict__.keys() print sc._data_arrays print 'num spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount original_amount = sc.spills[0].amount # we don't want to query the oil database, but get the sample oil #assert sc.spills[0].substance.record.id is None # set make_default_refs to True for objects contained in model after adding # objects to the model model.set_make_default_refs(True) model.setup_model_run() dissolved = [] for step in model: for sc in model.spills.items(): if step['step_num'] > 0: assert (sc.mass_balance['dissolution'] > 0) assert (sc.mass_balance['natural_dispersion'] > 0) assert (sc.mass_balance['sedimentation'] > 0) dissolved.append(sc.mass_balance['dissolution']) # print ("\nDissolved: {0}". # format(sc.mass_balance['dissolution'])) # print ("Mass: {0}". # format(sc._data_arrays['mass'])) # print ("Mass Components: {0}". # format(sc._data_arrays['mass_components'])) print ('Fraction dissolved after full run: {}' .format(dissolved[-1] / original_amount)) assert dissolved[0] == 0.0 assert np.isclose(dissolved[-1], expected_balance, rtol=1e-4)
def test_sort_order(): 'test sort order for Dissolution weatherer' wind = constant_wind(15., 0) waves = Waves(wind, Water()) diss = Dissolution(waves, wind) disp = NaturalDispersion(waves=waves, water=waves.water) weathering_data = WeatheringData(water=waves.water) # dissolution is dependent upon droplet distribution generated by # natural dispersion assert weatherer_sort(disp) < weatherer_sort(diss) # dissolution needs to happen before we treat our weathering data assert weatherer_sort(diss) < weatherer_sort(weathering_data)
def test_full_run_dissolution_not_active(sample_model_fcn): 'no water/wind/waves object and no evaporation' model = sample_model_weathering(sample_model_fcn, 'oil_4') model.environment += [Water(288.7), wind, waves] model.weatherers += Evaporation() model.weatherers += NaturalDispersion() model.weatherers += Dissolution(waves=waves, wind=wind, on=False) model.outputters += WeatheringOutput() for step in model: ''' if no weatherers, then no weathering output - need to add on/off switch to WeatheringOutput ''' assert 'dissolution' not in step['WeatheringOutput'] assert ('time_stamp' in step['WeatheringOutput']) print ("Completed step: {0}".format(step['step_num']))
def test_dissolution_not_active(oil, temp, num_elems): ''' Fuel Oil #6 does not exist... ''' diss = Dissolution(waves) et = floating(substance=oil) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et)[:2] sc.amount = 10000 model_time = (sc.spills[0].get('release_time') + timedelta(seconds=time_step)) diss.prepare_for_model_run(sc) new_model_time = (sc.spills[0].get('release_time') + timedelta(seconds=3600)) diss.active_start = new_model_time diss.prepare_for_model_step(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) assert np.all(sc.mass_balance['dissolution'] == 0)
def test__deserialize(): 'test serialize/deserialize for webapi' wind = constant_wind(15., 0) water = Water() waves = Waves(wind, water) diss = Dissolution(waves, wind) json_ = diss.serialize() pp.pprint(json_) assert json_['waves'] == waves.serialize() # deserialize and ensure the dict's are correct d_ = Dissolution.deserialize(json_) assert d_['waves'] == Waves.deserialize(json_['waves']) d_['waves'] = waves diss.update_from_dict(d_) assert diss.waves is waves
def test_dissolution_mass_balance(oil, temp, num_elems, expected_mb, on): ''' Fuel Oil #6 does not exist... ''' et = floating(substance=oil) diss = Dissolution(waves) (sc, time_step) = weathering_data_arrays(diss.array_types, water, element_type=et, num_elements=num_elems)[:2] print 'num spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount model_time = (sc.spills[0].get('release_time') + timedelta(seconds=time_step)) diss.on = on diss.prepare_for_model_run(sc) diss.initialize_data(sc, sc.num_released) diss.prepare_for_model_step(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) if on: assert np.isclose(sc.mass_balance['dissolution'], expected_mb) else: assert 'dissolution' not in sc.mass_balance
def test_dissolution_droplet_size(oil, temp, num_elems, drop_size, on): ''' Here we are testing that the molar averaged oil/water partition coefficient (K_ow) is getting calculated with reasonable values ''' disp = NaturalDispersion(waves, water) diss = Dissolution(waves, wind) (sc, time_step) = weathering_data_arrays(diss.array_types, water, num_elements=num_elems)[:2] print 'num_spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount, sc.spills[0].units model_time = (sc.spills[0] .release_time + timedelta(seconds=time_step)) print 'model_time = ', model_time print 'time_step = ', time_step # we don't want to query the oil database, but get the sample oil #assert sc.spills[0].substance.record.id is None disp.on = on diss.on = on disp.prepare_for_model_run(sc) diss.prepare_for_model_run(sc) disp.initialize_data(sc, sc.num_released) diss.initialize_data(sc, sc.num_released) for i in range(3): disp.prepare_for_model_step(sc, time_step, model_time) diss.prepare_for_model_step(sc, time_step, model_time) disp.weather_elements(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) print 'droplet_avg_size:', sc._data_arrays['droplet_avg_size'] assert np.allclose(sc._data_arrays['droplet_avg_size'], drop_size[i])
def test_dissolution_k_ow(oil, temp, num_elems, k_ow, on): ''' Here we are testing that the molar averaged oil/water partition coefficient (K_ow) is getting calculated with reasonable values Note: for now droplets are calculated in natural dispersion so natural dispersion is required for the dissolution algorithm ''' diss = Dissolution(waves, wind) disp = NaturalDispersion(waves, water) (sc, time_step) = weathering_data_arrays(diss.array_types, water, substance=oil, num_elements=num_elems)[:2] print 'num spills:', len(sc.spills) print 'spill[0] amount:', sc.spills[0].amount # we don't want to query the oil database, but get the sample oil #assert sc.spills[0].substance.record.id is None model_time = (sc.spills[0].release_time + timedelta(seconds=time_step)) disp.on = on diss.on = on disp.prepare_for_model_run(sc) diss.prepare_for_model_run(sc) disp.initialize_data(sc, sc.num_released) diss.initialize_data(sc, sc.num_released) disp.prepare_for_model_step(sc, time_step, model_time) diss.prepare_for_model_step(sc, time_step, model_time) disp.weather_elements(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) assert all(np.isclose(sc._data_arrays['partition_coeff'], k_ow))
def test_dissolution_mass_balance(oil, temp, wind_speed, num_elems, expected_mb, on): ''' Test a single dissolution step. - for this, we need a dispersion weatherer to give us a droplet size distribution. Fuel Oil #6 does not exist... ''' et = floating(substance=oil) waves = build_waves_obj(wind_speed, 'knots', 270, temp) water = waves.water disp = NaturalDispersion(waves, water) diss = Dissolution(waves) all_array_types = diss.array_types.union(disp.array_types) (sc, time_step) = weathering_data_arrays(all_array_types, water, element_type=et, num_elements=num_elems, units='kg', amount_per_element=1.0 )[:2] print 'time_step: {}'.format(time_step) print 'num spills:', len(sc.spills) print 'spill[0] amount: {} {}'.format(sc.spills[0].amount, sc.spills[0].units) print 'temperature = ', temp print 'wind = ', print '\n'.join(['\t{} {}'.format(ts[1][0], waves.wind.units) for ts in waves.wind.timeseries]) print # we don't want to query the oil database, but get the sample oil assert sc.spills[0].element_type.substance.record.id is None initial_amount = sc.spills[0].amount model_time = (sc.spills[0].release_time + timedelta(seconds=time_step)) disp.on = on disp.prepare_for_model_run(sc) disp.initialize_data(sc, sc.num_released) diss.on = on diss.prepare_for_model_run(sc) diss.initialize_data(sc, sc.num_released) disp.prepare_for_model_step(sc, time_step, model_time) diss.prepare_for_model_step(sc, time_step, model_time) disp.weather_elements(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) if on: print ('fraction dissolved: {}' .format(sc.mass_balance['dissolution'] / initial_amount) ) print ('fraction dissolved: {:.2%}' .format(sc.mass_balance['dissolution'] / initial_amount) ) print sc.mass_balance['dissolution'], expected_mb assert np.isclose(sc.mass_balance['dissolution'], expected_mb) else: assert 'dissolution' not in sc.mass_balance
def make_model(): """ Set up a GNOME simulation that uses TAMOC Set up a spill scenario in GNOME that uses TAMOC to simulate a subsurface blowout and then pass the TAMOC solution to GNOME for the far-field particle tracking """ # Set up the directory structure for the model base_dir, images_dir, outfiles_dir = set_directory_structure() # Set up the modeling environment print '\n-- Initializing the Model --' start_time = "2019-06-01T12:00" model = gs.Model(start_time=start_time, duration=gs.days(3), time_step=gs.minutes(30), uncertain=False) # Add a map print '\n-- Adding a Map --' model.map = gs.GnomeMap() # Add image output print '\n-- Adding Image Outputters --' renderer = gs.Renderer(output_dir=images_dir, image_size=(1024, 768), output_timestep=gs.hours(1), viewport=((-0.15, -0.35), (0.15, 0.35))) model.outputters += renderer # Add NetCDF output print '\n-- Adding NetCDF Outputter --' if not os.path.exists(outfiles_dir): os.mkdir(outfiles_dir) netcdf_file = os.path.join(outfiles_dir, 'script_tamoc.nc') gs.remove_netcdf(netcdf_file) file_writer = gs.NetCDFOutput(netcdf_file, which_data='all', output_timestep=gs.hours(2)) model.outputters += file_writer # Add a spill object print '\n-- Adding a Point Spill --' end_release_time = model.start_time + gs.hours(12) point_source = ts.TamocSpill(num_elements=100, start_position=(0.0, 0.0, 1000.), release_duration=gs.hours(24), release_time=start_time, substance='AD01554', release_rate=20000., units='bbl/day', gor=500., d0=0.5, phi_0=-np.pi / 2., theta_0=0., windage_range=(0.01, 0.04), windage_persist=900, name='Oil Well Blowout') model.spills += point_source # Create an ocean environment water, wind, waves = base_environment(water_temp=273.15 + 21., wind_speed=5., wind_dir=225.) # Add a uniform current in the easterly direction print '\n-- Adding Currents --' uniform_current = gs.SimpleMover(velocity=(0.1, 0.0, 0.)) model.movers += uniform_current # Add a wind mover wind_mover = gs.WindMover(wind) model.movers += wind_mover # Add particle diffusion...note, units are in cm^2/s print '\n-- Adding Particle Diffusion --' particle_diffusion = gs.RandomMover3D( horizontal_diffusion_coef_above_ml=100000., horizontal_diffusion_coef_below_ml=10000., vertical_diffusion_coef_above_ml=100., vertical_diffusion_coef_below_ml=10., mixed_layer_depth=15.) model.movers += particle_diffusion # Add rise velocity for droplets print '\n-- Adding Particle Rise Velocity --' # fixme: we do have code for rise velocity: # gnome.movers.RiseVelocityMover # let's test that later slip_velocity = gs.SimpleMover(velocity=(0.0, 0.0, -0.1)) model.movers += slip_velocity # Add dissolution print '\n-- Adding Weathering --' evaporation = Evaporation(water=water, wind=wind) model.weatherers += evaporation dissolution = Dissolution(waves=waves, wind=wind) model.weatherers += dissolution return model
def test_sort_order(): assert weatherer_sort(Dissolution()) > weatherer_sort(NaturalDispersion())
def test_dissolution_mass_balance(oil, temp, wind_speed, num_elems, expected_mb, on): ''' Test a single dissolution step. - for this, we need a dispersion weatherer to give us a droplet size distribution. Fuel Oil #6 does not exist... ''' waves = build_waves_obj(wind_speed, 'knots', 270, temp) wind = waves.wind water = waves.water disp = NaturalDispersion(waves, water) diss = Dissolution(waves, wind) all_array_types = diss.array_types.union(disp.array_types) (sc, time_step) = weathering_data_arrays(all_array_types, water, num_elements=num_elems, units='kg', amount_per_element=1.0 )[:2] print 'time_step: {}'.format(time_step) print 'num spills:', len(sc.spills) print 'spill[0] amount: {} {}'.format(sc.spills[0].amount, sc.spills[0].units) print 'temperature = ', temp print 'wind = ', print '\n'.join(['\t{} {}'.format(ts[1][0], waves.wind.units) for ts in waves.wind.timeseries]) print # we don't want to query the oil database, but get the sample oil #assert sc.spills[0].substance.record.id is None initial_amount = sc.spills[0].amount model_time = (sc.spills[0].release_time + timedelta(seconds=time_step)) disp.on = on disp.prepare_for_model_run(sc) disp.initialize_data(sc, sc.num_released) diss.on = on diss.prepare_for_model_run(sc) diss.initialize_data(sc, sc.num_released) disp.prepare_for_model_step(sc, time_step, model_time) diss.prepare_for_model_step(sc, time_step, model_time) disp.weather_elements(sc, time_step, model_time) diss.weather_elements(sc, time_step, model_time) if on: print ('fraction dissolved: {}' .format(sc.mass_balance['dissolution'] / initial_amount) ) print ('fraction dissolved: {:.2%}' .format(sc.mass_balance['dissolution'] / initial_amount) ) print sc.mass_balance['dissolution'], expected_mb assert np.isclose(sc.mass_balance['dissolution'], expected_mb, rtol=1e-4) else: assert 'dissolution' not in sc.mass_balance