예제 #1
0
    def test_expandingbox_like(self, opt):
        """
        Make sure SubDimensions aren't an obstacle to expanding boxes.
        """
        grid = Grid(shape=(8, 8))
        x, y = grid.dimensions

        u = TimeFunction(name='u', grid=grid)
        xi = SubDimension.middle(name='xi', parent=x, thickness_left=2, thickness_right=2)
        yi = SubDimension.middle(name='yi', parent=y, thickness_left=2, thickness_right=2)

        eqn = Eq(u.forward, u + 1)
        eqn = eqn.subs({x: xi, y: yi})

        op = Operator(eqn, opt=opt)

        op.apply(time=3, x_m=2, x_M=5, y_m=2, y_M=5,
                 xi_ltkn=0, xi_rtkn=0, yi_ltkn=0, yi_rtkn=0)

        assert np.all(u.data[0, 2:-2, 2:-2] == 4.)
        assert np.all(u.data[1, 2:-2, 2:-2] == 3.)
        assert np.all(u.data[:, :2] == 0.)
        assert np.all(u.data[:, -2:] == 0.)
        assert np.all(u.data[:, :, :2] == 0.)
        assert np.all(u.data[:, :, -2:] == 0.)
예제 #2
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