コード例 #1
0
def solver(I, w, dt, T):
    """
    Solve u'=v, v' = - w**2*u for t in (0,T], u(0)=I and v(0)=0,
    by an Euler-Cromer method.
    """
    dt = float(dt)
    Nt = int(round(T/dt))
    
    t = Dimension('t', spacing=Constant('h_t'))
    v = TimeFunction(name='v', dimensions=(t,), shape=(Nt+1,), space_order=2)
    u = TimeFunction(name='u', dimensions=(t,), shape=(Nt+1,), space_order=2)

    v.data[:] = 0    
    u.data[:] = I

    eq_v = Eq(v.dt, -(w**2)*u)
    eq_u = Eq(u.dt, v.forward)
    
    stencil_v = solve(eq_v, v.forward)
    stencil_u = solve(eq_u, u.forward)
    
    update_v = Eq(v.forward, stencil_v)
    update_u = Eq(u.forward, stencil_u)
    

    op = Operator([update_v, update_u])
    op.apply(h_t=dt, t_M=Nt-1)

    return u.data, v.data, np.linspace(0, Nt*dt, Nt+1)
コード例 #2
0
def solver_v1(I, w, dt, T):
    """
    Solve u'=v, v' = - w**2*u for t in (0,T], u(0)=I and v(0)=0,
    by a central finite difference method with time step dt.
    """
    dt = float(dt)
    Nt = int(round(T/dt))
    
    t = Dimension('t', spacing=Constant('h_t'))
    u = TimeFunction(name='u', dimensions=(t,), shape=(Nt+1,), space_order=2)
    v = TimeFunction(name='v', dimensions=(t,), shape=(Nt+1,), space_order=2)

    u.data[:] = I
    v.data[:] = 0 - 0.5*dt*w**2*u.data[:]
    
    eq_u = Eq(u.dt, v)
    eq_v = Eq(v.dt, -(w**2)*u.forward)
    
    stencil_u = solve(eq_u, u.forward)
    stencil_v = solve(eq_v, v.forward)
    
    update_u = Eq(u.forward, stencil_u)
    update_v = Eq(v.forward, stencil_v)
    
    op = Operator([update_u, update_v])
    op.apply(h_t=dt, t_M=Nt-1)

    t_mesh = np.linspace(0, Nt*dt, Nt+1)    # mesh for u
    t_v_mesh = (t_mesh + dt/2)[:-1]         # mesh for v

    return u.data, t_mesh, v.data, t_v_mesh
コード例 #3
0
    def test_solve(self, operate_on_empty_cache):
        """
        Test to ensure clear_cache wipes out *all of* sympy caches. ``sympy.solve``,
        in particular, relies on a series of private caches that must be purged too
        (calling sympy's clear_cache() API function isn't enough).
        """
        grid = Grid(shape=(4, ))

        u = TimeFunction(name='u', grid=grid, time_order=1, space_order=2)

        eqn = Eq(u.dt, u.dx2)
        solve(eqn, u.forward)

        del u
        del eqn
        del grid

        # `u` points to the various Dimensions, the Dimensions point to the various
        # spacing symbols, hence, we need three sweeps to clear up the cache
        assert len(_SymbolCache) == 12
        clear_cache()
        assert len(_SymbolCache) == 8
        clear_cache()
        assert len(_SymbolCache) == 2
        clear_cache()
        assert len(_SymbolCache) == 0
コード例 #4
0
    def test_solve(self, operate_on_empty_cache):
        """
        Test to ensure clear_cache wipes out *all of* sympy caches. ``sympy.solve``,
        in particular, relies on a series of private caches that must be purged too
        (calling sympy's clear_cache() API function isn't enough).
        """
        grid = Grid(shape=(4,))

        u = TimeFunction(name='u', grid=grid, time_order=1, space_order=2)

        eqn = Eq(u.dt, u.dx2)
        solve(eqn, u.forward)

        del u
        del eqn
        del grid

        # We only deleted `u`, however we also cache shifted version created by the
        # finite difference (u.dt, u.dx2). In this case we have three extra references
        # to u(t + dt), u(x - h_x) and u(x + h_x) that have to be cleared.
        # Then `u` points to the various Dimensions, the Dimensions point to the various
        # spacing symbols, hence, we need four sweeps to clear up the cache.
        assert len(_SymbolCache) == 16
        clear_cache()
        assert len(_SymbolCache) == 9
        clear_cache()
        assert len(_SymbolCache) == 3
        clear_cache()
        assert len(_SymbolCache) == 1
        clear_cache()
        assert len(_SymbolCache) == 0
