Ejemplo n.º 1
0
def test_LE_not_in_water():
    """
    Tests get_move returns 0 for LE's that have a status
    different from in_water
    """
    wm = CyWindMover()
    cm = cy_fixtures.CyTestMove()
    delta = np.zeros((cm.num_le, ), dtype=world_point)
    cm.status[:] = 0

    wm.prepare_for_model_step(cm.model_time, cm.time_step)
    wm.get_move(cm.model_time, cm.time_step, cm.ref, delta, cm.windage,
                cm.status, spill_type.forecast)

    assert np.all(delta['lat'] == 0)
    assert np.all(delta['long'] == 0)
    assert np.all(delta['z'] == 0)
Ejemplo n.º 2
0
class TestVariableWind:
    """
    Uses OSSMTimeValue_c to define a variable wind
    - variable wind has 'v' component, so movement
      should only be in 'lat' direction of world point

    Leave as a class as we may add more methods to it for testing
    """
    wm = CyWindMover()
    cm = cy_fixtures.CyTestMove()
    delta = np.zeros((cm.num_le, ), dtype=world_point)

    time_val = np.zeros((2, ), dtype=time_value_pair)
    (time_val['time'])[:] = np.add([0, 3600], cm.model_time)  # after 1 hour
    (time_val['value']['v'])[:] = [100, 200]

    # CyTimeseries needs the same scope as CyWindMover because CyWindMover
    # uses the C++ pointer defined in CyTimeseries.time_dep. This must be defined
    # for the scope of CyWindMover

    ossm = CyTimeseries(timeseries=time_val)
    wm.set_ossm(ossm)

    def test_move(self):
        for x in range(0, 3):
            vary_time = x * 1800
            self.wm.prepare_for_model_step(self.cm.model_time + vary_time,
                                           self.cm.time_step)
            self.wm.get_move(self.cm.model_time + vary_time,
                             self.cm.time_step,
                             self.cm.ref,
                             self.delta,
                             self.cm.windage,
                             self.cm.status,
                             spill_type.forecast)

            print self.delta
            assert np.all(self.delta['lat'] != 0)
            assert np.all(self.delta['long'] == 0)
            assert np.all(self.delta['z'] == 0)
