def test_iteration_parallelism_2d(self, exprs, atomic, parallel): """Tests detection of PARALLEL_* properties.""" grid = Grid(shape=(10, 10)) time = grid.time_dim # noqa t = grid.stepping_dim # noqa x, y = grid.dimensions # noqa p = Dimension(name='p') d = Dimension(name='d') rx = Dimension(name='rx') ry = Dimension(name='ry') u = Function(name='u', grid=grid) # noqa v = TimeFunction(name='v', grid=grid, save=None) # noqa cx = Function(name='coeff_x', dimensions=(p, rx), shape=(1, 2)) # noqa cy = Function(name='coeff_y', dimensions=(p, ry), shape=(1, 2)) # noqa gp = Function(name='gridpoints', dimensions=(p, d), shape=(1, 2)) # noqa src = Function(name='src', dimensions=(p,), shape=(1,)) # noqa rcv = Function(name='rcv', dimensions=(time, p), shape=(100, 1), space_order=0) # noqa # List comprehension would need explicit locals/globals mappings to eval for i, e in enumerate(list(exprs)): exprs[i] = eval(e) op = Operator(exprs, opt='openmp') iters = FindNodes(Iteration).visit(op) assert all(i.is_ParallelAtomic for i in iters if i.dim.name in atomic) assert all(not i.is_ParallelAtomic for i in iters if i.dim.name not in atomic) assert all(i.is_Parallel for i in iters if i.dim.name in parallel) assert all(not i.is_Parallel for i in iters if i.dim.name not in parallel)
def test_collapsing_v2(self): """ MFE from issue #1478. """ n = 8 m = 8 nx, ny, nchi, ncho = 12, 12, 1, 1 x, y = SpaceDimension("x"), SpaceDimension("y") ci, co = Dimension("ci"), Dimension("co") i, j = Dimension("i"), Dimension("j") grid = Grid((nx, ny), dtype=np.float32, dimensions=(x, y)) X = Function(name="xin", dimensions=(ci, x, y), shape=(nchi, nx, ny), grid=grid, space_order=n//2) dy = Function(name="dy", dimensions=(co, x, y), shape=(ncho, nx, ny), grid=grid, space_order=n//2) dW = Function(name="dW", dimensions=(co, ci, i, j), shape=(ncho, nchi, n, m), grid=grid) eq = [Eq(dW[co, ci, i, j], dW[co, ci, i, j] + dy[co, x, y]*X[ci, x+i-n//2, y+j-m//2]) for i in range(n) for j in range(m)] op = Operator(eq, opt=('advanced', {'openmp': True})) iterations = FindNodes(Iteration).visit(op) assert len(iterations) == 4 assert iterations[0].ncollapsed == 1 assert iterations[1].is_Vectorized assert iterations[2].is_Sequential assert iterations[3].is_Sequential
def grad(nx, ny, nchi, ncho, n, m, xdat, dydat): # Image size dt = np.float32 x, y, ci, co = (SpaceDimension("x"), SpaceDimension("y"), Dimension("ci"), Dimension("co")) grid = Grid((nx, ny), dtype=dt, dimensions=(x, y)) # Image X = Function(name="xin", dimensions=(ci, x, y), shape=(nchi, nx, ny), grid=grid, space_order=n//2) # Output dy = Function(name="dy", dimensions=(co, x, y), shape=(ncho, nx, ny), grid=grid, space_order=n//2) # Weights i, j = Dimension("i"), Dimension("j") dW = Function(name="dW", dimensions=(co, ci, i, j), shape=(ncho, nchi, n, m), grid=grid) # Gradient grad_eq = Inc(dW[co, ci, i, j], dy[co, x, y]*X[ci, x+i-n//2, y+j-m//2]) op = Operator(grad_eq) op.cfunction X.data[:] = xdat[:] dy.data[:] = dydat[:] return op
def test_indexed_w_indirections(self): """Test point-wise arithmetic with indirectly indexed :class:`Function`s.""" grid = Grid(shape=(10, 10)) x, y = grid.dimensions p_poke = Dimension('p_src') d = Dimension('d') npoke = 1 u = Function(name='u', grid=grid, space_order=0) coordinates = Function(name='coordinates', dimensions=(p_poke, d), shape=(npoke, grid.dim), space_order=0, dtype=np.int32) coordinates.data[0, 0] = 4 coordinates.data[0, 1] = 3 poke_eq = Eq(u.indexed[coordinates.indexed[p_poke, 0], coordinates.indexed[p_poke, 1]], 1.0) op = Operator(poke_eq) op.apply() ix, iy = np.where(u.data == 1.) assert len(ix) == len(iy) == 1 assert ix[0] == 4 and iy[0] == 3 assert np.all(u.data[0:3] == 0.) and np.all(u.data[5:] == 0.) assert np.all(u.data[:, 0:3] == 0.) and np.all(u.data[:, 5:] == 0.)
def test_multi_sets_eq(self): """ Check functionality for when multiple subdomain sets are present, each with multiple equations. """ Nx = 10 Ny = Nx n_domains = 2 n = Dimension(name='n') m = Dimension(name='m') class MySubdomains1(SubDomainSet): name = 'mydomains1' implicit_dimension = n class MySubdomains2(SubDomainSet): name = 'mydomains2' implicit_dimension = m bounds_xm = np.array([1, Nx / 2 + 1], dtype=np.int32) bounds_xM = np.array([Nx / 2 + 1, 1], dtype=np.int32) bounds_ym = int(1) bounds_yM = int(Ny / 2 + 1) bounds1 = (bounds_xm, bounds_xM, bounds_ym, bounds_yM) bounds_xm = np.array([1, Nx / 2 + 1], dtype=np.int32) bounds_xM = np.array([Nx / 2 + 1, 1], dtype=np.int32) bounds_ym = int(Ny / 2 + 1) bounds_yM = int(1) bounds2 = (bounds_xm, bounds_xM, bounds_ym, bounds_yM) my_sd1 = MySubdomains1(N=n_domains, bounds=bounds1) my_sd2 = MySubdomains2(N=n_domains, bounds=bounds2) grid = Grid(extent=(Nx, Ny), shape=(Nx, Ny), subdomains=(my_sd1, my_sd2)) f = Function(name='f', grid=grid, dtype=np.int32) g = Function(name='g', grid=grid, dtype=np.int32) eq1 = Eq(f, f + 2, subdomain=grid.subdomains['mydomains1']) eq2 = Eq(g, g + 2, subdomain=grid.subdomains['mydomains2']) eq3 = Eq(f, f - 1, subdomain=grid.subdomains['mydomains1']) eq4 = Eq(g, g + 1, subdomain=grid.subdomains['mydomains2']) op = Operator([eq1, eq2, eq3, eq4]) op.apply() expected = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 1, 1, 1, 0, 0, 3, 3, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.int32) assert ((np.array(f.data[:] + g.data[:]) == expected).all())
def test_conditional_dimension(self): """Test that different ConditionalDimensions have different hash value.""" d0 = Dimension(name='d') s0 = Scalar(name='s') d1 = Dimension(name='d', spacing=s0) cd0 = ConditionalDimension(name='cd', parent=d0, factor=4) cd1 = ConditionalDimension(name='cd', parent=d0, factor=5) assert cd0 is not cd1 assert hash(cd0) != hash(cd1) cd2 = ConditionalDimension(name='cd', parent=d0, factor=4, indirect=True) assert hash(cd0) != hash(cd2) cd3 = ConditionalDimension(name='cd', parent=d1, factor=4) assert hash(cd0) != hash(cd3) s1 = Scalar(name='s', dtype=np.int32) cd4 = ConditionalDimension(name='cd', parent=d0, factor=4, condition=s0 > 3) assert hash(cd0) != hash(cd4) cd5 = ConditionalDimension(name='cd', parent=d0, factor=4, condition=s1 > 3) assert hash(cd0) != hash(cd5) assert hash(cd4) != hash(cd5)
def test_partial_offloading(self): """ Check that :class:`Function` objects not using any :class:`SpaceDimension` are computed in Devito-land, rather than via YASK. """ shape = (4, 4, 4) grid = Grid(shape=shape) dx = Dimension(name='dx') dy = Dimension(name='dy') dz = Dimension(name='dz') x, y, z = grid.dimensions u = TimeFunction(name='yu4D', grid=grid, space_order=0) f = Function(name='f', dimensions=(dx, dy, dz), shape=shape) u.data_with_halo[:] = 0. f.data[:] = 0. eqns = [Eq(u.forward, u + 1.), Eq(f, u[1, dx, dy, dz] + 1.)] op = Operator(eqns) op(time=0) assert np.all(u.data[0] == 0.) assert np.all(u.data[1] == 1.) assert np.all(f.data == 2.)
def custom_points(grid, ranges, npoints, name='points'): """Create a set of sparse points from a set of coordinate ranges for each spatial dimension. """ scale = Dimension(name="scale") dim = Dimension(name="dim") points = SparseFunction(name=name, grid=grid, dimensions=(scale, dim), shape=(3, npoints), npoint=npoints) for i, r in enumerate(ranges): points.coordinates.data[:, i] = np.linspace(r[0], r[1], npoints) return points
def conv(nx, ny, nchi, ncho, n, m): # Image size dt = np.float32 x, y, ci, co = (SpaceDimension("x"), SpaceDimension("y"), Dimension("ci"), Dimension("co")) grid = Grid((nchi, ncho, nx, ny), dtype=dt, dimensions=(ci, co, x, y)) # Image im_in = Function(name="imi", dimensions=(ci, x, y), shape=(nchi, nx, ny), grid=grid, space_order=n // 2) # Output im_out = Function(name="imo", dimensions=(co, x, y), shape=(ncho, nx, ny), grid=grid, space_order=n // 2) # Weights i, j = Dimension("i"), Dimension("j") W = Function(name="W", dimensions=(co, ci, i, j), shape=(ncho, nchi, n, m), grid=grid) # Popuate weights with deterministic values for i in range(ncho): for j in range(nchi): W.data[i, j, :, :] = np.linspace(i + j, i + j + (n * m), n * m).reshape(n, m) # Convlution conv = [ Eq( im_out, im_out + sum([ W[co, ci, i2, i1] * im_in[ci, x + i1 - n // 2, y + i2 - m // 2] for i1 in range(n) for i2 in range(m) ])) ] op = Operator(conv) op.cfunction # Initialize the input/output input_data = np.linspace(-1, 1, nx * ny * nchi).reshape(nchi, nx, ny) im_in.data[:] = input_data.astype(np.float32) im_out.data return op
def test_sub_dimension(self): """Test that different SubDimensions have different hash value.""" d0 = Dimension(name='d') d1 = Dimension(name='d', spacing=Scalar(name='s')) di0 = SubDimension.middle('di', d0, 1, 1) di1 = SubDimension.middle('di', d1, 1, 1) assert hash(di0) != hash(d0) assert hash(di0) != hash(di1) dl0 = SubDimension.left('dl', d0, 2) assert hash(dl0) != hash(di0)
def test_symbols_args_vs_kwargs(self): """ Unlike Functions, Symbols don't require the use of a kwarg to specify the name. This test basically checks that `Symbol('s') is Symbol(name='s')`, i.e. that we don't make any silly mistakes when it gets to compute the cache key. """ v_arg = Symbol('v') v_kwarg = Symbol(name='v') assert v_arg is v_kwarg d_arg = Dimension('d100') d_kwarg = Dimension(name='d100') assert d_arg is d_kwarg
def test_dimension(self): """Test that different Dimensions have different hash value.""" d0 = Dimension(name='d') s0 = Scalar(name='s') d1 = Dimension(name='d', spacing=s0) assert hash(d0) != hash(d1) s1 = Scalar(name='s', dtype=np.int32) d2 = Dimension(name='d', spacing=s1) assert hash(d1) != hash(d2) d3 = Dimension(name='d', spacing=Constant(name='s1')) assert hash(d3) != hash(d0) assert hash(d3) != hash(d1)
def __new__(cls, name, grid, ntime=None, npoint=None, data=None, coordinates=None, **kwargs): p_dim = kwargs.get('dimension', Dimension(name='p_%s' % name)) npoint = npoint or coordinates.shape[0] if data is None: if ntime is None: error('Either data or ntime are required to' 'initialise source/receiver objects') else: ntime = ntime or data.shape[0] # Create the underlying SparseTimeFunction object obj = SparseTimeFunction.__new__(cls, name=name, grid=grid, dimensions=[grid.time_dim, p_dim], npoint=npoint, nt=ntime, coordinates=coordinates, **kwargs) # If provided, copy initial data into the allocated buffer if data is not None: obj.data[:] = data return obj
def test_override_composite_data(self): i, j = dimify('i j') grid = Grid(shape=(10, 10), dimensions=(i, j)) original_coords = (1., 1.) new_coords = (2., 2.) p_dim = Dimension('p_src') u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2) src1 = SparseFunction(name='src1', grid=grid, dimensions=[time, p_dim], npoint=1, nt=10, coordinates=original_coords) src2 = SparseFunction(name='src1', grid=grid, dimensions=[time, p_dim], npoint=1, nt=10, coordinates=new_coords) op = Operator(src1.inject(u, src1)) # Move the source from the location where the setup put it so we can test # whether the override picks up the original coordinates or the changed ones # Operator.arguments() returns a tuple of (data, dimension_sizes) args = op.arguments(src1=src2)[0] arg_name = src1.name + "_coords" assert (np.array_equal(args[arg_name], np.asarray((new_coords, ))))
def test_reinsertion_after_deletion(self, operate_on_empty_cache): """ Test that dead weakrefs in the symbol cache do not cause any issues when objects with the same key/hash are reinserted. """ d = Dimension(name='d') del d # `d` has just been deleted, but a weakref pointing to a dead object is still # in the symbol cache at this point; `h_d` is still in the cache too, dead too assert len(_SymbolCache) == 2 assert all(i() is None for i in _SymbolCache.values()) d = Dimension(name='d') # noqa assert len(_SymbolCache) == 2 assert all(i() is not None for i in _SymbolCache.values())
def test_default_dimension(self): d = Dimension(name='d') dd0 = DefaultDimension(name='d') assert d is not dd0 dd1 = DefaultDimension(name='d') assert dd0 is not dd1
def test_equations_mixed_densedata_timedata(self, shape, dimensions): """ Test that equations using a mixture of DenseData and TimeData objects are embedded within the same time loop. """ a = TimeData(name='a', shape=shape, time_order=2, dimensions=dimensions, space_order=2, time_dim=6, save=False) p_aux = Dimension(name='p_aux', size=10) b = DenseData(name='b', shape=shape + (10,), dimensions=dimensions + (p_aux,), space_order=2) b.data[:] = 1.0 b2 = DenseData(name='b2', shape=(10,) + shape, dimensions=(p_aux,) + dimensions, space_order=2) b2.data[:] = 1.0 eqns = [Eq(a.forward, a.laplace + 1.), Eq(b, time*b*a + b)] eqns2 = [Eq(a.forward, a.laplace + 1.), Eq(b2, time*b2*a + b2)] subs = {x.spacing: 2.5, y.spacing: 1.5, z.spacing: 2.0} op = Operator(eqns, subs=subs, dle='noop') trees = retrieve_iteration_tree(op) assert len(trees) == 2 assert all(trees[0][i] is trees[1][i] for i in range(3)) op2 = Operator(eqns2, subs=subs, dle='noop') trees = retrieve_iteration_tree(op2) assert len(trees) == 2 assert all(trees[0][i] is trees[1][i] for i in range(3)) # Verify both operators produce the same result op() op2() assert(np.allclose(b2.data[2, ...].reshape(-1) - b.data[..., 2].reshape(-1), 0.))
def adjoint_y_run(self, y, src_coords, rcv_coords, weight_fun_pars=None, save=False): v = wavefield(self.model, self.space_order, save=save, nt=y.shape[0], fw=False) kwargs = wf_kwargs(v) rcv = Receiver(name="rcv", grid=self.model.grid, ntime=y.shape[0], coordinates=src_coords) src = PointSource(name="src", grid=self.model.grid, ntime=y.shape[0], coordinates=rcv_coords) src.data[:, :] = y[:, :] adj = self.op_adj_y(weight_fun_pars=weight_fun_pars, save=save) i = Dimension(name="i", ) norm_v = Function(name="nvy2", shape=(1, ), dimensions=(i, ), grid=self.model.grid) adj(src=src, rcv=rcv, nvy2=norm_v, **kwargs) return norm_v.data[0], rcv.data, v
def forward_freq_modeling(model, src_coords, wavelet, rec_coords, freq, space_order=8, dt=None, factor=None, free_surface=False): # Forward modeling with on-the-fly DFT of forward wavefields clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp freq_dim = Dimension(name='freq_dim') time = model.grid.time_dim if factor is None: factor = int(1 / (dt*4*np.max(freq))) tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) if factor==1: tsave = time else: tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) print("DFT subsampling factor: ", factor) # Create wavefields nfreq = freq.shape[0] u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) f = Function(name='f', dimensions=(freq_dim,), shape=(nfreq,)) f.data[:] = freq[:] ufr = Function(name='ufr', dimensions=(freq_dim,) + u.indices[1:], shape=(nfreq,) + model.shape_domain) ufi = Function(name='ufi', dimensions=(freq_dim,) + u.indices[1:], shape=(nfreq,) + model.shape_domain) ulaplace, rho = acoustic_laplacian(u, rho) # Set up PDE and rearrange stencil = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace) expression = [Eq(u.forward, stencil)] expression += [Eq(ufr, ufr + factor*u*cos(2*np.pi*f*tsave*factor*dt))] expression += [Eq(ufi, ufi - factor*u*sin(2*np.pi*f*tsave*factor*dt))] # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, expr=src * dt**2 / m) # Data is sampled at receiver locations rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u) # Create operator and run expression += src_term + rec_term # Free surface if free_surface is True: expression += freesurface(u, space_order//2, model.nbpml) subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced') cf = op.cfunction op() return rec.data, ufr, ufi
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)
def test_implicit_dims(self): """ Test ConditionalDimension as an implicit dimension for an equation. """ # This test makes an Operator that should create a vector of increasing # integers, but stop incrementing when a certain stop value is reached shape = (50, ) stop_value = 20 time = Dimension(name='time') f = TimeFunction(name='f', shape=shape, dimensions=[time]) # The condition to stop incrementing cond = ConditionalDimension(name='cond', parent=time, condition=f[time] < stop_value) eqs = [ Eq(f.forward, f), Eq(f.forward, f.forward + 1, implicit_dims=[cond]) ] op = Operator(eqs) op.apply(time_M=shape[0] - 2) # Make the same calculation in python to assert the result F = np.zeros(shape[0]) for i in range(shape[0]): F[i] = i if i < stop_value else stop_value assert np.all(f.data == F)
def test_staggered_function(self, order): """Test custom function coefficients on a staggered grid""" grid = Grid(shape=(11, ), extent=(10., )) x = grid.dimensions[0] f = Function(name='f', grid=grid, space_order=order, coefficients='symbolic') g = Function(name='g', grid=grid, space_order=order, coefficients='symbolic', staggered=x) f.data[::2] = 1 g.data[::2] = 1 s = Dimension(name='s') ncoeffs = order + 1 wshape = grid.shape + (ncoeffs, ) wdims = grid.dimensions + (s, ) w = Function(name='w', dimensions=wdims, shape=wshape) w.data[:] = 1.0 / grid.spacing[0]**2 coeffs_f = Coefficient(2, f, x, w) coeffs_g = Coefficient(2, g, x, w) eq_f = Eq(f, f.dx2, coefficients=Substitutions(coeffs_f)) eq_g = Eq(g, g.dx2, coefficients=Substitutions(coeffs_g)) Operator([eq_f, eq_g])() assert np.allclose(f.data, g.data, atol=1e-7)
def test_argument_from_index_constant(self): nx, ny = 30, 30 grid = Grid(shape=(nx, ny)) x, y = grid.dimensions arbdim = Dimension('arb') u = TimeFunction(name='u', grid=grid, save=None, time_order=2, space_order=0) snap = Function(name='snap', dimensions=(arbdim, x, y), shape=(5, nx, ny), space_order=0) save_t = Constant(name='save_t', dtype=np.int32) save_slot = Constant(name='save_slot', dtype=np.int32) expr = Eq(snap.subs(arbdim, save_slot), u.subs(grid.stepping_dim, save_t)) op = Operator(expr) u.data[:] = 0.0 snap.data[:] = 0.0 u.data[0, 10, 10] = 1.0 op.apply(save_t=0, save_slot=1) assert snap.data[1, 10, 10] == 1.0
def test_conditional_dimension(self): """ Test that ConditionalDimensions with same name but different attributes do not alias to the same ConditionalDimension. Conversely, if the name and the attributes are the same, they must alias to the same ConditionalDimension. """ i = Dimension(name='i') ci0 = ConditionalDimension(name='ci', parent=i, factor=4) ci1 = ConditionalDimension(name='ci', parent=i, factor=4) assert ci0 is ci1 ci2 = ConditionalDimension(name='ci', parent=i, factor=8) assert ci2 is not ci1 ci3 = ConditionalDimension(name='ci', parent=i, factor=4, indirect=True) assert ci3 is not ci1 s = Scalar(name='s') ci4 = ConditionalDimension(name='ci', parent=i, factor=4, condition=s > 3) assert ci4 is not ci1 ci5 = ConditionalDimension(name='ci', parent=i, factor=4, condition=s > 3) assert ci5 is ci4
def __new__(cls, name, grid, time_range, npoint=None, data=None, coordinates=None, **kwargs): p_dim = kwargs.get('dimension', Dimension(name='p_%s' % name)) time_order = kwargs.get('time_order', 2) npoint = npoint or coordinates.shape[0] # Create the underlying SparseTimeFunction object obj = SparseTimeFunction.__new__(cls, name=name, grid=grid, dimensions=[grid.time_dim, p_dim], npoint=npoint, nt=time_range.num, time_order=time_order, coordinates=coordinates, **kwargs) obj._time_range = time_range._rebuild() # If provided, copy initial data into the allocated buffer if data is not None: obj.data[:] = data return obj
def __new__(cls, **kwargs): name = kwargs.pop('name') grid = kwargs.pop('grid') time_range = kwargs.pop('time_range') time_order = kwargs.pop('time_order', 2) p_dim = kwargs.pop('dimension', Dimension(name='p_%s' % name)) # Either `npoint` or `coordinates` must be provided coordinates = kwargs.pop('coordinates', None) npoint = kwargs.pop('npoint', None) or coordinates.shape[0] # Create the underlying SparseTimeFunction object obj = SparseTimeFunction.__new__(cls, name=name, grid=grid, dimensions=(grid.time_dim, p_dim), npoint=npoint, nt=time_range.num, time_order=time_order, coordinates=coordinates, **kwargs) obj._time_range = time_range._rebuild() # If provided, copy initial data into the allocated buffer data = kwargs.get('data') if data is not None: obj.data[:] = data return obj
def test_function_wo(self): grid = Grid(shape=(3, 3, 3)) i = Dimension(name='i') f = Function(name='f', shape=(1,), dimensions=(i,), grid=grid) u = TimeFunction(name='u', grid=grid) eqns = [Eq(u.forward, u + 1), Eq(f[0], u[0, 0, 0, 0])] op = Operator(eqns, opt='noop') assert len(op.body[1].header) == 2 assert len(op.body[1].footer) == 2 assert op.body[1].header[0].value ==\ ('omp target enter data map(to: u[0:u_vec->size[0]]' '[0:u_vec->size[1]][0:u_vec->size[2]][0:u_vec->size[3]])') assert str(op.body[1].header[1]) == '' assert str(op.body[1].footer[0]) == '' assert op.body[1].footer[1].contents[0].value ==\ ('omp target update from(u[0:u_vec->size[0]]' '[0:u_vec->size[1]][0:u_vec->size[2]][0:u_vec->size[3]])') assert op.body[1].footer[1].contents[1].value ==\ ('omp target exit data map(release: u[0:u_vec->size[0]]' '[0:u_vec->size[1]][0:u_vec->size[2]][0:u_vec->size[3]])')
def test_array(): grid = Grid(shape=(3, 3)) d = Dimension(name='d') a = Array(name='a', dimensions=grid.dimensions, dtype=np.int32, halo=((1, 1), (2, 2)), padding=((2, 2), (2, 2)), space='remote', scope='stack') pkl_a = pickle.dumps(a) new_a = pickle.loads(pkl_a) assert new_a.name == a.name assert new_a.dtype is np.int32 assert new_a.dimensions[0].name == 'x' assert new_a.dimensions[1].name == 'y' assert new_a.halo == ((1, 1), (2, 2)) assert new_a.padding == ((2, 2), (2, 2)) assert new_a.space == 'remote' assert new_a.scope == 'stack' # Now with a pointer array pa = PointerArray(name='pa', dimensions=d, array=a) pkl_pa = pickle.dumps(pa) new_pa = pickle.loads(pkl_pa) assert new_pa.name == pa.name assert new_pa.dim.name == 'd' assert new_pa.array.name == 'a'
def test_override_sparse_data_fix_dim(self): """ Ensure the arguments are derived correctly for an input SparseFunction. The dimensions are forced to be the same in this case to verify the aliasing on the SparseFunction name. """ grid = Grid(shape=(10, 10)) time = grid.time_dim u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2) original_coords = (1., 1.) new_coords = (2., 2.) p_dim = Dimension(name='p_src') src1 = SparseTimeFunction(name='src1', grid=grid, dimensions=[time, p_dim], nt=10, npoint=1, coordinates=original_coords, time_order=2) src2 = SparseTimeFunction(name='src2', grid=grid, dimensions=[time, p_dim], npoint=1, nt=10, coordinates=new_coords, time_order=2) op = Operator(src1.inject(u, src1)) # Move the source from the location where the setup put it so we can test # whether the override picks up the original coordinates or the changed ones args = op.arguments(src1=src2, time=0) arg_name = src1.name + "_coords" assert(np.array_equal(args[arg_name], np.asarray((new_coords,))))
def test_temp_function(): grid = Grid(shape=(3, 3)) d = Dimension(name='d') cf = TempFunction(name='f', dtype=np.float64, dimensions=grid.dimensions, halo=((1, 1), (1, 1))) pkl_cf = pickle.dumps(cf) new_cf = pickle.loads(pkl_cf) assert new_cf.name == cf.name assert new_cf.dtype is np.float64 assert new_cf.halo == ((1, 1), (1, 1)) assert new_cf.ndim == cf.ndim assert new_cf.dim is None pcf = cf._make_pointer(d) pkl_pcf = pickle.dumps(pcf) new_pcf = pickle.loads(pkl_pcf) assert new_pcf.name == pcf.name assert new_pcf.dim.name == 'd' assert new_pcf.ndim == cf.ndim + 1 assert new_pcf.halo == ((0, 0), (1, 1), (1, 1))