def get_volume(self, units=None): """ return the volume released during the spill. The default units for volume are as defined in 'volume_units' property. User can also specify desired output units in the function. """ if self._volume is None: return self._volume if units is None: return unit_conversion.convert('Volume', 'm^3', self.volume_units, self._volume) else: self._check_units(units) return unit_conversion.convert('Volume', 'm^3', units, self._volume)
def Calculate(self, depth, gas_oil_ratio, oil_jet_velocity=None, oil_jet_density=None, source_pressure=None, output_metric=False): if oil_jet_velocity and oil_jet_density: # N/m^2 or Pa units (Pascals) # equavelent to 950 psi source_pressure = (oil_jet_density * (oil_jet_velocity ** 2)) / 2 elif not source_pressure: raise ValueError('need either ' 'oil_jet_velocity and oil_jet_density, ' 'or source_pressure') if self.metric_inputs: depth = convert('Length', 'meter', 'foot', depth) gas_oil_ratio = Volume.CubicMeterRatioToScfPerStb(gas_oil_ratio) source_pressure = Force.PascalsToPsi(source_pressure) # Start-Equation 1.5, page 8 # Calculating ambient pressure outside leak at depth in psi. # We will go off the document, but here are some considerations # regarding this calculation: # - The ambient atmospheric pressure at sea level is not constant. # It varies with the weather, but averages around 100 kPa # One bar is 100kPa or approximately ambient pressure at sea level # - One atmosphere(atm) is also approximately the ambient pressure # at sea level and is equal to 14.7 psi or 1.01325 bar # - Ambient water pressure increases linearly with depth. # Roughly, each 10 meters (33 ft) of depth adds another bar # to the ambient pressure. Assuming the density of sea water # to be 1025 kg/m^3 (in fact it is slightly variable), # pressure increases by 1 atm with each 10 m of depth ambient_pressure_at_depth = self.ambient_pressure_at_sea_level + (0.446533 * depth); # Start-Equation 1.4, page 8 # The relative pressure, deltaPrel, difference over the leak point is relative_pressure_delta = source_pressure / ambient_pressure_at_depth # Start- Table 1.3, page 11 # Maximum released volume fraction, frel max_release_fraction, max_release_occurrence = self.release_fraction_lu[relative_pressure_delta] # Start-Section 1.3.5 # # Table 1.4 GOR reduction factors, page 11 gor_reduction_factor = self.gor_reduction_factor_lu.get_gas_oil_reduction_factor(gas_oil_ratio, max_release_occurrence) if output_metric: source_pressure = Force.PsiToPascals(source_pressure) ambient_pressure_at_depth = Force.PsiToPascals(ambient_pressure_at_depth) max_release_occurrence = Volume.ScfPerStbToCubicMeterRatio(max_release_occurrence) return self.gor_results(source_pressure, ambient_pressure_at_depth, relative_pressure_delta, max_release_fraction, max_release_occurrence, gor_reduction_factor)
def _convert_units(self, data, ts_format, from_unit, to_unit): ''' Private method to convert units for the 'value' stored in the date/time value pair ''' if from_unit != to_unit: data[:, 0] = unit_conversion.convert('Velocity', from_unit, to_unit, data[:, 0]) if ts_format == basic_types.ts_format.uv: # TODO: avoid clobbering the 'ts_format' namespace data[:, 1] = unit_conversion.convert('Velocity', from_unit, to_unit, data[:, 1]) return data
def test_invalid_unit_convert(): with pytest.raises(unit_conversion.InvalidUnitError): unit_conversion.convert("length", "flintstones", "meters", 1.0) with pytest.raises(unit_conversion.InvalidUnitError): unit_conversion.convert("length", "feet", "flintstones", 1.0) with pytest.raises(unit_conversion.InvalidUnitError): unit_conversion.convert("temperature", "feet", "C", 1.0) with pytest.raises(unit_conversion.InvalidUnitError): unit_conversion.convert("temperature", "f", "feet", 1.0)
def set_volume(self, volume, units): """ set the volume released during the spill. The default units for volume are as defined in 'volume_units' property. User can also specify desired output units in the function. """ self._check_units(units) self._volume = unit_conversion.convert('Volume', units, 'm^3', volume) self.volume_units = units
def get_density(self, units='kg/m^3'): """ :param units=kg/m^3: optional input if output units should be something other than kg/m^3 """ if self.oil.api is None: raise ValueError("Oil with name '{0}' does not contain 'api'"\ " property.".format(self.oil.name)) if units not in self.valid_density_units: raise unit_conversion.InvalidUnitError("Desired density units"\ " must be from following list to be valid: {0}".\ format(self.valid_density_units)) # since Oil object can have various densities depending on temperature, # lets return API in correct units return unit_conversion.convert('Density', 'API degree', units, self.oil.api)
def test_read_file_init(): """ initialize from a long wind file """ wind = environment.Wind(filename=file_) wm = WindMover(wind) wind_ts = wind.get_timeseries(format='uv', units='meter per second') _defaults(wm) # check defaults set correctly cpp_timeseries = _get_timeseries_from_cpp(wm) _assert_timeseries_equivalence(cpp_timeseries, wind_ts) # make sure default units is correct and correctly called # NOTE: Following functionality is already tested in test_wind.py, # but what the heck - do it here too. wind_ts = wind.get_timeseries(format=ts_format.uv) cpp_timeseries['value'] = unit_conversion.convert('Velocity', 'meter per second', wind.units, cpp_timeseries['value']) _assert_timeseries_equivalence(cpp_timeseries, wind_ts)
def test_wind_circ_fixture(wind_circ): """ check 'uv' values for wind_circ fixture are correct """ wm = wind_circ['wind'] # output is in knots gtime_val = wm.get_timeseries(format='uv').view(dtype=np.recarray) assert np.all(gtime_val.time == wind_circ['uv'].time) assert np.allclose(gtime_val.value, wind_circ['uv'].value, atol, rtol) # output is in meter per second gtime_val = wm.get_timeseries(format='uv', units='meter per second' ).view(dtype=np.recarray) expected = unit_conversion.convert('Velocity', wm.units, 'meter per second', wind_circ['uv'].value) assert np.all(gtime_val.time == wind_circ['uv'].time) assert np.allclose(gtime_val.value, expected, atol, rtol)
def test_init(wind_circ): """ figure out how to pass the parameter to above fixture """ wm = wind_circ['wind'] # output is in knots gtime_val = wm.get_timeseries(format='uv').view(dtype=np.recarray) assert np.all(gtime_val.time == wind_circ['uv'].time) assert np.allclose(gtime_val.value, wind_circ['uv'].value, atol, rtol) # output is in meter per second gtime_val = wm.get_timeseries(format='uv', units='meter per second' ).view(dtype=np.recarray) expected = unit_conversion.convert('Velocity', wm.units, 'meter per second', wind_circ['uv'].value) assert np.all(gtime_val.time == wind_circ['uv'].time) assert np.allclose(gtime_val.value, expected, atol, rtol)
def __init__( self, release, element_type=None, on=True, volume=None, volume_units='m^3', # Is this total mass of the spill? mass=None, mass_units='g', id=None, ): """ Base spill class. Spill used by a gnome model derive from this class :param num_elements: number of LEs - default is 0. :type num_elements: int Optional parameters (kwargs): :param on: Toggles the spill on/off (bool). Default is 'on'. :type on: bool :type id: str :param volume: oil spilled volume (used to compute mass per particle) Default is None. :type volume: float :param volume_units=m^3: volume units :type volume_units: str :param windage_range=(0.01, 0.04): the windage range of the elements default is (0.01, 0.04) from 1% to 4%. :type windage_range: tuple: (min, max) :param windage_persist=-1: Default is 900s, so windage is updated every 900 sec. -1 means the persistence is infinite so it is only set at the beginning of the run. :type windage_persist: integer seconds :param id: Unique Id identifying the newly created mover (a UUID as a string), used when loading from a persisted model :param element_type=None: list of various element_type that are released. These are spill specific properties of the elements. :type element_type: list of gnome.element_type.* objects """ #self.num_elements = num_elements self.release = release if element_type is None: element_type = elements.floating() self.element_type = element_type self.on = on # spill is active or not # mass/volume, type of oil spilled self._check_units(volume_units) self._volume_units = volume_units # user defined for display self._volume = volume if volume is not None: self._volume = unit_conversion.convert('Volume', volume_units, 'm^3', volume) self._check_units(mass_units, 'Mass') self._mass_units = mass_units # user defined for display self._mass = mass if mass is not None: self._mass = uc.convert('Mass', mass_units, 'g', mass) if mass is not None and volume is not None: raise ValueError("'mass' and 'volume' cannot both be set") #============================================================================== # if windage_range is not None: # if 'windages' not in self.element_type.initializers: # raise TypeError("'windage_range' cannot be set for specified" # " element_type: {0}".format(element_type)) # (self.element_type.initializers['windages']).windage_range = \ # windage_range # # if windage_persist is not None: # if 'windages' not in self.element_type.initializers: # raise TypeError("'windage_persist' cannot be set for specified" # " element_type: {0}".format(element_type)) # (self.element_type.initializers['windages']).windage_persist = \ # windage_persist #============================================================================== self._gnome_id = GnomeId(id)
def __init__( self, num_elements=0, on=True, volume=None, volume_units='m^3', mass=None, mass_units='g', oil='oil_conservative', windage_range=None, windage_persist=None, element_type=None, id=None, ): """ Base spill class. Spill used by a gnome model derive from this class :param num_elements: number of LEs - default is 0. :type num_elements: int Optional parameters (kwargs): :param on: Toggles the spill on/off (bool). Default is 'on'. :type on: bool :type id: str :param volume: oil spilled volume (used to compute mass per particle) Default is None. :type volume: float :param volume_units=m^3: volume units :type volume_units: str :param oil='oil_conservative': Type of oil spilled. If this is a string, or an oillibrary.models.Oil object, then create gnome.spill.OilProps(oil) object. If this is a gnome.spill.OilProps object, then simply instance oil_props variable to it: self.oil_props = oil :type oil: either str, or oillibrary.models.Oil object or gnome.spill.OilProps :param windage_range: A tuple defining the min/max % of wind acting on each LE. Default (0.01, 0.04) :type windage_range: a tuple of size 2 (min, max) :param id: Unique Id identifying the newly created mover (a UUID as a string), used when loading from a persisted model :param element_type=None: list of various element_type that are released. These are spill specific properties of the elements. :type element_type: list of gnome.element_type.* objects """ self.num_elements = num_elements self.on = on # spill is active or not # mass/volume, type of oil spilled self._check_units(volume_units) self._volume_units = volume_units # user defined for display self._volume = volume if volume is not None: self._volume = unit_conversion.convert('Volume', volume_units, 'm^3', volume) self.oil_props = OilProps(oil) self._gnome_id = GnomeId(id) if element_type is None: element_type = elements.Floating() self.element_type = element_type if windage_range is not None: if 'windages' not in self.element_type.initializers: raise TypeError("'windage_range' cannot be set for specified" " element_type: {0}".format(element_type)) (self.element_type.initializers['windages']).windage_range = \ windage_range if windage_persist is not None: if 'windages' not in self.element_type.initializers: raise TypeError("'windage_persist' cannot be set for specified" " element_type: {0}".format(element_type)) (self.element_type.initializers['windages']).windage_persist = \ windage_persist # number of new particles released at each timestep self.num_released = 0 self.elements_not_released = True # flag determines if the first time is valid. If the first call to # self.num_elements_to_release(current_time, time_step) has # current_time > self.release_time, then no particles are ever released # if current_time <= self.release_time, then toggle this flag since # model start time is valid self.start_time_invalid = True
from hazpy import unit_conversion import sqlalchemy from hazpy import unit_conversion from itertools import chain from gnome.db.oil_library.models import Oil, DBSession from gnome.db.oil_library.initializedb import initialize_sql, \ load_database from gnome.utilities.remote_data import get_datafile # Some standard oils - scope is module level, non-public _sample_oils = { 'oil_gas': {'Oil Name': 'oil_gas', 'API': unit_conversion.convert('Density', 'gram per cubic centimeter', 'API degree', 0.75)}, 'oil_jetfuels': {'Oil Name': 'oil_jetfuels', 'API': unit_conversion.convert('Density', 'gram per cubic centimeter', 'API degree', 0.81)}, 'oil_diesel': {'Oil Name': 'oil_diesel', 'API': unit_conversion.convert('Density', 'gram per cubic centimeter', 'API degree', 0.87)}, 'oil_4': {'Oil Name': 'oil_4', 'API': unit_conversion.convert('Density', 'gram per cubic centimeter', 'API degree', 0.90)}, 'oil_crude': {'Oil Name': 'oil_crude', 'API': unit_conversion.convert('Density', 'gram per cubic centimeter', 'API degree', 0.90)},