コード例 #5
0
def solver_FECS(I, U0, v, L, dt, C, T, user_action=None):
    Nt = int(round(T / float(dt)))
    t = np.linspace(0, Nt * dt, Nt + 1)  # Mesh points in time
    dx = v * dt / C
    Nx = int(round(L / dx))
    x = np.linspace(0, L, Nx + 1)  # Mesh points in space

    # Make sure dx and dt are compatible with x and t
    dx = float(x[1] - x[0])
    dt = float(t[1] - t[0])
    C = v * dt / dx

    grid = Grid(shape=(Nx + 1, ), extent=(L, ))
    t_s = grid.time_dim

    u = TimeFunction(name='u', grid=grid, space_order=2, save=Nt + 1)

    pde = u.dtr + v * u.dxc

    stencil = solve(pde, u.forward)
    eq = Eq(u.forward, stencil)

    # Set initial condition u(x,0) = I(x)
    u.data[1, :] = [I(xi) for xi in x]

    # Insert boundary condition
    bc = [Eq(u[t_s + 1, 0], U0)]

    op = Operator([eq] + bc)
    op.apply(dt=dt, x_m=1, x_M=Nx - 1)

    if user_action is not None:
        for n in range(0, Nt + 1):
            user_action(u.data[n], x, t, n)
コード例 #6
0
ファイル: operators.py プロジェクト: yuriyi/devito
def iso_stencil(field, m, s, damp, kernel, **kwargs):
    """
    Stencil for the acoustic isotropic wave-equation:
    u.dt2 - H + damp*u.dt = 0
    :param field: Symbolic TimeFunction object, solution to be computed
    :param m: square slowness
    :param s: symbol for the time-step
    :param damp: ABC dampening field (Function)
    :param kwargs: forwad/backward wave equation (sign of u.dt will change accordingly
    as well as the updated time-step (u.forwad or u.backward)
    :return: Stencil for the wave-equation
    """

    # Creat a temporary symbol for H to avoid expensive sympy solve
    H = Symbol('H')
    # Define time sep to be updated
    next = field.forward if kwargs.get('forward', True) else field.backward
    # Define PDE
    eq = m * field.dt2 - H - kwargs.get('q', 0)
    # Add dampening field according to the propagation direction
    eq += damp * field.dt if kwargs.get('forward', True) else -damp * field.dt
    # Solve the symbolic equation for the field to be updated
    eq_time = solve(eq, next)
    # Get the spacial FD
    lap = laplacian(field, m, s, kernel)
    # return the Stencil with H replaced by its symbolic expression
    return [Eq(next, eq_time.subs({H: lap}))]
コード例 #7
0
def iso_stencil(field, m, s, damp, kernel, **kwargs):
    """
    Stencil for the acoustic isotropic wave-equation:
    u.dt2 - H + damp*u.dt = 0.

    Parameters
    ----------
    field : TimeFunction
        The computed solution.
    m : Function or float
        Square slowness.
    s : float or Scalar
        The time dimension spacing.
    damp : Function
        The damping field for absorbing boundary condition.
    forward : bool
        The propagation direction. Defaults to True.
    q : TimeFunction, Function or float
        Full-space/time source of the wave-equation.
    """

    # Creat a temporary symbol for H to avoid expensive sympy solve
    H = Symbol('H')
    # Define time sep to be updated
    next = field.forward if kwargs.get('forward', True) else field.backward
    # Define PDE
    eq = m * field.dt2 - H - kwargs.get('q', 0)
    # Add dampening field according to the propagation direction
    eq += damp * field.dt if kwargs.get('forward', True) else damp * field.dt.T
    # Solve the symbolic equation for the field to be updated
    eq_time = solve(eq, next)
    # Get the spacial FD
    lap = laplacian(field, m, s, kernel)
    # return the Stencil with H replaced by its symbolic expression
    return [Eq(next, eq_time.subs({H: lap}))]
コード例 #8
0
def test_issue_1725():
    class ToyPMLLeft(SubDomain):
        name = 'toypmlleft'

        def define(self, dimensions):
            x, y = dimensions
            return {x: x, y: ('left', 2)}

    class ToyPMLRight(SubDomain):
        name = 'toypmlright'

        def define(self, dimensions):
            x, y = dimensions
            return {x: x, y: ('right', 2)}

    subdomains = [ToyPMLLeft(), ToyPMLRight()]
    grid = Grid(shape=(20, 20), subdomains=subdomains)

    u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2)

    eqns = [
        Eq(u.forward, solve(u.dt2 - u.laplace, u.forward), subdomain=sd)
        for sd in subdomains
    ]

    op = Operator(eqns, opt='fission')

    # Note the `x` loop is fissioned, so now both loop nests can be collapsed
    # for maximum parallelism
    assert_structure(op, ['t,x,i1y', 't,x,i2y'], 't,x,i1y,x,i2y')
