예제 #1
0
파일: test_data.py 프로젝트: opesci/devito
    def test_indexing_into_sparse(self):
        """
        Test indexing into SparseFunctions.
        """
        grid = Grid(shape=(4, 4))
        sf = SparseTimeFunction(name='sf', grid=grid, npoint=1, nt=10)

        sf.data[1:-1, 0] = np.arange(8)
        assert np.all(sf.data[1:-1, 0] == np.arange(8))
예제 #2
0
파일: test_dse.py 프로젝트: opesci/devito
def test_scheduling_after_rewrite():
    """Tests loop scheduling after DSE-induced expression hoisting."""
    grid = Grid((10, 10))
    u1 = TimeFunction(name="u1", grid=grid, save=10, time_order=2)
    u2 = TimeFunction(name="u2", grid=grid, time_order=2)
    sf1 = SparseTimeFunction(name='sf1', grid=grid, npoint=1, nt=10)
    const = Function(name="const", grid=grid, space_order=2)

    # Deliberately inject into u1, rather than u1.forward, to create a WAR
    eqn1 = Eq(u1.forward, u1 + sin(const))
    eqn2 = sf1.inject(u1.forward, expr=sf1)
    eqn3 = Eq(u2.forward, u2 - u1.dt2 + sin(const))

    op = Operator([eqn1] + eqn2 + [eqn3])
    trees = retrieve_iteration_tree(op)

    # Check loop nest structure
    assert len(trees) == 4
    assert all(i.dim == j for i, j in zip(trees[0], grid.dimensions))  # time invariant
    assert trees[1][0].dim == trees[2][0].dim == trees[3][0].dim == grid.time_dim
예제 #3
0
파일: test_dle.py 프로젝트: opesci/devito
    def test_scheduling(self):
        """
        Affine iterations -> #pragma omp ... schedule(static,1) ...
        Non-affine iterations -> #pragma omp ... schedule(static) ...
        """
        grid = Grid(shape=(11, 11))

        u = TimeFunction(name='u', grid=grid, time_order=2, save=5, space_order=0)
        sf1 = SparseTimeFunction(name='s', grid=grid, npoint=1, nt=5)

        eqns = [Eq(u.forward, u + 1)]
        eqns += sf1.interpolate(u)

        op = Operator(eqns, dle='openmp')

        iterations = FindNodes(Iteration).visit(op)
        assert len(iterations) == 4
        assert iterations[1].is_Affine
        assert 'schedule(static,1)' in iterations[1].pragmas[0].value
        assert not iterations[3].is_Affine
        assert 'schedule(static)' in iterations[3].pragmas[0].value
예제 #4
0
def test_operator_leakage_sparse():
    """
    Test to ensure that Operator creation does not cause memory leaks for
    SparseTimeFunctions.
    """
    grid = Grid(shape=(5, 6))
    a = Function(name='a', grid=grid)
    s = SparseTimeFunction(name='s', grid=grid, npoint=1, nt=1)
    w_a = weakref.ref(a)
    w_s = weakref.ref(s)

    # Create operator and delete everything again
    op = Operator(s.interpolate(a))
    w_op = weakref.ref(op)
    del op
    del s
    del a
    clear_cache()

    # Test whether things are still hanging around
    assert w_a() is None
    assert w_s() is None
    assert w_op() is None
예제 #5
0
    def test_empty_arrays(self):
        """
        MFE for issue #1641.
        """
        grid = Grid(shape=(4, 4), extent=(3.0, 3.0))

        f = TimeFunction(name='f', grid=grid, space_order=0)
        f.data[:] = 1.
        sf1 = SparseTimeFunction(name='sf1', grid=grid, npoint=0, nt=10)
        sf2 = SparseTimeFunction(name='sf2', grid=grid, npoint=0, nt=10)
        assert sf1.size == 0
        assert sf2.size == 0

        eqns = sf1.inject(field=f, expr=sf1 + sf2 + 1.)

        op = Operator(eqns)
        op.apply()
        assert np.all(f.data == 1.)

        # Again, but with a MatrixSparseTimeFunction
        mat = scipy.sparse.coo_matrix((0, 0), dtype=np.float32)
        sf = MatrixSparseTimeFunction(name="s",
                                      grid=grid,
                                      r=2,
                                      matrix=mat,
                                      nt=10)
        assert sf.size == 0

        eqns = sf.interpolate(f)

        op = Operator(eqns)

        sf.manual_scatter()
        op(time_m=0, time_M=9)
        sf.manual_gather()
        assert np.all(f.data == 1.)
