Exemple #1
0
    def __init__(self, area, **kwargs):
        self.area = area
        super(ConstantArea, self).__init__(**kwargs)

        self.array_types.update({
            'area': gat('area'),
            'fay_area': gat('fay_area')
        })
    def __init__(self, waves=None, **kwargs):

        if 'arctic' not in kwargs:
            self.arctic = False  # default is a temperate conditions (>6 deg C)
        else:
            self.arctic = kwargs.pop('arctic')

        self.waves = waves

        super(Biodegradation, self).__init__(**kwargs)

        self.array_types.update({
            'mass': gat('mass'),
            'mass_components': gat('mass_components'),
            'droplet_avg_size': gat('droplet_avg_size'),
            'positions': gat('positions'),
            'yield_factor': gat('yield_factor'),
        })

        #
        # Original bio degradation formula:
        #
        #  m(j, t+1) = m(j, t0) * exp(-K(j) * A(t) / M(t))
        #
        #  where
        #    m(j, t + 1) - mass of pseudocomponent j at time step t + 1
        #    K(j) - biodegradation rate constant for pseudocomponent j
        #    A(t) - droplet surface area at time step t
        #    M(t) - droplet mass at time step t
        #
        # Since
        #
        #  A(t) / M(t) = 6 / (d(t) * ro(t))
        #
        # where
        #   d(t) - droplet diameter at time step t
        #   ro(t) - droplet density at time step t
        #
        # follows this formula for bio degradation:
        #
        #  m(j, t+1) = m(j, t0) * exp(-6 * K(j) / (d(t) * ro(t)))
        #
        # and then interative bio degradation formula:
        #
        #  m(j, t+1) = m(j, t) * exp(6 * K(j) *
        #    (1 / (d(t-1) * ro(t-1)) - 1 / (d(t) * ro(t))))
        #
        # where
        #  d(t-1) - droplet diameter at previous (t-1) time step
        #  ro(t-1) - droplet density at previous (t-1) time step
        #
        # So we will keep previous time step specific surface value
        # (squre meter per kilogram) or yield_factor =  1 / (d * ro)
        #

        self.prev_yield_factor = None
Exemple #3
0
    def __init__(self,
                 release_time=None,
                 num_elements=0,
                 release_mass=0,
                 **kwargs):

        self.num_elements = num_elements
        self.release_time = asdatetime(release_time)
        self.release_mass = release_mass
        self.rewind()
        super(Release, self).__init__(**kwargs)
        self.array_types.update({
            'positions': gat('positions'),
            'mass': gat('mass'),
            'init_mass': gat('mass')
        })
Exemple #4
0
    def __init__(self, distribution=None, **kwargs):
        """
        Set the rise velocity parameters to be sampled from a distribution.

        :param distribution: An object capable of generating a probability
                             distribution.
        :type distribution:
            Right now, we have:
             * UniformDistribution
             * NormalDistribution
             * LogNormalDistribution
             * WeibullDistribution
            New distribution classes could be made.  The only
            requirement is they need to have a set_values()
            method which accepts a NumPy array.
            (presumably, this function will also modify
             the array in some way)
        """
        super(InitRiseVelFromDist, self).__init__(**kwargs)

        if distribution:
            self.distribution = distribution
        else:
            raise TypeError('InitRiseVelFromDist requires a distribution for '
                            'rise velocities')

        self.array_types['rise_vel'] = gat('rise_vel')
        self.name = 'rise_vel'
Exemple #5
0
 def __init__(self):
     """
     update array_types
     """
     super(InitMassFromPlume, self).__init__()
     self.array_types['mass'] = gat('mass')
     self.name = 'mass'