Ejemplo n.º 3
0
class TestRandomVertical:

    msg = 'vertical_diffusion_coef_above_ml = {0.vertical_diffusion_coef_above_ml},vertical_diffusion_coef_below_ml = {0.vertical_diffusion_coef_below_ml}'
    cm = cy_fixtures.CyTestMove()
    cm.ref['z'][:]=.1
    rm = CyRandomVerticalMover(vertical_diffusion_coef_above_ml=5,vertical_diffusion_coef_below_ml=.11)

    def move(self, delta):
        self.rm.prepare_for_model_run()

        self.rm.prepare_for_model_step(self.cm.model_time,
                self.cm.time_step)
        self.rm.get_move(
            self.cm.model_time,
            self.cm.time_step,
            self.cm.ref,
            delta,
            self.cm.status,
            spill_type.forecast,
            )

    def test_move(self):
        """
        test that it moved
        """

        self.move(self.cm.delta)
        np.set_printoptions(precision=4)
        print
        print self.msg.format(self.rm),
        print 'get_move output:'
        print self.cm.delta.view(dtype=np.float64).reshape(-1, 3)
        assert np.all(self.cm.delta['z'] != 0)
        assert np.all(self.cm.delta['lat'] != 0)
        assert np.all(self.cm.delta['long'] != 0)

    def test_zero_coef(self):
        """
        ensure no move for 0 vertical diffusion coefficient
        """

        self.rm.vertical_diffusion_coef_above_ml = 0
        self.rm.vertical_diffusion_coef_below_ml = 0
        self.rm.horizontal_diffusion_coef_above_ml = 0
        self.rm.horizontal_diffusion_coef_below_ml = 0
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)
        self.rm.vertical_diffusion_coef_above_ml = 5
        self.rm.vertical_diffusion_coef_below_ml = .11
        self.rm.horizontal_diffusion_coef_above_ml = 100000
        self.rm.horizontal_diffusion_coef_below_ml = 126
        assert np.all(new_delta.view(dtype=np.double).reshape(1, -1)
                      == 0)

    def test_surface_particles(self):
        """
        ensure no move for surface particles
        if the surface_is_allowed flag is on
        """

    	self.cm.ref['z'][:]=0
        self.rm.surface_is_allowed = True
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)
    	self.cm.ref['z'][:]=.1
        assert np.all(new_delta.view(dtype=np.double).reshape(1, -1)
                      == 0)

    def test_mixed_layer_zero(self):
        """
        Test that the move for z above the mixed layer
        is different from move for z below the mixed layer
        and the same if the mixed layer is zero
        Use the py.test -s flag to view the differences
        """

        srand(1)
        np.set_printoptions(precision=6)
        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)  # get the move before changing the coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print delta.view(dtype=np.float64).reshape(-1, 3)

        srand(1)
        self.cm.ref['z'][:]=20
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)  # get the move after changing coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        assert np.all(delta['z'] != new_delta['z'])

        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta).reshape(-1, 1)

        self.rm.mixed_layer_depth = 0

        srand(1)
    	self.cm.ref['z'][:]=.1
        newer_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(newer_delta)  # get the move after changing mld
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print newer_delta.view(dtype=np.float64).reshape(-1, 3)
        print

        msg = r"{0} move is not within a tolerance of {1}"
        tol = 1e-10
        np.testing.assert_allclose(
            new_delta['z'],
            newer_delta['z'],
            tol,
            tol,
            msg.format('random_vertical', tol),
            0,
            )

        print '-- Norm of difference between movement vector --'
        print self._diff(new_delta, newer_delta).reshape(-1, 1)

        self.rm.mixed_layer_depth = 10

    def test_update_coef(self):
        """
        Test that the move is different from original move since
        vertical diffusion coefficient is different
        Use the py.test -s flag to view the difference between the two
        """

        np.set_printoptions(precision=6)
        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)  # get the move before changing the coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print delta.view(dtype=np.float64).reshape(-1, 3)
        self.rm.vertical_diffusion_coef_above_ml = 10
        assert self.rm.vertical_diffusion_coef_above_ml == 10

        srand(1)
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)  # get the move after changing coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta).reshape(-1, 1)

        assert np.all(delta['z'] != new_delta['z'])

        self.rm.vertical_diffusion_coef_above_ml = 5  # reset it

    def test_update_horiz_coef(self):
        """
        Test that the move is different from original move since
        horizontal diffusion coefficient is different
        Use the py.test -s flag to view the difference between the two
        """

        np.set_printoptions(precision=6)
        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)  # get the move before changing the coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print delta.view(dtype=np.float64).reshape(-1, 3)
        self.rm.horizontal_diffusion_coef_above_ml = 1000
        assert self.rm.horizontal_diffusion_coef_above_ml == 1000

        srand(1)
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)  # get the move after changing coefficient
        print
        print self.msg.format(self.rm) + ' get_move output:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta).reshape(-1, 1)

        assert np.all(delta['lat'] != new_delta['lat'])
        assert np.all(delta['long'] != new_delta['long'])

        self.rm.horizontal_diffusion_coef_above_ml = 100000  # reset it

    def test_seed(self):
        """
        Since seed is not reset, the move should be repeatable
        """

        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)
        srand(1)

        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)

        print
        print '-- Do not reset seed and call get move again',
        print 'to get identical results --'
        print 'get_move results 1st time:'
        print delta.view(dtype=np.float64).reshape(-1, 3)
        print 'get_move results 2nd time - same seed:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        assert np.all(delta['lat'] == new_delta['lat'])
        assert np.all(delta['long'] == new_delta['long'])
        assert np.all(delta['z'] == new_delta['z'])
        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta)

    def _diff(self, delta, new_delta):
        """
        gives the norm of the (delta-new_delta)
        """

        diff = delta.view(dtype=world_point_type).reshape(-1, 3)
        diff -= new_delta.view(dtype=world_point_type).reshape(-1, 3)
        return np.sum(diff ** 2, axis=1) ** .5
