Exemplo n.º 1
0
def test_issue_1838():
    """
    MFE for issue #1838.
    """
    space_order = 4

    grid = Grid(shape=(4, 4, 4))

    f = Function(name='f', grid=grid, space_order=space_order)
    b = Function(name='b', grid=grid, space_order=space_order)
    p0 = TimeFunction(name='p0', grid=grid, space_order=space_order)
    p1 = TimeFunction(name='p0', grid=grid, space_order=space_order)

    f.data[:] = 2.1
    b.data[:] = 1.3
    p0.data[:, 2, 2, 2] = .3
    p1.data[:, 2, 2, 2] = .3

    eq = Eq(p0.forward, (sin(b) * p0.dx).dx + (sin(b) * p0.dx).dy +
            (sin(b) * p0.dx).dz + p0)

    op0 = Operator(eq)
    op1 = Operator(eq, opt=('advanced', {'linearize': True}))

    op0.apply(time_M=3, dt=1.)
    op1.apply(time_M=3, dt=1., p0=p1)

    # Check generated code
    assert "r4L0(x, y, z) r4[(x)*y_stride2 + (y)*z_stride1 + (z)]" in str(op1)

    assert np.allclose(p0.data, p1.data, rtol=1e-6)
Exemplo n.º 2
0
    def test_fd_adjoint(self, so, ndim, derivative, adjoint_name):
        grid = Grid(shape=tuple([51] * ndim), extent=tuple([25] * ndim))
        x = grid.dimensions[0]
        f = Function(name='f', grid=grid, space_order=so)
        f_deriv = Function(name='f_deriv', grid=grid, space_order=so)
        g = Function(name='g', grid=grid, space_order=so)
        g_deriv = Function(name='g_deriv', grid=grid, space_order=so)

        # Fill f and g with smooth cos/sin
        Operator(
            [Eq(g, x * cos(2 * np.pi * x / 5)),
             Eq(f, sin(2 * np.pi * x / 8))]).apply()
        # Check symbolic expression are expected ones for the adjoint .T
        deriv = getattr(f, derivative)
        coeff = 1 if derivative == 'dx2' else -1
        expected = coeff * getattr(f, derivative).evaluate.subs(
            {x.spacing: -x.spacing})
        assert simplify(deriv.T.evaluate) == simplify(bypass_uneval(expected))

        # Compute numerical derivatives and verify dot test
        #  i.e <f.dx, g> = <f, g.dx.T>

        eq_f = Eq(f_deriv, deriv)
        eq_g = Eq(g_deriv, getattr(g, derivative).T)

        op = Operator([eq_f, eq_g])
        op()

        a = np.dot(f_deriv.data.reshape(-1), g.data.reshape(-1))
        b = np.dot(g_deriv.data.reshape(-1), f.data.reshape(-1))
        assert np.isclose(1 - a / b, 0, atol=1e-5)
Exemplo n.º 3
0
def test_find_symbols_with_duplicates():
    grid = Grid(shape=(4, 4))
    x, y = grid.dimensions

    f = TimeFunction(name='f', grid=grid)
    g = Function(name='g', grid=grid)

    eq = Eq(f.forward, sin(g) * f + g)

    op = Operator(eq)

    exprs = FindNodes(Expression).visit(op)

    assert len(exprs) == 2

    # Two syntactically identical indexeds r0[x, y], but they're different
    # objects because they are constructed in two different places during
    # the CIRE pass
    r0a = exprs[0].output
    r0b = exprs[1].expr.rhs.args[0].args[0]
    assert r0a.function is r0b.function
    assert r0a.name == r0b.name == "r0"
    assert hash(r0a) == hash(r0b)
    assert r0a is not r0b

    # So we expect FindSymbols to catch five Indexeds in total
    symbols = FindSymbols('indexeds').visit(op)
    assert len(symbols) == 5