コード例 #9
0
def execute_devito(ui,
                   spacing=0.01,
                   a=0.5,
                   timesteps=500,
                   space_order=2,
                   dse="advanced"):
    """Execute diffusion stencil using the devito Operator API."""
    nx, ny = ui.shape
    dx2, dy2 = spacing**2, spacing**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))
    # Allocate the grid and set initial condition
    # Note: This should be made simpler through the use of defaults
    grid = Grid(shape=(nx, ny))
    u = TimeFunction(name='u',
                     grid=grid,
                     time_order=1,
                     space_order=space_order)
    u.data[0, :] = ui[:]

    # Derive the stencil according to devito conventions
    eqn = Eq(u.dt, a * (u.dx2 + u.dy2))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil), dse=dse)

    # Execute the generated Devito stencil operator
    summary = op.apply(u=u, t=timesteps, dt=dt)
    return summary.gflopss, summary.oi, summary.timings
コード例 #10
0
 def __init__(self, shape, order):
     grid = Grid(shape=shape)
     c = 10.0
     u = TimeFunction(name='u', grid=grid, spc_order=order)
     eq = Eq(u.dt + c * u.dxl + c * u.dyl)
     stencil = solve(eq, u.forward)
     self.op = Operator([Eq(u.forward, stencil)])
コード例 #11
0
ファイル: operators.py プロジェクト: opesci/devito
def iso_stencil(field, m, s, damp, kernel, **kwargs):
    """
    Stencil for the acoustic isotropic wave-equation:
    u.dt2 - H + damp*u.dt = 0
    :param field: Symbolic TimeFunction object, solution to be computed
    :param m: square slowness
    :param s: symbol for the time-step
    :param damp: ABC dampening field (Function)
    :param kwargs: forwad/backward wave equation (sign of u.dt will change accordingly
    as well as the updated time-step (u.forwad or u.backward)
    :return: Stencil for the wave-equation
    """

    # Creat a temporary symbol for H to avoid expensive sympy solve
    H = Symbol('H')
    # Define time sep to be updated
    next = field.forward if kwargs.get('forward', True) else field.backward
    # Define PDE
    eq = m * field.dt2 - H - kwargs.get('q', 0)
    # Add dampening field according to the propagation direction
    eq += damp * field.dt if kwargs.get('forward', True) else -damp * field.dt
    # Solve the symbolic equation for the field to be updated
    eq_time = solve(eq, next)
    # Get the spacial FD
    lap = laplacian(field, m, s, kernel)
    # return the Stencil with H replaced by its symbolic expression
    return [Eq(next, eq_time.subs({H: lap}))]
コード例 #12
0
ファイル: test_constant.py プロジェクト: opesci/devito
    def test_const_change(self):
        """
        Test that Constand.data can be set as required.
        """

        n = 5
        t = Constant(name='t', dtype=np.int32)

        grid = Grid(shape=(2, 2))
        x, y = grid.dimensions

        f = TimeFunction(name='f', grid=grid, save=n+1)
        f.data[:] = 0
        eq = Eq(f.dt-1)
        stencil = Eq(f.forward, solve(eq, f.forward))
        op = Operator([stencil])
        op.apply(time_m=0, time_M=n-1, dt=1)

        check = Function(name='check', grid=grid)
        eq_test = Eq(check, f[t, x, y])
        op_test = Operator([eq_test])
        for j in range(0, n+1):
            t.data = j  # Ensure constant is being updated correctly
            op_test.apply(t=t)
            assert(np.amax(check.data[:], axis=None) == j)
            assert(np.amin(check.data[:], axis=None) == j)
コード例 #13
0
def test_solve(so):
    """
    Test that our solve produces the correct output and faster than sympy's
    default behavior for an affine equation (i.e. PDE time steppers).
    """
    grid = Grid((10, 10, 10))
    u = TimeFunction(name="u", grid=grid, time_order=2, space_order=so)
    v = Function(name="v", grid=grid, space_order=so)
    eq = u.dt2 - div(v * grad(u))

    # Standard sympy solve
    t0 = time.time()
    sol1 = sympy.solve(eq.evaluate, u.forward, rational=False, simplify=False)[0]
    t1 = time.time() - t0

    # Devito custom solve for linear equation in the target ax + b (most PDE tie steppers)
    t0 = time.time()
    sol2 = solve(eq.evaluate, u.forward)
    t12 = time.time() - t0

    diff = sympy.simplify(sol1 - sol2)
    # Difference can end up with super small coeffs with different evaluation
    # so zero out everything very small
    assert diff.xreplace({k: 0 if abs(k) < 1e-10 else k
                          for k in diff.atoms(sympy.Float)}) == 0
    # Make sure faster (actually much more than 10 for very complex cases)
    assert t12 < t1/10