Exemple #6
0
    def __init__(self, name=None, water=None, **kwargs):
        oil_info = name
        if name in _sample_oils:
            oil_info = _sample_oils[name]
        elif isinstance(name, six.string_types):
            # check if it's json from save file or from client
            if kwargs.get('component_density', False):
                oil_info = kwargs
            else:                
                from oil_library import get_oil_props
                if kwargs.get('adios_oil_id', False): 
                    # init the oilprops from dictionary, old form
                    oil_obj = get_oil_props(kwargs)
                else: 
                    # use name to get oil from oil library
                    oil_obj = get_oil_props(name) 
                oil_info = oil_obj.get_gnome_oil()
                
            kwargs['name'] = name #this is important; it passes name up to GnomeId to be handled there!
        else:
            raise ValueError('Must provide an oil name or OilLibrary.Oil '
                             'to GnomeOil init')

        Oil.__init__(self, **oil_info)

        # because passing oilLibrary kwargs makes problem up the tree,
        # only pass up the kwargs specified in the schema
        keys = self._schema().get_nodes_by_attr('all')
        if 'windage_range' in kwargs:
            keys.append('windage_range')
        if 'windage_persist' in kwargs:
            keys.append('windage_persist')
        k2 = dict([(key, kwargs.get(key)) for key in keys])
        read_only_attrs = GnomeOil._schema().get_nodes_by_attr('read_only')
        for n in read_only_attrs:
            k2.pop(n, None)
        k2.pop('water')
        Substance.__init__(self, **k2)

        self.water = water

        # add the array types that this substance DIRECTLY initializes
        self.array_types.update({'density': gat('density'),
                                 'viscosity': gat('viscosity'),
                                 'mass_components': gat('mass_components')})
        self.array_types['mass_components'].shape = (self.num_components,)
        self.array_types['mass_components'].initial_value = (self.mass_fraction,)
Exemple #7
0
    def __init__(self, waves=None, wind=None, **kwargs):
        '''
            :param waves: waves object for obtaining wave_height, etc. at a
                          given time
        '''
        self.waves = waves
        self.wind = wind

        if waves is not None and wind is not None:
            make_default_refs = False
        else:
            make_default_refs = True

        super(Dissolution, self).__init__(make_default_refs=make_default_refs,
                                          **kwargs)

        self.array_types.update({
            'area': gat('area'),
            'mass': gat('mass'),
            'density': gat('density'),
            'positions': gat('positions'),
            'viscosity': gat('viscosity'),
            'partition_coeff': gat('partition_coeff'),
            'droplet_avg_size': gat('droplet_avg_size')
        })
Exemple #8
0
    def __init__(self, water=None, thickness_limit=None, **kwargs):
        '''
        initialize object - invoke super, add required data_arrays.
        '''
        super(FayGravityViscous, self).__init__(**kwargs)
        self.spreading_const = (1.53, 1.21)

        # need water temp to get initial viscosity of oil so thickness_limit
        # can be set
        # fixme: can use nominal viscosity!
        self.water = water
        self.array_types.update({
            'fay_area': gat('fay_area'),
            'area': gat('area'),
            'bulk_init_volume': gat('bulk_init_volume'),
            'age': gat('age'),
            'density': gat('density'),
            'frac_coverage': gat('frac_coverage'),
            'spill_num': gat('spill_num')
        })
        # relative_buoyancy - use density at release time. For now
        # temperature is fixed so just compute once and store. When temperature
        # varies over time, may want to do something different
        self._init_relative_buoyancy = None
        self.thickness_limit = thickness_limit
        self.is_first_step = True
Exemple #9
0
    def __init__(self, water=None, wind=None, **kwargs):
        '''
        :param conditions: gnome.environment.Conditions object which contains
            things like water temperature
        :param wind: wind object for obtaining speed at specified time
        :type wind: Wind API, specifically must have get_value(time) method
        '''
        self.water = water
        self.wind = wind

        if water is not None and wind is not None:
            make_default_refs = False
        else:
            make_default_refs = True

        super(Evaporation, self).__init__(make_default_refs=make_default_refs,
                                          **kwargs)
        self.array_types.update({
            'positions':
            gat('positions'),
            'area':
            gat('area'),
            'evap_decay_constant':
            gat('evap_decay_constant'),
            'frac_water':
            gat('frac_water'),
            'frac_lost':
            gat('frac_lost'),
            'frac_evap':
            gat('frac_evap'),
            'init_mass':
            gat('init_mass')
        })