Exemplo n.º 4
0
def test_unsubstituted_indexeds():
    """
    This issue emerged in the context of PR #1828, after the introduction
    of Uxreplace to substitute Indexeds with FIndexeds. Basically what happened
    was that `FindSymbols('indexeds')` was missing syntactically identical
    objects that however look the same. For example, as in this test,
    we end up with two `r0[x, y, z]`, but the former's `x` and `y` are
    SpaceDimensions, while the latter's are BlockDimensions. This means
    that the two objects, while looking identical, are different, and in
    partical they hash differently, hence we need two entries in a mapper
    to perform an Uxreplace. But FindSymbols made us detect only one entry...
    """
    grid = Grid(shape=(8, 8, 8))

    f = Function(name='f', grid=grid)
    p = TimeFunction(name='p', grid=grid)
    p1 = TimeFunction(name='p', grid=grid)

    f.data[:] = 0.12
    p.data[:] = 1.
    p1.data[:] = 1.

    eq = Eq(p.forward, sin(f) * p * f)

    op0 = Operator(eq)
    op1 = Operator(eq, opt=('advanced', {'linearize': True}))

    # NOTE: Eventually we compare the numerical output, but truly the most
    # import check is implicit to op1.apply, and it's the fact that op1
    # actually jit-compiles successfully, meaning that all substitutions
    # were performed correctly
    op0.apply(time_M=2)
    op1.apply(time_M=2, p=p1)

    assert np.allclose(p.data, p1.data, rtol=1e-7)
Exemplo n.º 5
0
def initialize_damp(damp, padsizes, spacing, abc_type="damp", fs=False):
    """
    Initialize damping field with an absorbing boundary layer.

    Parameters
    ----------
    damp : Function
        The damping field for absorbing boundary condition.
    nbl : int
        Number of points in the damping layer.
    spacing :
        Grid spacing coefficient.
    mask : bool, optional
        whether the dampening is a mask or layer.
        mask => 1 inside the domain and decreases in the layer
        not mask => 0 inside the domain and increase in the layer
    """

    eqs = [Eq(damp, 1.0 if abc_type == "mask" else 0.0)]
    for (nbl, nbr), d in zip(padsizes, damp.dimensions):
        if not fs or d is not damp.dimensions[-1]:
            dampcoeff = 1.5 * np.log(1.0 / 0.001) / (nbl)
            # left
            dim_l = SubDimension.left(name='abc_%s_l' % d.name,
                                      parent=d,
                                      thickness=nbl)
            pos = Abs((nbl - (dim_l - d.symbolic_min) + 1) / float(nbl))
            val = dampcoeff * (pos - sin(2 * np.pi * pos) / (2 * np.pi))
            val = -val if abc_type == "mask" else val
            eqs += [Inc(damp.subs({d: dim_l}), val / d.spacing)]
        # right
        dampcoeff = 1.5 * np.log(1.0 / 0.001) / (nbr)
        dim_r = SubDimension.right(name='abc_%s_r' % d.name,
                                   parent=d,
                                   thickness=nbr)
        pos = Abs((nbr - (d.symbolic_max - dim_r) + 1) / float(nbr))
        val = dampcoeff * (pos - sin(2 * np.pi * pos) / (2 * np.pi))
        val = -val if abc_type == "mask" else val
        eqs += [Inc(damp.subs({d: dim_r}), val / d.spacing)]

    Operator(eqs, name='initdamp')()
Exemplo n.º 6
0
def trig_func(model):
    """
    Trigonometric function of the tilt and azymuth angles.
    """
    try:
        theta = model.theta
    except AttributeError:
        theta = 0

    costheta = cos(theta)
    sintheta = sin(theta)
    if model.dim == 3:
        try:
            phi = model.phi
        except AttributeError:
            phi = 0

        cosphi = cos(phi)
        sinphi = sin(phi)
        return costheta, sintheta, cosphi, sinphi
    return costheta, sintheta