コード例 #14
0
def ImagingOperator(model, image):
    # Define the wavefield with the size of the model and the time dimension
    v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=4)

    u = TimeFunction(name='u',
                     grid=model.grid,
                     time_order=2,
                     space_order=4,
                     save=geometry.nt)

    # Define the wave equation, but with a negated damping term
    eqn = model.m * v.dt2 - v.laplace - model.damp * v.dt

    # Use `solve` to rearrange the equation into a stencil expression
    stencil = Eq(v.backward, solve(eqn, v.backward))

    # Define residual injection at the location of the forward receivers
    dt = model.critical_dt
    residual = PointSource(name='residual',
                           grid=model.grid,
                           time_range=geometry.time_axis,
                           coordinates=geometry.rec_positions)
    res_term = residual.inject(field=v, expr=residual * dt**2 / model.m)

    # Correlate u and v for the current time step and add it to the image
    image_update = Eq(image, image - u * v)

    return Operator([stencil] + res_term + [image_update],
                    subs=model.spacing_map)
コード例 #15
0
def iso_stencil(field, m, s, damp, kernel, **kwargs):
    """
    Stencil for the acoustic isotropic wave-equation:
    u.dt2 - H + damp*u.dt = 0.

    Parameters
    ----------
    field : TimeFunction
        The computed solution.
    m : Function or float
        Square slowness.
    s : float or Scalar
        The time dimension spacing.
    damp : Function
        The damping field for absorbing boundary condition.
    forward : bool
        The propagation direction. Defaults to True.
    q : TimeFunction, Function or float
        Full-space/time source of the wave-equation.
    """
    # Forward or backward
    forward = kwargs.get('forward', True)
    # Define time step to be updated
    unext = field.forward if forward else field.backward
    udt = field.dt if forward else field.dt.T
    # Get the spacial FD
    lap = laplacian(field, m, s, kernel)
    # Get source
    q = kwargs.get('q', 0)
    # Define PDE and update rule
    eq_time = solve(m * field.dt2 - lap - q + damp * udt, unext)
    # Time update stencil
    return [Eq(unext, eq_time)]
コード例 #16
0
ファイル: test_constant.py プロジェクト: yohanesnuwara/devito
    def test_const_change(self):
        """
        Test that Constand.data can be set as required.
        """

        n = 5
        t = Constant(name='t', dtype=np.int32)

        grid = Grid(shape=(2, 2))
        x, y = grid.dimensions

        f = TimeFunction(name='f', grid=grid, save=n+1)
        f.data[:] = 0
        eq = Eq(f.dt-1)
        stencil = Eq(f.forward, solve(eq, f.forward))
        op = Operator([stencil])
        op.apply(time_m=0, time_M=n-1, dt=1)

        check = Function(name='check', grid=grid)
        eq_test = Eq(check, f[t, x, y])
        op_test = Operator([eq_test])
        for j in range(0, n+1):
            t.data = j  # Ensure constant is being updated correctly
            op_test.apply(t=t)
            assert(np.amax(check.data[:], axis=None) == j)
            assert(np.amin(check.data[:], axis=None) == j)
コード例 #17
0
ファイル: test_dle.py プロジェクト: sujathakestur/devito
def _new_operator3(shape, blockshape0=None, blockshape1=None, dle=None):
    blockshape0 = as_tuple(blockshape0)
    blockshape1 = as_tuple(blockshape1)

    grid = Grid(shape=shape, dtype=np.float64)
    spacing = 0.1
    a = 0.5
    c = 0.5
    dx2, dy2 = spacing**2, spacing**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))

    # Allocate the grid and set initial condition
    # Note: This should be made simpler through the use of defaults
    u = TimeFunction(name='u', grid=grid, time_order=1, space_order=(2, 2, 2))
    u.data[0, :] = np.arange(reduce(mul, shape), dtype=np.int32).reshape(shape)

    # Derive the stencil according to devito conventions
    eqn = Eq(u.dt, a * (u.dx2 + u.dy2) - c * (u.dxl + u.dyl))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil), dle=dle)

    blocksizes0 = get_blocksizes(op, dle, grid, blockshape0, 0)
    blocksizes1 = get_blocksizes(op, dle, grid, blockshape1, 1)
    op.apply(u=u, t=10, dt=dt, **blocksizes0, **blocksizes1)

    return u.data[1, :], op