Exemple #10
0
    def __init__(self, **kwargs):
        '''
        Base weatherer class; defines the API for all weatherers
        Passes optional arguments to base (Process) class via super. See base
        class for optional arguments:  `gnome.movers.mover.Process`

        adds 'mass_components', 'mass' to array_types since all weatherers
        need these.
        '''
        super(Weatherer, self).__init__(**kwargs)

        # arrays that all weatherers will update - use this to ask
        self.array_types.update({
            'mass_components': gat('mass_components'),
            'fate_status': gat('fate_status'),
            'mass': gat('mass'),
            'init_mass': gat('init_mass')
        })
Exemple #11
0
    def __init__(self, efficiency=1.0, **kwargs):
        '''
        add 'frac_water' to array_types and pass **kwargs to base class
        __init__ using super
        '''
        self._efficiency = None
        self.efficiency = efficiency

        super(CleanUpBase, self).__init__(**kwargs)

        self.array_types.update({'frac_water': gat('frac_water')})
Exemple #12
0
def test_LEData_prep():
    arrtypes = {'area': gat('area')}

    dat = LEData()
    dat.prepare_for_model_run(arrtypes, 0)
    assert 'area' in dat._array_types
    assert dat['area'].shape == (0, )
    assert dat['positions'].shape == (0, 3)
    assert dat._bufs['area'].shape == (100, )
    assert dat._bufs['positions'].shape == (100, 3)
    assert len(dat) == 0
Exemple #13
0
    def __init__(self, distribution=None,
                 water_density=1020.0, water_viscosity=1.0e-6,
                 **kwargs):
        """
        Set the droplet size from a distribution. Use the C++ get_rise_velocity
        function exposed via cython (rise_velocity_from_drop_size) to obtain
        rise_velocity from droplet size. Even though the droplet size is not
        changing over time, it is still stored in data array, as it can be
        useful for post-processing (called 'droplet_diameter')

        :param distribution: An object capable of generating a probability
                             distribution.
        :type distribution:
        Right now, we have:
         * UniformDistribution
         * NormalDistribution
         * LogNormalDistribution
         * WeibullDistribution
        New distribution classes could be made.  The only
        requirement is they need to have a set_values()
        method which accepts a NumPy array.
        (presumably, this function will also modify
         the array in some way)
        :param water_density: 1020.0 [kg/m3]
        :type water_density: float
        :param water_viscosity: 1.0e-6 [m^2/s]
        :type water_viscosity: float
        """
        super(InitRiseVelFromDropletSizeFromDist, self).__init__(**kwargs)

        if distribution:
            self.distribution = distribution
        else:
            raise TypeError('InitRiseVelFromDropletSizeFromDist requires a '
                            'distribution for droplet sizes')

        self.water_viscosity = water_viscosity
        self.water_density = water_density
        self.array_types.update({'rise_vel': gat('rise_vel'),
                                 'droplet_diameter': gat('droplet_diameter')})
        self.name = 'rise_vel'