예제 #6
0
    def test_drop_redundants_after_fusion(self):
        """
        Test for detection of redundant aliases that get exposed after
        Cluster fusion.
        """
        grid = Grid(shape=(10, 10))

        t = cos(Function(name="t", grid=grid))
        p = sin(Function(name="p", grid=grid))

        a = TimeFunction(name="a", grid=grid)
        b = TimeFunction(name="b", grid=grid)
        c = TimeFunction(name="c", grid=grid)
        d = TimeFunction(name="d", grid=grid)
        e = TimeFunction(name="e", grid=grid)
        f = TimeFunction(name="f", grid=grid)

        s1 = SparseTimeFunction(name="s1", grid=grid, npoint=1, nt=2)

        eqns = [Eq(a.forward, t*a.dx + p*b.dy),
                Eq(b.forward, p*b.dx + p*t*a.dy)]

        eqns += s1.inject(field=a.forward, expr=s1)
        eqns += s1.inject(field=b.forward, expr=s1)

        eqns += [Eq(c.forward, t*p*a.forward.dx + b.forward.dy),
                 Eq(d.forward, t*d.dx + e.dy + p*a.dt),
                 Eq(e.forward, p*d.dx + e.dy + t*b.dt)]

        eqns += [Eq(f.forward, t*p*e.forward.dx + p*d.forward.dy)]

        op = Operator(eqns)

        arrays = [i for i in FindSymbols().visit(op) if i.is_Array]
        assert len(arrays) == 2
        assert all(i._mem_heap and not i._mem_external for i in arrays)
예제 #7
0
    def setup(self):
        grid = Grid(shape=(5, 5, 5))

        funcs = [Function(name='f%d' % n, grid=grid) for n in range(30)]
        tfuncs = [TimeFunction(name='u%d' % n, grid=grid) for n in range(30)]
        stfuncs = [SparseTimeFunction(name='su%d' % n, grid=grid, npoint=1, nt=100)
                   for n in range(30)]
        v = TimeFunction(name='v', grid=grid, space_order=2)

        eq = Eq(v.forward, v.laplace + sum(funcs) + sum(tfuncs) + sum(stfuncs),
                subdomain=grid.interior)

        self.op = Operator(eq, opt='noop')

        # Allocate data, populate cached properties, etc.
        self.op.arguments(time_M=98)
예제 #8
0
파일: test_yask.py 프로젝트: richah2/devito
    def test_irregular_write(self):
        """
        Compute a simple stencil S w/o offloading it to YASK because of the presence
        of indirect write accesses (e.g. A[B[i]] = ...); YASK grid functions are however
        used in the generated code to access the data at the right location. This
        test checks that the numerical output is correct after this transformation.

        Initially, the input array (a YASK grid, under the hood), at t=0 is (2D view):

            0 1 2 3
            0 1 2 3
            0 1 2 3
            0 1 2 3

        Then, the Operator "flips" its content, and at timestep t=1 we get (2D view):

            3 2 1 0
            3 2 1 0
            3 2 1 0
            3 2 1 0
        """
        grid = Grid(shape=(4, 4, 4))
        x, y, z = grid.dimensions
        t = grid.stepping_dim
        p = SparseTimeFunction(name='points', grid=grid, nt=1, npoint=4)
        u = TimeFunction(name='yu4D', grid=grid, space_order=0)
        for i in range(4):
            for j in range(4):
                for k in range(4):
                    u.data[0, i, j, k] = k
        ind = lambda i: p.indexed[0, i]
        eqs = [
            Eq(p.indexed[0, 0], 3.),
            Eq(p.indexed[0, 1], 2.),
            Eq(p.indexed[0, 2], 1.),
            Eq(p.indexed[0, 3], 0.),
            Eq(u.indexed[t + 1, ind(x), ind(y), ind(z)], u.indexed[t, x, y, z])
        ]
        op = Operator(eqs, subs=grid.spacing_map)
        op(yu4D=u, time=0)
        assert 'run_solution' not in str(op)
        assert all(np.all(u.data[1, :, :, i] == 3 - i) for i in range(4))
예제 #9
0
 def test_constants(self):
     """
     Check that :class:`Constant` objects are treated correctly.
     """
     grid = Grid(shape=(4, 4, 4))
     c = Constant(name='c', value=2.)
     p = SparseTimeFunction(name='points', grid=grid, nt=1, npoint=1)
     u = TimeFunction(name='yu4D', grid=grid, space_order=0)
     u.data[:] = 0.
     op = Operator([Eq(u.forward, u + c), Eq(p.indexed[0, 0], 1. + c)])
     assert 'run_solution' in str(op)
     op.apply(yu4D=u, c=c, t=11)
     # Check YASK did its job and could read constant grids w/o problems
     assert np.all(u.data[0] == 20.)
     # Check the Constant could be read correctly even in Devito-land, i.e.,
     # outside of run_solution
     assert p.data[0][0] == 3.
     # Check re-executing with another constant gives the correct result
     c2 = Constant(name='c', value=5.)
     op.apply(yu4D=u, c=c2, t=4)
     assert np.all(u.data[0] == 30.)
     assert p.data[0][0] == 6.
