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.)
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