def GradientOperator(model, geometry, space_order=4, save=True, kernel='OT2', **kwargs): """ Construct a gradient operator in an acoustic media. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. space_order : int, optional Space discretization order. save : int or Buffer, optional Option to store the entire (unrolled) wavefield. kernel : str, optional Type of discretization, centered or shifted. """ m, damp = model.m, model.damp # Gradient symbol and wavefield symbols grad = Function(name='grad', grid=model.grid) u = TimeFunction(name='u', grid=model.grid, save=geometry.nt if save else None, time_order=2, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, save=None, time_order=2, space_order=space_order) rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) s = model.grid.stepping_dim.spacing eqn = iso_stencil(v, m, s, damp, kernel, forward=False) if kernel == 'OT2': gradient_update = Inc(grad, -u.dt2 * v) elif kernel == 'OT4': gradient_update = Inc( grad, -(u.dt2 + s**2 / 12.0 * u.biharmonic(m**(-2))) * v) # Add expression for receiver injection receivers = rec.inject(field=v.backward, expr=rec * s**2 / m) # Substitute spacing terms to reduce flops return Operator(eqn + receivers + [gradient_update], subs=model.spacing_map, name='Gradient', **kwargs)
def test_symbolic_constant_times_add(self): grid = Grid(shape=(10, 10)) dt = grid.time_dim.spacing u = TimeFunction(name="u", grid=grid, space_order=4, time_order=2) f = Function(name='f', grid=grid) eq = Eq(u.forward, u.laplace + dt**0.2 * u.biharmonic(1 / f)) leq = collect_derivatives.func([eq])[0] assert len(eq.rhs.args) == 3 assert len(leq.rhs.args) == 2 assert all(isinstance(i, Derivative) for i in leq.rhs.args)