Exemple #14
0
    def __init__(self,
                 uncertain_duration=3,
                 uncertain_time_delay=0,
                 uncertain_speed_scale=2.,
                 uncertain_angle_scale=0.4,
                 **kwargs):
        """
        This is simply a base class for WindMover and GridWindMover for the
        common properties.

        The classes that inherit from this should define the self.mover object
        correctly so it has the required attributes.

        Input args with defaults:

        :param uncertain_duration: (seconds) the randomly generated uncertainty
            array gets recomputed based on 'uncertain_duration'
        :param uncertain_time_delay: when does the uncertainly kick in.
        :param uncertain_speed_scale: Scale for uncertainty in wind speed
            non-dimensional number
        :param uncertain_angle_scale: Scale for uncertainty in wind direction.
            Assumes this is in radians

        It calls super in the __init__ method and passes in the optional
        parameters (kwargs)
        """
        super(WindMoversBase, self).__init__(**kwargs)

        self.uncertain_duration = uncertain_duration
        self.uncertain_time_delay = uncertain_time_delay
        self.uncertain_speed_scale = uncertain_speed_scale

        # also sets self._uncertain_angle_units
        self.uncertain_angle_scale = uncertain_angle_scale

        self.array_types.update({
            'windages': gat('windages'),
            'windage_range': gat('windage_range'),
            'windage_persist': gat('windage_persist')
        })
Exemple #15
0
    def __init__(self,
                 standard_density=1000.0,
                 **kwargs):
        '''
        Non-weathering substance class for use with ElementType.
        - Right now, we consider our substance to have default properties
          similar to water, which we can of course change by passing something
          in.

        :param standard_density=1000.0: The density of the substance, assumed
                                        to be measured at 15 C.
        :type standard_density: Floating point decimal value

        :param pour_point=273.15: The pour_point of the substance, assumed
                                  to be measured in degrees Kelvin.
        :type pour_point: Floating point decimal value
        '''
        super(NonWeatheringSubstance, self).__init__(**kwargs)
        self.standard_density = standard_density
        self.array_types.update({
            'density': gat('density'),
            'fate_status': gat('fate_status')})
Exemple #16
0
    def __init__(self, windage_range=(0.01, 0.04), windage_persist=900, *args, **kwargs):
        """
        Initializes the windages, windage_range, windage_persist data arrays.
        Initial values for windages use infinite persistence. These are updated
        by the WindMover for particles with non-zero persistence.

        Optional arguments:

        :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
        """
        super(InitWindages, self).__init__(*args, **kwargs)
        self.windage_persist = windage_persist
        self.windage_range = windage_range
        self.array_types.update({'windages': gat('windages'),
                                 'windage_range': gat('windage_range'),
                                 'windage_persist': gat('windage_persist')})
    def __init__(self, **kwargs):
        """
        Uses super to invoke base class __init__ method.

        Optional parameters (kwargs) used to initialize CyRiseVelocityMover

        :param water_density: Default is 1020 kg/m3
        :param water_viscosity: Default is 1.e-6

        Remaining kwargs are passed onto Mover's __init__ using super.
        See Mover documentation for remaining valid kwargs.
        """
        self.mover = CyRiseVelocityMover()

        super(RiseVelocityMover, self).__init__(**kwargs)

        self.array_types['rise_vel'] = gat('rise_vel')
Exemple #18
0
    def rewind(self):
        '''
        Called by model.rewind()

        Reset variables set during prepare_for_model_run() to init conditions
        Make sure all child classes call parent rewind() first!
        '''
        self._model_start_time = None
        self._dt_since_lastoutput = None
        self._write_step = True
        self._is_first_output = True
        self._surf_conc_computed = True
        self._middle_of_run = False

        if self.surface_conc:
            self.array_types['surface_concentration'] = gat(
                'surface_concentration')
Exemple #19
0
    def __init__(self, water=None, wind=None, **kwargs):
        '''
        initialize wind to (0, 0) if it is None
        '''
        super(Langmuir, self).__init__(**kwargs)
        self.array_types.update({
            'fay_area': gat('fay_area'),
            'area': gat('area'),
            'bulk_init_volume': gat('bulk_init_volume'),
            'age': gat('age'),
            'positions': gat('positions'),
            'spill_num': gat('spill_num'),
            'frac_coverage': gat('frac_coverage'),
            'density': gat('density')
        })

        self.wind = wind

        # need water object to find relative buoyancy
        self.water = water
