def test_staggered_function(self, order):
        """Test custom function coefficients on a staggered grid"""
        grid = Grid(shape=(11, ), extent=(10., ))
        x = grid.dimensions[0]

        f = Function(name='f',
                     grid=grid,
                     space_order=order,
                     coefficients='symbolic')
        g = Function(name='g',
                     grid=grid,
                     space_order=order,
                     coefficients='symbolic',
                     staggered=x)
        f.data[::2] = 1
        g.data[::2] = 1

        s = Dimension(name='s')
        ncoeffs = order + 1

        wshape = grid.shape + (ncoeffs, )
        wdims = grid.dimensions + (s, )

        w = Function(name='w', dimensions=wdims, shape=wshape)
        w.data[:] = 1.0 / grid.spacing[0]**2

        coeffs_f = Coefficient(2, f, x, w)
        coeffs_g = Coefficient(2, g, x, w)

        eq_f = Eq(f, f.dx2, coefficients=Substitutions(coeffs_f))
        eq_g = Eq(g, g.dx2, coefficients=Substitutions(coeffs_g))

        Operator([eq_f, eq_g])()

        assert np.allclose(f.data, g.data, atol=1e-7)
    def test_staggered_array(self, order):
        """Test custom coefficients provided as an array on a staggered grid"""
        grid = Grid(shape=(11, ), extent=(10., ))
        x = grid.dimensions[0]

        f = Function(name='f',
                     grid=grid,
                     space_order=order,
                     coefficients='symbolic')
        g = Function(name='g',
                     grid=grid,
                     space_order=order,
                     coefficients='symbolic',
                     staggered=x)
        f.data[::2] = 1
        g.data[::2] = 1

        weights = np.ones(order + 1) / grid.spacing[0]**2
        coeffs_f = Coefficient(2, f, x, weights)
        coeffs_g = Coefficient(2, g, x, weights)

        eq_f = Eq(f, f.dx2, coefficients=Substitutions(coeffs_f))
        eq_g = Eq(g, g.dx2, coefficients=Substitutions(coeffs_g))

        Operator([eq_f, eq_g])()

        assert np.allclose(f.data, g.data, atol=1e-7)
    def test_with_timefunction(self, stagger):
        """Check compatibility of custom coefficients and TimeFunctions"""
        grid = Grid(shape=(11, ), extent=(10., ))
        x = grid.dimensions[0]
        if stagger:
            staggered = x
        else:
            staggered = None

        f = TimeFunction(name='f',
                         grid=grid,
                         space_order=2,
                         staggered=staggered)
        g = TimeFunction(name='g',
                         grid=grid,
                         space_order=2,
                         staggered=staggered,
                         coefficients='symbolic')

        f.data[:, ::2] = 1
        g.data[:, ::2] = 1

        weights = np.array([-1, 2, -1]) / grid.spacing[0]**2
        coeffs = Coefficient(2, g, x, weights)

        eq_f = Eq(f.forward, f.dx2)
        eq_g = Eq(g.forward, g.dx2, coefficients=Substitutions(coeffs))

        Operator([eq_f, eq_g])(t_m=0, t_M=1)

        assert np.allclose(f.data[-1], -g.data[-1], atol=1e-7)
    def test_function_coefficients(self):
        """Test that custom function coefficients return the expected result"""
        so = 2
        grid = Grid(shape=(4, 4))
        f0 = TimeFunction(name='f0',
                          grid=grid,
                          space_order=so,
                          coefficients='symbolic')
        f1 = TimeFunction(name='f1', grid=grid, space_order=so)
        x, y = grid.dimensions

        s = Dimension(name='s')
        ncoeffs = so + 1

        wshape = list(grid.shape)
        wshape.append(ncoeffs)
        wshape = as_tuple(wshape)

        wdims = list(grid.dimensions)
        wdims.append(s)
        wdims = as_tuple(wdims)

        w = Function(name='w', dimensions=wdims, shape=wshape)
        w.data[:, :, 0] = 0.0
        w.data[:, :, 1] = -1.0 / grid.spacing[0]
        w.data[:, :, 2] = 1.0 / grid.spacing[0]

        f_x_coeffs = Coefficient(1, f0, x, w)

        subs = Substitutions(f_x_coeffs)

        eq0 = Eq(f0.dt + f0.dx, 1, coefficients=subs)
        eq1 = Eq(f1.dt + f1.dx, 1)

        stencil0 = solve(eq0.evaluate, f0.forward)
        stencil1 = solve(eq1.evaluate, f1.forward)

        op0 = Operator(Eq(f0.forward, stencil0))
        op1 = Operator(Eq(f1.forward, stencil1))

        op0(time_m=0, time_M=5, dt=1.0)
        op1(time_m=0, time_M=5, dt=1.0)

        assert np.all(
            np.isclose(f0.data[:] - f1.data[:], 0.0, atol=1e-5, rtol=0))
    def test_coefficients(self, expr, sorder, dorder, dim, weights, expected):
        """Test that custom coefficients return the expected result"""
        grid = Grid(shape=(10, 10))
        u = Function(name='u',
                     grid=grid,
                     space_order=sorder,
                     coefficients='symbolic')
        x = grid.dimensions

        order = dorder
        dim = x[dim]
        weights = np.array(weights)

        coeffs = Coefficient(order, u, dim, weights)

        eq = Eq(eval(expr), coefficients=Substitutions(coeffs))
        assert isinstance(eq.lhs, Differentiable)
        assert expected == str(eq.evaluate.lhs)