コード例 #18
0
def td_born_adjoint_op(model, geometry, time_order, space_order):

    nt = geometry.nt

    # Define the wavefields with the size of the model and the time dimension
    u = TimeFunction(
        name='u',
        grid=model.grid,
        time_order=time_order,
        space_order=space_order,
        save=nt
    )

    # Define the wave equation
    pde = model.m * u.dt2 - u.laplace + model.damp * u.dt.T

    # Use `solve` to rearrange the equation into a stencil expression
    stencil = Eq(u.backward, solve(pde, u.backward), subdomain=model.grid.subdomains['physdomain'])

    # Inject at receivers
    born_data_rec = PointSource(
        name='born_data_rec',
        grid=model.grid,
        time_range=geometry.time_axis,
        coordinates=geometry.rec_positions
    )
    dt = Constant(name='dt')
    rec_term = born_data_rec.inject(field=u.backward, expr=born_data_rec * (dt ** 2) / model.m)

    return Operator([stencil] + rec_term, subs=model.spacing_map)
コード例 #19
0
    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))
コード例 #20
0
def reference_shot(model, time_range, f0):
    """
    Produce a reference shot gather with a level, conventional free-surface
    implementation.
    """
    src = RickerSource(name='src',
                       grid=model.grid,
                       f0=f0,
                       npoint=1,
                       time_range=time_range)

    # First, position source centrally in all dimensions, then set depth
    src.coordinates.data[0, :] = np.array(model.domain_size) * .5
    # Remember that 0, 0, 0 is top left corner
    # Depth is 100m from free-surface boundary
    src.coordinates.data[0, -1] = 600.

    # Create symbol for 101 receivers
    rec = Receiver(name='rec',
                   grid=model.grid,
                   npoint=101,
                   time_range=time_range)

    # Prescribe even spacing for receivers along the x-axis
    rec.coordinates.data[:, 0] = np.linspace(0, model.domain_size[0], num=101)
    rec.coordinates.data[:, 1] = 500.  # Centered on y axis
    rec.coordinates.data[:, 2] = 650.  # Depth is 150m from free surface

    # Define the wavefield with the size of the model and the time dimension
    u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=4)

    # We can now write the PDE
    pde = model.m * u.dt2 - u.laplace + model.damp * u.dt

    stencil = Eq(u.forward, solve(pde, u.forward))

    # Finally we define the source injection and receiver read function
    src_term = src.inject(field=u.forward,
                          expr=src * model.critical_dt**2 / model.m)

    # Create interpolation expression for receivers
    rec_term = rec.interpolate(expr=u.forward)

    x, y, z = model.grid.dimensions
    time = u.grid.stepping_dim
    # Throw a free surface in here
    free_surface_0 = Eq(u[time + 1, x, y, 60], 0)
    free_surface_1 = Eq(u[time + 1, x, y, 59], -u[time + 1, x, y, 61])
    free_surface_2 = Eq(u[time + 1, x, y, 58], -u[time + 1, x, y, 62])
    free_surface = [free_surface_0, free_surface_1, free_surface_2]

    op = Operator([stencil] + src_term + rec_term + free_surface)

    op(time=time_range.num - 1, dt=model.critical_dt)

    return rec.data
コード例 #21
0
    def iso_acoustic(self, opt):
        shape = (101, 101)
        extent = (1000, 1000)
        origin = (0., 0.)

        v = np.empty(shape, dtype=np.float32)
        v[:, :51] = 1.5
        v[:, 51:] = 2.5

        grid = Grid(shape=shape, extent=extent, origin=origin)

        t0 = 0.
        tn = 1000.
        dt = 1.6
        time_range = TimeAxis(start=t0, stop=tn, step=dt)

        f0 = 0.010
        src = RickerSource(name='src',
                           grid=grid,
                           f0=f0,
                           npoint=1,
                           time_range=time_range)

        domain_size = np.array(extent)

        src.coordinates.data[0, :] = domain_size * .5
        src.coordinates.data[0, -1] = 20.

        rec = Receiver(name='rec',
                       grid=grid,
                       npoint=101,
                       time_range=time_range)
        rec.coordinates.data[:, 0] = np.linspace(0, domain_size[0], num=101)
        rec.coordinates.data[:, 1] = 20.

        u = TimeFunction(name="u", grid=grid, time_order=2, space_order=2)
        m = Function(name='m', grid=grid)
        m.data[:] = 1. / (v * v)

        pde = m * u.dt2 - u.laplace
        stencil = Eq(u.forward, solve(pde, u.forward))

        src_term = src.inject(field=u.forward, expr=src * dt**2 / m)
        rec_term = rec.interpolate(expr=u.forward)

        op = Operator([stencil] + src_term + rec_term,
                      opt=opt,
                      language='openmp')

        # Make sure we've indeed generated OpenMP offloading code
        assert 'omp target' in str(op)

        op(time=time_range.num - 1, dt=dt)

        assert np.isclose(norm(rec), 490.55, atol=1e-2, rtol=0)