예제 #10
0
    def test_over_injection(self):
        nt = 10
        grid = Grid(shape=(4, 4))

        src = SparseTimeFunction(name='src', grid=grid, npoint=1, nt=nt)
        rec = SparseTimeFunction(name='rec', grid=grid, npoint=1, nt=nt)
        u = TimeFunction(name="u",
                         grid=grid,
                         time_order=2,
                         space_order=2,
                         save=nt)
        u1 = TimeFunction(name="u",
                          grid=grid,
                          time_order=2,
                          space_order=2,
                          save=nt)

        src.data[:] = 1.

        eqns = ([Eq(u.forward, u + 1)] +
                src.inject(field=u.forward, expr=src) +
                rec.interpolate(expr=u.forward))

        op0 = Operator(eqns, opt='noop')
        op1 = Operator(eqns, opt='buffering')

        # Check generated code
        assert len(retrieve_iteration_tree(op1)) ==\
            5 + bool(configuration['language'] != 'C')
        buffers = [i for i in FindSymbols().visit(op1) if i.is_Array]
        assert len(buffers) == 1

        op0.apply(time_M=nt - 2)
        op1.apply(time_M=nt - 2, u=u1)

        assert np.all(u.data == u1.data)
예제 #11
0
    def test_injection_wodup_wtime(self):
        """
        Just like ``test_injection_wodup``, but using a SparseTimeFunction
        instead of a SparseFunction. Hence, the data scattering/gathering now
        has to correctly pack/unpack multidimensional arrays.
        """
        grid = Grid(shape=(4, 4), extent=(3.0, 3.0))

        save = 3
        f = TimeFunction(name='f', grid=grid, save=save, space_order=0)
        f.data[:] = 0.
        coords = np.array([(0.5, 0.5), (0.5, 2.5), (2.5, 0.5), (2.5, 2.5)])
        sf = SparseTimeFunction(name='sf', grid=grid, nt=save,
                                npoint=len(coords), coordinates=coords)
        sf.data[0, :] = 4.
        sf.data[1, :] = 8.
        sf.data[2, :] = 12.

        op = Operator(sf.inject(field=f, expr=sf + 1))
        op.apply()

        assert np.all(f.data[0] == 1.25)
        assert np.all(f.data[1] == 2.25)
        assert np.all(f.data[2] == 3.25)
예제 #12
0
def solver(I, V, f, c, L, dt, C, T, user_action=None):
    """Solve u_tt=c^2*u_xx + f on (0,L)x(0,T]."""
    Nt = int(round(T / dt))
    t = np.linspace(0, Nt * dt, Nt + 1)  # Mesh points in time
    dx = dt * c / float(C)
    Nx = int(round(L / dx))
    x = np.linspace(0, L, Nx + 1)  # Mesh points in space
    C2 = C**2  # Help variable in the scheme

    # Make sure dx and dt are compatible with x and t
    dx = x[1] - x[0]
    dt = t[1] - t[0]

    # Initialising functions f and V if not provided
    if f is None or f == 0:
        f = lambda x, t: 0
    if V is None or V == 0:
        V = lambda x: 0

    t0 = time.perf_counter()  # Measure CPU time

    # Set up grid
    grid = Grid(shape=(Nx + 1), extent=(L))
    t_s = grid.stepping_dim

    # Create and initialise u
    u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2)
    u.data[:, :] = I(x[:])

    x_dim = grid.dimensions[0]
    t_dim = grid.time_dim

    # The wave equation we are trying to solve
    pde = (1 / c**2) * u.dt2 - u.dx2

    # Source term and injection into equation
    dt_symbolic = grid.time_dim.spacing
    src = SparseTimeFunction(name='f', grid=grid, npoint=Nx + 1, nt=Nt + 1)

    for i in range(Nt):
        src.data[i] = f(x, t[i])

    src.coordinates.data[:, 0] = x
    src_term = src.inject(field=u.forward, expr=src * (dt_symbolic**2))
    stencil = Eq(u.forward, solve(pde, u.forward))

    # Set up special stencil for initial timestep with substitution for u.backward
    v = Function(name='v', grid=grid, npoint=Nx + 1, nt=1)
    v.data[:] = V(x[:])
    stencil_init = stencil.subs(u.backward, u.forward - dt_symbolic * v)

    # Boundary conditions
    bc = [Eq(u[t_s + 1, 0], 0)]
    bc += [Eq(u[t_s + 1, Nx], 0)]

    # Create and apply operators
    op_init = Operator([stencil_init] + src_term + bc)
    op = Operator([stencil] + src_term + bc)

    op_init.apply(time_M=1, dt=dt)
    op.apply(time_m=1, time_M=Nt, dt=dt)

    cpu_time = time.perf_counter() - t0

    return u.data[-1], x, t, cpu_time