def test_interpolation_msf(): grid = Grid(shape=(4, 4)) r = 2 # Because we interpolate across 2 neighbouring points in each dimension nt = 10 m0 = TimeFunction(name="m0", grid=grid, space_order=0, save=nt, time_order=0) m1 = TimeFunction(name="m1", grid=grid, space_order=0, save=nt, time_order=0) mat = scipy.sparse.coo_matrix((0, 0), dtype=np.float32) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=r, matrix=mat, nt=nt) eqns = sf.inject(field=m0.forward, expr=sf.dt2) eqns += sf.inject(field=m1.forward, expr=sf.dt2) op0 = Operator(eqns) op1 = Operator(eqns, opt=('advanced', {'linearize': True})) assert 'm0L0' in str(op1) # There used to be a bug causing the jit compilation to fail because of # the writing to `const int` variables assert op0.cfunction assert op1.cfunction
def test_precomputed_subpoints_inject_dt2(self): shape = (101, 101) grid = Grid(shape=shape) x, y = grid.dimensions r = 2 # Constant for linear interpolation # because we interpolate across 2 neighbouring points in each dimension nt = 10 m = TimeFunction(name="m", grid=grid, space_order=0, save=None, time_order=1) m.data[:] = 0.0 m.data[:, 40, 40] = 1.0 matrix = scipy.sparse.coo_matrix(np.array([[1], [1]], dtype=np.float32)) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=r, matrix=matrix, nt=nt, time_order=2) # Lookup the exact point sf.gridpoints.data[0, 0] = 40 sf.gridpoints.data[0, 1] = 40 sf.interpolation_coefficients[x].data[0, 0] = 1.0 sf.interpolation_coefficients[x].data[0, 1] = 2.0 sf.interpolation_coefficients[y].data[0, 0] = 1.0 sf.interpolation_coefficients[y].data[0, 1] = 2.0 sf.gridpoints.data[1, 0] = 39 sf.gridpoints.data[1, 1] = 39 sf.interpolation_coefficients[x].data[1, 0] = 1.0 sf.interpolation_coefficients[x].data[1, 1] = 2.0 sf.interpolation_coefficients[y].data[1, 0] = 1.0 sf.interpolation_coefficients[y].data[1, 1] = 2.0 # Single timestep, -0.5*1e-6, so that with dt=0.001, the .dt2 == 1 at t=1 sf.data[1, 0] = -5e-7 step = [Eq(m.forward, m)] inject = sf.inject(field=m.forward, expr=sf.dt2) op = Operator(step + inject) sf.manual_scatter() op(time_m=1, time_M=1, dt=0.001) sf.manual_gather() assert m.data[0, 40, 40] == pytest.approx(6.0) # 1 + 1 + 4 assert m.data[0, 40, 41] == pytest.approx(2.0) assert m.data[0, 41, 40] == pytest.approx(2.0) assert m.data[0, 41, 41] == pytest.approx(4.0) assert m.data[0, 39, 39] == pytest.approx(1.0) assert m.data[0, 39, 40] == pytest.approx(2.0) assert m.data[0, 40, 39] == pytest.approx(2.0)
def test_msf_interpolate(): """ Test interpolation with MatrixSparseTimeFunction which accepts precomputed values for interpolation coefficients, but this time with a TimeFunction """ shape = (101, 101) points = [(.05, .9), (.01, .8), (0.07, 0.84)] origin = (0, 0) grid = Grid(shape=shape, origin=origin) r = 2 # Constant for linear interpolation # because we interpolate across 2 neighbouring points in each dimension u = TimeFunction(name='u', grid=grid, space_order=0, save=5) for it in range(5): u.data[it, :] = it gridpoints, interpolation_coeffs = precompute_linear_interpolation(points, grid, origin) matrix = scipy.sparse.eye(len(points)) sf = MatrixSparseTimeFunction( name='s', grid=grid, r=r, matrix=matrix, nt=5 ) sf.gridpoints.data[:] = gridpoints sf.coefficients_x.data[:] = interpolation_coeffs[:, 0, :] sf.coefficients_y.data[:] = interpolation_coeffs[:, 0, :] assert sf.data.shape == (5, 3) eqn = sf.interpolate(u) op = Operator(eqn) print(op) sf.manual_scatter() op(time_m=0, time_M=4) sf.manual_gather() for it in range(5): assert np.allclose(sf.data[it, :], it) # Now test injection u.data[:] = 0 eqn_inject = sf.inject(field=u, expr=sf) op2 = Operator(eqn_inject) print(op2) op2(time_m=0, time_M=4) # There should be 4 points touched for each source point # (5, 90), (1, 80), (7, 84) and x+1, y+1 for each nzt, nzx, nzy = np.nonzero(u.data) assert np.all(np.unique(nzx) == np.array([1, 2, 5, 6, 7, 8])) assert np.all(np.unique(nzy) == np.array([80, 81, 84, 85, 90, 91])) assert np.all(np.unique(nzt) == np.array([1, 2, 3, 4])) # 12 points x 4 timesteps assert nzt.size == 48
def test_precomputed_subpoints_inject(self): shape = (101, 101) grid = Grid(shape=shape) x, y = grid.dimensions r = 2 # Constant for linear interpolation # because we interpolate across 2 neighbouring points in each dimension nt = 10 m = TimeFunction(name="m", grid=grid, space_order=0, save=None, time_order=1) m.data[:] = 0.0 m.data[:, 40, 40] = 1.0 # Single two-component source with coefficients both +1 matrix = scipy.sparse.coo_matrix(np.array([[1], [1]], dtype=np.float32)) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=r, matrix=matrix, nt=nt) # Lookup the exact point sf.gridpoints.data[0, 0] = 40 sf.gridpoints.data[0, 1] = 40 sf.interpolation_coefficients[x].data[0, 0] = 1.0 sf.interpolation_coefficients[x].data[0, 1] = 2.0 sf.interpolation_coefficients[y].data[0, 0] = 1.0 sf.interpolation_coefficients[y].data[0, 1] = 2.0 sf.gridpoints.data[1, 0] = 39 sf.gridpoints.data[1, 1] = 39 sf.interpolation_coefficients[x].data[1, 0] = 1.0 sf.interpolation_coefficients[x].data[1, 1] = 2.0 sf.interpolation_coefficients[y].data[1, 0] = 1.0 sf.interpolation_coefficients[y].data[1, 1] = 2.0 sf.data[0, 0] = 1.0 step = [Eq(m.forward, m)] inject = sf.inject(field=m.forward, expr=sf) op = Operator(step + inject) sf.manual_scatter() op(time_m=0, time_M=0) sf.manual_gather() assert m.data[1, 40, 40] == 6.0 # 1 + 1 + 4 assert m.data[1, 40, 41] == 2.0 assert m.data[1, 41, 40] == 2.0 assert m.data[1, 41, 41] == 4.0 assert m.data[1, 39, 39] == 1.0 assert m.data[1, 39, 40] == 2.0 assert m.data[1, 40, 39] == 2.0
def test_precomputed_subpoints_inject(self, rxy, par_dim_index): shape = (101, 101) grid = Grid(shape=shape) x, y = grid.dimensions if isinstance(rxy, tuple): r = {grid.dimensions[0]: rxy[0], grid.dimensions[1]: rxy[1]} else: r = rxy par_dim = grid.dimensions[par_dim_index] nt = 10 m = TimeFunction(name="m", grid=grid, space_order=0, save=None, time_order=1) # Put some data in there to ensure it acts additively m.data[:] = 0.0 m.data[:, 40, 40] = 1.0 # Single two-component source with coefficients both +1 matrix = scipy.sparse.coo_matrix(np.array([[1], [1]], dtype=np.float32)) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=r, par_dim=par_dim, matrix=matrix, nt=nt) coeff_size_x = sf.interpolation_coefficients[x].data.shape[1] coeff_size_y = sf.interpolation_coefficients[y].data.shape[1] sf.gridpoints.data[0, 0] = 40 sf.gridpoints.data[0, 1] = 40 sf.gridpoints.data[1, 0] = 39 sf.gridpoints.data[1, 1] = 39 sf.interpolation_coefficients[x].data[ 0, :] = 1.0 + np.arange(coeff_size_x) sf.interpolation_coefficients[y].data[ 0, :] = 1.0 + np.arange(coeff_size_y) sf.interpolation_coefficients[x].data[ 1, :] = 1.0 + np.arange(coeff_size_x) sf.interpolation_coefficients[y].data[ 1, :] = 1.0 + np.arange(coeff_size_y) sf.data[0, 0] = 1.0 step = [Eq(m.forward, m)] inject = sf.inject(field=m.forward, expr=sf) op = Operator(step + inject) sf.manual_scatter() op(time_m=0, time_M=0) sf.manual_gather() check_coeffs = self._pure_python_coeffs(sf) expected_data1 = ( m.data[0] + np.tensordot(np.array(sf.data[0, :]), check_coeffs, axes=1)) assert np.all(m.data[1] == expected_data1)