コード例 #22
0
 def diffusion_stencil():
     """Create stencil and substitutions for the diffusion equation"""
     p = sympy.Function('p')
     x, y, t, h, s = sympy.symbols('x y t h s')
     dx2 = p(x, y, t).diff(x, x).as_finite_difference([x - h, x, x + h])
     dy2 = p(x, y, t).diff(y, y).as_finite_difference([y - h, y, y + h])
     dt = p(x, y, t).diff(t).as_finite_difference([t, t + s])
     eqn = Eq(dt, a * (dx2 + dy2))
     stencil = solve(eqn, p(x, y, t + s))
     return stencil, (p(x, y, t), p(x + h, y, t), p(x - h, y, t),
                      p(x, y + h, t), p(x, y - h, t), s, h)
コード例 #23
0
ファイル: operators.py プロジェクト: mmohrhard/devito
def second_order_stencil(model, u, v, H0, Hz, forward=True):
    """
    Creates the stencil corresponding to the second order TTI wave equation
    m * u.dt2 =  (epsilon * H0 + delta * Hz) - damp * u.dt
    m * v.dt2 =  (delta * H0 + Hz) - damp * v.dt
    """
    m, damp = model.m, model.damp

    unext = u.forward if forward else u.backward
    vnext = v.forward if forward else v.backward
    udt = u.dt if forward else u.dt.T
    vdt = v.dt if forward else v.dt.T

    # Stencils
    stencilp = solve(m * u.dt2 - H0 + damp * udt, unext)
    stencilr = solve(m * v.dt2 - Hz + damp * vdt, vnext)

    first_stencil = Eq(unext, stencilp)
    second_stencil = Eq(vnext, stencilr)

    stencils = [first_stencil, second_stencil]
    return stencils
コード例 #24
0
ファイル: test_save.py プロジェクト: opesci/devito
def run_simulation(save=False, dx=0.01, dy=0.01, a=0.5, timesteps=100):
    nx, ny = int(1 / dx), int(1 / dy)
    dx2, dy2 = dx**2, dy**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))

    grid = Grid(shape=(nx, ny))
    u = TimeFunction(name='u', grid=grid, save=timesteps if save else None,
                     initializer=initializer, time_order=1, space_order=2)

    eqn = Eq(u.dt, a * (u.dx2 + u.dy2))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil))
    op.apply(time=timesteps-2, dt=dt)

    return u.data[timesteps - 1]
コード例 #25
0
def run_simulation(save=False, dx=0.01, dy=0.01, a=0.5, timesteps=100):
    nx, ny = int(1 / dx), int(1 / dy)
    dx2, dy2 = dx**2, dy**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))

    grid = Grid(shape=(nx, ny))
    u = TimeFunction(name='u', grid=grid, save=timesteps if save else None,
                     initializer=initializer, time_order=1, space_order=2)

    eqn = Eq(u.dt, a * (u.dx2 + u.dy2))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil))
    op.apply(time=timesteps-2, dt=dt)

    return u.data[timesteps - 1]
コード例 #26
0
    def test_solve(self):
        """
        By remaining unevaluated until after Operator's collect_derivatives,
        the Derivatives after a solve() should be collected.
        """
        grid = Grid(shape=(10, 10))

        u = TimeFunction(name="u", grid=grid, space_order=4, time_order=2)

        pde = u.dt2 - (u.dx.dx + u.dy.dy) - u.dx.dy
        eq = Eq(u.forward, solve(pde, u.forward))
        leq = collect_derivatives.func([eq])[0]

        assert len(eq.rhs.find(Derivative)) == 5
        assert len(leq.rhs.find(Derivative)) == 4
        assert len(
            leq.rhs.args[2].find(Derivative)) == 3  # Check factorization