Exemple #20
0
def test_LEData_extend():
    arrtypes = {'area': gat('area')}

    dat = LEData()
    dat.prepare_for_model_run(arrtypes, 10)
    assert len(dat['area']) == 0
    dat.extend_data_arrays(5)
    assert len(dat['area']) == 5
    assert np.all(dat['area'] == 0)
    dat['area'][:] = 42
    assert np.all(dat['area'] == 42)
    assert len(dat._bufs['area']) == 100

    dat.extend_data_arrays(1000)
    assert dat._bufs['area'].shape == (2010, )
    assert dat._bufs['positions'].shape == (2010, 3)
    assert len(dat['area']) == 1005
    assert np.all(dat['area'][0:5] == 42)
    assert np.all(dat['area'][5:] == 0)
    def __init__(self, waves=None, water=None, **kwargs):
        '''
        :param conditions: gnome.environment.Conditions object which contains
            things like water temperature
        :param waves: waves object for obtaining wave_height, etc at given time
        '''
        self.waves = waves
        self.water = water

        super(NaturalDispersion, self).__init__(**kwargs)
        self.array_types.update({
            'viscosity': gat('viscosity'),
            'mass': gat('mass'),
            'density': gat('density'),
            'positions': gat('positions'),
            'area': gat('area'),
            'frac_water': gat('frac_water'),
            'droplet_avg_size': gat('droplet_avg_size'),
        })
    r = RiseVelocityMover()
    #r.water_density = 1
    #r.water_viscosity = 1.1e-6

    #assert r.water_density == 1
    #assert r.water_viscosity == 1.1e-6


time_step = 15 * 60  # seconds
rel_time = datetime(2012, 8, 20, 13)  # yyyy/month/day/hr/min/sec
initializers = [InitRiseVelFromDist(distribution=UniformDistribution())]
sc = sample_sc_release(
    5, (3., 6., 0.),
    rel_time,
    uncertain=False,
    arr_types={'rise_vel': gat('rise_vel')},
    substance=NonWeatheringSubstance(initializers=initializers))
initializers = [InitRiseVelFromDist(distribution=UniformDistribution())]
u_sc = sample_sc_release(
    5, (3., 6., 0.),
    rel_time,
    uncertain=True,
    arr_types={'rise_vel': gat('rise_vel')},
    substance=NonWeatheringSubstance(initializers=initializers))
model_time = rel_time