Ejemplo n.º 4
0
class TestRandom:

    cm = cy_fixtures.CyTestMove()
    rm = CyRandomMover(diffusion_coef=100000)

    def move(self, delta):
        self.rm.prepare_for_model_run()

        self.rm.prepare_for_model_step(self.cm.model_time,
                self.cm.time_step)
        self.rm.get_move(
            self.cm.model_time,
            self.cm.time_step,
            self.cm.ref,
            delta,
            self.cm.status,
            spill_type.forecast,
            )

    def test_move(self):
        """
        test that it moved
        """

        self.move(self.cm.delta)
        np.set_printoptions(precision=4)

        print
        print 'diffusion_coef = {0:0.1f}'.format(self.rm.diffusion_coef),
        print 'get_move output:'
        print self.cm.delta.view(dtype=np.float64).reshape(-1, 3)

        assert np.all(self.cm.delta['lat'] != 0)
        assert np.all(self.cm.delta['long'] != 0)

    def test_zero_subsurface_move(self):
        """
        ensure no move for z below surface
        """

    	self.cm.ref['z'][:]=100
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)
    	self.cm.ref['z'][:]=0
        assert np.all(new_delta.view(dtype=np.double).reshape(1, -1)
                      == 0)

    def test_zero_coef(self):
        """
        ensure no move for 0 diffusion coefficient
        """

        self.rm.diffusion_coef = 0
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)
        self.rm.diffusion_coef = 100000
        assert np.all(new_delta.view(dtype=np.double).reshape(1, -1)
                      == 0)

    def test_update_coef(self):
        """
        Test that the move is different from original move since
        diffusion coefficient is different
        Use the py.test -s flag to view the difference between the two
        """

        np.set_printoptions(precision=6)
        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)  # get the move before changing the coefficient

        print
        print 'diffusion_coef = {0.diffusion_coef}'.format(self.rm),
        print 'get_move output:'
        print delta.view(dtype=np.float64).reshape(-1, 3)
        self.rm.diffusion_coef = 10
        assert self.rm.diffusion_coef == 10

        srand(1)
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)  # get the move after changing coefficient
        print
        print 'diffusion_coef = {0.diffusion_coef}'.format(self.rm),
        print 'get_move output:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta).reshape(-1, 1)
        assert np.all(delta['lat'] != new_delta['lat'])
        assert np.all(delta['long'] != new_delta['long'])

        self.rm.diffusion_coef = 100000  # reset it

    def test_seed(self):
        """
        Since seed is not reset, the move should be repeatable
        """

        delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(delta)

        srand(1)
        new_delta = np.zeros((self.cm.num_le, ), dtype=world_point)
        self.move(new_delta)

        print
        print '-- Do not reset seed and call get move again to get identical results --'
        print 'get_move results 1st time:'
        print delta.view(dtype=np.float64).reshape(-1, 3)
        print 'get_move results 2nd time - same seed:'
        print new_delta.view(dtype=np.float64).reshape(-1, 3)
        print
        print '-- Norm of difference between movement vector --'
        print self._diff(delta, new_delta)
        print delta['lat'], new_delta['lat']
        assert np.all(delta['lat'] == new_delta['lat'])
        assert np.all(delta['long'] == new_delta['long'])

    def _diff(self, delta, new_delta):
        """
        gives the norm of the (delta-new_delta)
        """

        diff = delta.view(dtype=world_point_type).reshape(-1, 3) \
            - new_delta.view(dtype=world_point_type).reshape(-1, 3)
        return np.sum(diff ** 2, axis=1) ** .5
Ejemplo n.º 5
0
class TestVariableWind:
    """
    Uses OSSMTimeValue_c to define a variable wind
    - variable wind has 'v' component, so movement
      should only be in 'lat' direction of world point

    Leave as a class as we may add more methods to it for testing
    """
    wm = CyWindMover()
    cm = cy_fixtures.CyTestMove()
    delta = np.zeros((cm.num_le, ), dtype=world_point)

    time_val = np.zeros((2, ), dtype=time_value_pair)
    (time_val['time'])[:] = np.add([0, 3600], cm.model_time)  # after 1 hour
    (time_val['value']['v'])[:] = [100, 200]

    # CyTimeseries needs the same scope as CyWindMover because CyWindMover
    # uses the C++ pointer defined in CyTimeseries.time_dep.
    # This must be defined for the scope of CyWindMover

    ossm = CyTimeseries(timeseries=time_val)
    wm.set_ossm(ossm)

    def test_move(self):
        for x in range(0, 3):
            vary_time = x * 1800
            self.wm.prepare_for_model_step(self.cm.model_time + vary_time,
                                           self.cm.time_step)

            self.wm.get_move(self.cm.model_time + vary_time,
                             self.cm.time_step,
                             self.cm.ref,
                             self.delta,
                             self.cm.windage,
                             self.cm.status,
                             spill_type.forecast)

            print self.delta
            assert np.all(self.delta['lat'] != 0)
            assert np.all(self.delta['long'] == 0)
            assert np.all(self.delta['z'] == 0)

    def test_move_out_of_bounds(self):
        '''
            Our wind mover should fail in the prepare_for_model_step() function
            if our wind time series is out of bounds with respect to the
            model time we are preparing for, unless our wind time series is
            configured to extrapolate wind values.
        '''
        # setup a time series that's out of range of our model time
        time_val = np.zeros((2, ), dtype=time_value_pair)
        (time_val['time'])[:] = np.add([3600, 7200], self.cm.model_time)
        (time_val['value']['v'])[:] = [100, 200]

        # extrapolation should be off by default
        ossm = CyTimeseries(timeseries=time_val)
        self.wm.set_ossm(ossm)

        # this should fail because our time series is not set to extrapolate
        with raises(OSError):
            self.wm.prepare_for_model_step(self.cm.model_time,
                                           self.cm.time_step)

        ossm = CyTimeseries(timeseries=time_val, extrapolation_is_allowed=True)
        self.wm.set_ossm(ossm)

        # We set our time series to extrapolate, so this should pass
        self.wm.prepare_for_model_step(self.cm.model_time,
                                       self.cm.time_step)

        # clean up our time series
        self.wm.set_ossm(self.ossm)