コード例 #27
0
    def test_subdomainset_mpi(self):

        n_domains = 5

        class Inner(SubDomainSet):
            name = 'inner'

        bounds_xm = np.zeros((n_domains, ), dtype=np.int32)
        bounds_xM = np.zeros((n_domains, ), dtype=np.int32)
        bounds_ym = np.zeros((n_domains, ), dtype=np.int32)
        bounds_yM = np.zeros((n_domains, ), dtype=np.int32)

        for j in range(0, n_domains):
            bounds_xm[j] = j
            bounds_xM[j] = j
            bounds_ym[j] = j
            bounds_yM[j] = 2 * n_domains - 1 - j

        bounds = (bounds_xm, bounds_xM, bounds_ym, bounds_yM)

        inner_sd = Inner(N=n_domains, bounds=bounds)

        grid = Grid(extent=(10, 10), shape=(10, 10), subdomains=(inner_sd, ))

        assert (grid.subdomains['inner'].shape == ((10, 1), (8, 1), (6, 1),
                                                   (4, 1), (2, 1)))

        f = TimeFunction(name='f', grid=grid, dtype=np.int32)
        f.data[:] = 0

        stencil = Eq(f.forward,
                     solve(Eq(f.dt, 1), f.forward),
                     subdomain=grid.subdomains['inner'])

        op = Operator(stencil)
        op(time_m=0, time_M=9, dt=1)
        result = f.data[0]

        fex = Function(name='fex', grid=grid)
        expected = np.zeros((10, 10), dtype=np.int32)
        for j in range(0, n_domains):
            expected[j, j:10 - j] = 10
        fex.data[:] = np.transpose(expected)

        assert ((np.array(result) == np.array(fex.data[:])).all())
コード例 #28
0
    def test_iterate_NDomains(self):
        """
        Test that a set of subdomains are iterated upon correctly.
        """

        n_domains = 10

        class Inner(SubDomainSet):
            name = 'inner'

        bounds_xm = np.zeros((n_domains, ), dtype=np.int32)
        bounds_xM = np.zeros((n_domains, ), dtype=np.int32)
        bounds_ym = np.zeros((n_domains, ), dtype=np.int32)
        bounds_yM = np.zeros((n_domains, ), dtype=np.int32)

        for j in range(0, n_domains):
            bounds_xm[j] = j
            bounds_xM[j] = n_domains - 1 - j
            bounds_ym[j] = floor(j / 2)
            bounds_yM[j] = floor(j / 2)

        bounds = (bounds_xm, bounds_xM, bounds_ym, bounds_yM)

        inner_sd = Inner(N=n_domains, bounds=bounds)

        grid = Grid(extent=(10, 10), shape=(10, 10), subdomains=(inner_sd, ))

        f = TimeFunction(name='f', grid=grid, dtype=np.int32)
        f.data[:] = 0

        stencil = Eq(f.forward,
                     solve(Eq(f.dt, 1), f.forward),
                     subdomain=grid.subdomains['inner'])

        op = Operator(stencil)
        op(time_m=0, time_M=9, dt=1)
        result = f.data[0]

        expected = np.zeros((10, 10), dtype=np.int32)
        for j in range(0, n_domains):
            expected[j, bounds_ym[j]:n_domains - bounds_yM[j]] = 10

        assert ((np.array(result) == expected).all())
コード例 #29
0
def td_born_forward_op(model, geometry, time_order, space_order):

    nt = geometry.nt

    # Define the wavefields with the size of the model and the time dimension
    u0 = TimeFunction(
        name='u0',
        grid=model.grid,
        time_order=time_order,
        space_order=space_order,
        save=nt
    )
    u = TimeFunction(
        name='u',
        grid=model.grid,
        time_order=time_order,
        space_order=space_order,
        save=nt
    )
    dm = TimeFunction(
        name='dm',
        grid=model.grid,
        time_order=time_order,
        space_order=space_order,
        save=nt
    )

    # Define the wave equation
    pde = model.m * u.dt2 - u.laplace + model.damp * u.dt - dm * u0

    # Use `solve` to rearrange the equation into a stencil expression
    stencil = Eq(u.forward, solve(pde, u.forward), subdomain=model.grid.subdomains['physdomain'])

    # Sample at receivers
    born_data_rec = PointSource(
        name='born_data_rec',
        grid=model.grid,
        time_range=geometry.time_axis,
        coordinates=geometry.rec_positions
    )
    rec_term = born_data_rec.interpolate(expr=u)

    return Operator([stencil] + rec_term, subs=model.spacing_map)
コード例 #30
0
def solver(I, w, dt, T):
    """
    Solve u'' + w**2*u = 0 for t in (0,T], u(0)=I and u'(0)=0,
    by a central finite difference method with time step dt.
    """
    dt = float(dt)
    Nt = int(round(T / dt))
    t = Dimension('t', spacing=Constant('h_t'))

    u = TimeFunction(name='u',
                     dimensions=(t, ),
                     shape=(Nt + 1, ),
                     space_order=2)

    u.data[:] = I
    eqn = u.dt2 + (w**2) * u
    stencil = Eq(u.forward, solve(eqn, u.forward))
    op = Operator(stencil)
    op.apply(h_t=dt, t_M=Nt - 1)
    return u.data, np.linspace(0, Nt * dt, Nt + 1)