@pytest.mark.parametrize("test_sc", [sc, u_sc])
def test_one_move(test_sc):
    """
    calls one step for movement - just checks that it doesn't fail for any step
    def __init__(self, *args, **kwargs):
        super(TamocRiseVelocityMover, self).__init__(*args, **kwargs)

        self.array_types.update({'density': gat('density'),
                                 'droplet_diameter': gat('droplet_diameter')})
Exemple #24
0
    def __init__(self, waves=None, **kwargs):
        '''
        :param conditions: gnome.environment.Conditions object which contains
            things like water temperature
        :param waves: waves object for obtaining emulsification wind speed at specified time
        :type waves: get_emulsification_wind(model_time)
        '''
        self.waves = waves

        self._bw = 0
        if waves is not None:
            kwargs['make_default_refs'] = \
                kwargs.pop('make_default_refs', False)

        super(Emulsification, self).__init__(**kwargs)
        self.array_types.update({
            'age': gat('age'),
            'bulltime': gat('bulltime'),
            'frac_water': gat('frac_water'),
            'density': gat('density'),
            'viscosity': gat('viscosity'),
            'positions': gat('positions'),
            'oil_density': gat('oil_density'),
            'oil_viscosity': gat('oil_viscosity'),
            'mass': gat('mass'),
            'interfacial_area': gat('interfacial_area'),
            'frac_evap': gat('frac_evap')
        })
Exemple #25
0
Only contains tests for ArrayType since the remaining array_types classes
are trivial. They are tested in the integrated_tests
'''

import numpy as np

from gnome.basic_types import world_point_type, oil_status, \
    status_code_type

from gnome.array_types import ArrayType
from gnome.array_types import gat, reset_to_defaults
from pytest import mark, raises

from testfixtures import log_capture

age = gat('age')
mass = gat('mass')
mass_components = gat('mass_components')


def test_reset_to_defaults():
    '''
    will reset the object that found in array_types._default_values and
    ignore the one not found in this dict.
    '''
    ival = age.initial_value
    age.initial_value = 100
    reset_to_defaults(age)
    assert age.initial_value == ival

    def __init__(self,
                 filename=None,
                 wind=None,
                 time_offset=0,
                 uncertain_duration=3,
                 uncertain_time_delay=0,
                 uncertain_speed_scale=2.,
                 uncertain_angle_scale=0.4,
                 scale_value=1,
                 default_num_method='RK2',
                 **kwargs):
        """
        Initialize a PyWindMover

        :param filename: absolute or relative path to the data file(s):
                         could be a string or list of strings in the
                         case of a multi-file dataset
        :param wind: Environment object representing wind to be
                        used. If this is not specified, a GridWind object
                        will attempt to be instantiated from the file

        :param active_range: Range of datetimes for when the mover should be
                             active
        :type active_range: 2-tuple of datetimes

        :param scale_value: Value to scale wind data
        :param uncertain_duration: how often does a given uncertain element
                                   get reset
        :param uncertain_time_delay: when does the uncertainly kick in.
        :param uncertain_cross: Scale for uncertainty perpendicular to the flow
        :param uncertain_along: Scale for uncertainty parallel to the flow
        :param time_offset: Time zone shift if data is in GMT
        :param num_method: Numerical method for calculating movement delta.
                           Choices:('Euler', 'RK2', 'RK4')
                           Default: RK2

        """

        (super(PyWindMover,
               self).__init__(default_num_method=default_num_method, **kwargs))
        self.wind = wind
        self.make_default_refs = False

        self.filename = filename

        if self.wind is None:
            if filename is None:
                raise ValueError("must provide a filename or wind object")
            else:
                self.wind = GridWind.from_netCDF(filename=self.filename,
                                                 **kwargs)

        self.uncertain_duration = uncertain_duration
        self.uncertain_time_delay = uncertain_time_delay
        self.uncertain_speed_scale = uncertain_speed_scale
        self.scale_value = scale_value
        self.time_offset = time_offset

        # also sets self._uncertain_angle_units
        self.uncertain_angle_scale = uncertain_angle_scale

        self.array_types.update({
            'windages': gat('windages'),
            'windage_range': gat('windage_range'),
            'windage_persist': gat('windage_persist')
        })
    def __init__(self, water=None, **kwargs):
        '''
        initialize object.

        :param water: requires a water object
        :type water: gnome.environment.Water

        Options arguments kwargs: these get passed to base class via super
        '''
        super(WeatheringData, self).__init__(**kwargs)

        self.water = water
        self.array_types = {
            'fate_status': gat('fate_status'),
            'positions': gat('positions'),
            'status_codes': gat('status_codes'),
            'density': gat('density'),
            'viscosity': gat('viscosity'),
            'mass_components': gat('mass_components'),
            'mass': gat('mass'),
            'oil_density': gat('oil_density'),
            'oil_viscosity': gat('oil_viscosity'),
            'init_mass': gat('init_mass'),
            'frac_water': gat('frac_water'),
            'frac_lost': gat('frac_lost'),  # change to frac_dissolved
            'frac_evap': gat('frac_evap'),
            'age': gat('age')
        }

        # following used to update viscosity
        self.visc_curvfit_param = 1.5e3  # units are sec^0.5 / m
        self.visc_f_ref = 0.84