예제 #6
0
    def subs(self, derivs):
        """
        Return a devito Substitutions for each specified combination of function
        and derivative.

        Parameters
        ----------
        derivs : pandas DataFrame
            The desired combinations of function, derivative, and the offset
            at which the derivative should be taken. These should be in three
            columns of a dataframe, called 'function', 'derivative', and
            'eval_offset' respectively. Note that the offset should be relative
            to the location of the function nodes (-0.5 for backward staggered,
            0.5 for forward, and 0. for no stagger). Offset should be provided
            as a tuple of (x, y, z).
        """
        # Check that dataframe contains columns with specified names
        if 'function' not in derivs.columns:
            raise ValueError("No function column specified")
        if 'derivative' not in derivs.columns:
            raise ValueError("No derivative column specified")
        if 'eval_offset' not in derivs.columns:
            raise ValueError("No evaluation offset column specified")
        # Need to check all functions specified are in the attatched functions
        if not np.all(derivs.function.isin(self._functions.function)):
            raise ValueError(
                "Specified functions are not attatched to boundary")

        # Add names column to allow for grouping
        name_functions(derivs)

        grouped = derivs.groupby('name')

        weights = ()

        for name, group in grouped:
            # Loop over items in each group and call a function
            func_weights = self._get_function_weights(group)
            weights += func_weights

        return Substitutions(*weights)
예제 #7
0
    def test_staggered_equation(self):
        """
        Check that expressions with substitutions are consistent with
        those without
        """
        grid = Grid(shape=(11, ), extent=(10., ))
        x = grid.dimensions[0]

        f = Function(name='f',
                     grid=grid,
                     space_order=2,
                     coefficients='symbolic',
                     staggered=x)

        weights = np.array([1, -2, 1]) / grid.spacing[0]**2
        coeffs_f = Coefficient(2, f, x, weights)

        eq_f = Eq(f, f.dx2, coefficients=Substitutions(coeffs_f))

        expected = 'Eq(f(x + h_x/2), f(x - h_x/2) - 2.0*f(x + h_x/2) + f(x + 3*h_x/2))'
        assert (str(eq_f.evaluate) == expected)
    def test_coefficients_w_xreplace(self):
        """Test custom coefficients with an xreplace before they are applied"""
        grid = Grid(shape=(4, 4))
        u = Function(name='u',
                     grid=grid,
                     space_order=2,
                     coefficients='symbolic')
        x = grid.dimensions[0]

        dorder = 1
        weights = np.array([-0.6, 0.1, 0.6])

        coeffs = Coefficient(dorder, u, x, weights)

        c = sp.Symbol('c')

        eq = Eq(u.dx + c, coefficients=Substitutions(coeffs))
        eq = eq.xreplace({c: 2})

        expected = '0.1*u(x, y) - 0.6*u(x - h_x, y) + 0.6*u(x + h_x, y) + 2'

        assert expected == str(eq.evaluate.lhs)