コード例 #31
0
ファイル: test_dle.py プロジェクト: yuriyi/devito
def _new_operator3(shape, **kwargs):
    grid = Grid(shape=shape)
    spacing = 0.1
    a = 0.5
    c = 0.5
    dx2, dy2 = spacing**2, spacing**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))

    # Allocate the grid and set initial condition
    # Note: This should be made simpler through the use of defaults
    u = TimeFunction(name='u', grid=grid, time_order=1, space_order=(2, 2, 2))
    u.data[0, :] = np.arange(reduce(mul, shape), dtype=np.int32).reshape(shape)

    # Derive the stencil according to devito conventions
    eqn = Eq(u.dt, a * (u.dx2 + u.dy2) - c * (u.dxl + u.dyl))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil), **kwargs)

    # Execute the generated Devito stencil operator
    op.apply(u=u, t=10, dt=dt)
    return u.data[1, :], op
コード例 #32
0
ファイル: test_dle.py プロジェクト: opesci/devito
def _new_operator3(shape, blockshape=None, dle=None):
    blockshape = as_tuple(blockshape)
    grid = Grid(shape=shape)
    spacing = 0.1
    a = 0.5
    c = 0.5
    dx2, dy2 = spacing**2, spacing**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))

    # Allocate the grid and set initial condition
    # Note: This should be made simpler through the use of defaults
    u = TimeFunction(name='u', grid=grid, time_order=1, space_order=(2, 2, 2))
    u.data[0, :] = np.arange(reduce(mul, shape), dtype=np.int32).reshape(shape)

    # Derive the stencil according to devito conventions
    eqn = Eq(u.dt, a * (u.dx2 + u.dy2) - c * (u.dxl + u.dyl))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil), dle=dle)

    blocksizes = get_blocksizes(op, dle, grid, blockshape)
    op.apply(u=u, t=10, dt=dt, **blocksizes)

    return u.data[1, :], op
コード例 #33
0
def execute_devito(ui, spacing=0.01, a=0.5, timesteps=500):
    """Execute diffusion stencil using the devito Operator API."""
    nx, ny = ui.shape
    dx2, dy2 = spacing**2, spacing**2
    dt = dx2 * dy2 / (2 * a * (dx2 + dy2))
    # Allocate the grid and set initial condition
    # Note: This should be made simpler through the use of defaults
    grid = Grid(shape=(nx, ny))
    u = TimeFunction(name='u', grid=grid, time_order=1, space_order=2)
    u.data[0, :] = ui[:]

    # Derive the stencil according to devito conventions
    eqn = Eq(u.dt, a * (u.dx2 + u.dy2))
    stencil = solve(eqn, u.forward)
    op = Operator(Eq(u.forward, stencil))

    # Execute the generated Devito stencil operator
    tstart = time.time()
    op.apply(u=u, t=timesteps, dt=dt)
    runtime = time.time() - tstart
    log("Devito: Diffusion with dx=%0.4f, dy=%0.4f, executed %d timesteps in %f seconds"
        % (spacing, spacing, timesteps, runtime))
    return u.data[1, :], runtime
コード例 #34
0
def iso_stencil(field, model, kernel, **kwargs):
    """
    Stencil for the acoustic isotropic wave-equation:
    u.dt2 - H + damp*u.dt = 0.

    Parameters
    ----------
    field : TimeFunction
        The computed solution.
    model : Model
        Physical model.
    kernel : str, optional
        Type of discretization, 'OT2' or 'OT4'.
    q : TimeFunction, Function or float
        Full-space/time source of the wave-equation.
    forward : bool, optional
        Whether to propagate forward (True) or backward (False) in time.
    """
    # Forward or backward
    forward = kwargs.get('forward', True)
    # Define time step to be updated
    unext = field.forward if forward else field.backward
    udt = field.dt if forward else field.dt.T
    # Get the spacial FD
    lap = laplacian(field, model, kernel)
    # Get source
    q = kwargs.get('q', 0)
    # Define PDE and update rule
    eq_time = solve(model.m * field.dt2 - lap - q + model.damp * udt, unext)

    # Time-stepping stencil.
    eqns = [Eq(unext, eq_time, subdomain=model.grid.subdomains['physdomain'])]

    # Add free surface
    if model.fs:
        eqns.append(freesurface(model, Eq(unext, eq_time)))
    return eqns