def test_empty_arrays(self): """ MFE for issue #1641. """ grid = Grid(shape=(4, 4), extent=(3.0, 3.0)) f = TimeFunction(name='f', grid=grid, space_order=0) f.data[:] = 1. sf1 = SparseTimeFunction(name='sf1', grid=grid, npoint=0, nt=10) sf2 = SparseTimeFunction(name='sf2', grid=grid, npoint=0, nt=10) assert sf1.size == 0 assert sf2.size == 0 eqns = sf1.inject(field=f, expr=sf1 + sf2 + 1.) op = Operator(eqns) op.apply() assert np.all(f.data == 1.) # Again, but with a MatrixSparseTimeFunction mat = scipy.sparse.coo_matrix((0, 0), dtype=np.float32) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=2, matrix=mat, nt=10) assert sf.size == 0 eqns = sf.interpolate(f) op = Operator(eqns) sf.manual_scatter() op(time_m=0, time_M=9) sf.manual_gather() assert np.all(f.data == 1.)
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_mpi(self): # Shape chosen to get a source in multiple ranks shape = (91, 91) grid = Grid(shape=shape) x, y = grid.dimensions # because we interpolate across 2 neighbouring points in each dimension r = 2 nt = 10 # NOTE: halo on function (space_order//2?) must be at least >= r m = TimeFunction(name="m", grid=grid, space_order=4, save=None, time_order=1) m.data[:] = 0.0 m.data[:, 40, 40] = 1.0 m.data[:, 50, 50] = 1.0 # only rank 0 is allowed to have points if grid.distributor.myrank == 0: # A single dipole source - so two rows, one column matrix = scipy.sparse.coo_matrix( np.array([[1], [-1]], dtype=np.float32)) else: matrix = scipy.sparse.coo_matrix((0, 0), dtype=np.float32) sf = MatrixSparseTimeFunction(name="s", grid=grid, r=r, matrix=matrix, nt=nt) if grid.distributor.myrank == 0: # First component of the dipole at 40, 40 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] = 50 sf.gridpoints.data[1, 1] = 50 sf.interpolation_coefficients[x].data[1, 0] = 2.0 sf.interpolation_coefficients[x].data[1, 1] = 2.0 sf.interpolation_coefficients[y].data[1, 0] = 2.0 sf.interpolation_coefficients[y].data[1, 1] = 2.0 op = Operator(sf.interpolate(m)) sf.manual_scatter() args = op.arguments(time_m=0, time_M=9) print("rank %d: %s" % (grid.distributor.myrank, str(args))) op.apply(time_m=0, time_M=0) sf.manual_gather() for i in range(grid.distributor.nprocs): print("==== from rank %d" % i) if i == grid.distributor.myrank: print(repr(sf.data)) grid.distributor.comm.Barrier() if grid.distributor.myrank == 0: assert sf.data[0, 0] == -3.0 # 1 * (1 * 1) * 1 + (-1) * (2 * 2) * 1
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)