示例#1
0
def src_rec(p, model, geometry, **kwargs):
    """
    Forward case: Source injection and receiver interpolation
    Adjoint case: Receiver injection and source interpolation
    """
    dt = model.grid.time_dim.spacing
    m = model.m
    # Source symbol with input wavelet
    src = PointSource(name="src", grid=model.grid, time_range=geometry.time_axis,
                      npoint=geometry.nsrc)
    rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    forward = kwargs.get('forward', True)
    time_order = p.time_order

    if forward:
        # The source injection term
        if(time_order == 1):
            src_term = src.inject(field=p.forward, expr=src * dt)
        else:
            src_term = src.inject(field=p.forward, expr=src * dt**2 / m)
        # Create interpolation expression for receivers
        rec_term = rec.interpolate(expr=p)
    else:
        # Construct expression to inject receiver values
        if(time_order == 1):
            rec_term = rec.inject(field=p.backward, expr=rec * dt)
        else:
            rec_term = rec.inject(field=p.backward, expr=rec * dt**2 / m)
        # Create interpolation expression for the adjoint-source
        src_term = src.interpolate(expr=p)

    return src_term + rec_term
示例#2
0
def JacobianOperator(model, geometry, space_order=4,
                     **kwargs):
    """
    Construct a Linearized Born operator in a TTI 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.
    kernel : str, optional
        Type of discretization, centered or staggered.
    """
    dt = model.grid.stepping_dim.spacing
    m = model.m
    time_order = 2

    # Create source and receiver symbols
    src = Receiver(name='src', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nsrc)

    rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    # Create wavefields and a dm field
    u0 = TimeFunction(name='u0', grid=model.grid, save=None, time_order=time_order,
                      space_order=space_order)
    v0 = TimeFunction(name='v0', grid=model.grid, save=None, time_order=time_order,
                      space_order=space_order)
    du = TimeFunction(name="du", grid=model.grid, save=None,
                      time_order=2, space_order=space_order)
    dv = TimeFunction(name="dv", grid=model.grid, save=None,
                      time_order=2, space_order=space_order)
    dm = Function(name="dm", grid=model.grid, space_order=0)

    # FD kernels of the PDE
    FD_kernel = kernels[('centered', len(model.shape))]
    eqn1 = FD_kernel(model, u0, v0, space_order)

    # Linearized source and stencil
    lin_usrc = -dm * u0.dt2
    lin_vsrc = -dm * v0.dt2

    eqn2 = FD_kernel(model, du, dv, space_order, qu=lin_usrc, qv=lin_vsrc)

    # Construct expression to inject source values, injecting at u0(t+dt)/v0(t+dt)
    src_term = src.inject(field=u0.forward, expr=src * dt**2 / m)
    src_term += src.inject(field=v0.forward, expr=src * dt**2 / m)

    # Create interpolation expression for receivers, extracting at du(t)+dv(t)
    rec_term = rec.interpolate(expr=du + dv)

    # Substitute spacing terms to reduce flops
    return Operator(eqn1 + src_term + eqn2 + rec_term, subs=model.spacing_map,
                    name='BornTTI', **kwargs)
示例#3
0
def JacobianAdjOperator(model, geometry, space_order=4,
                        save=True, **kwargs):
    """
    Construct a linearized JacobianAdjoint modeling Operator in a TTI 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.
    """
    dt = model.grid.stepping_dim.spacing
    m = model.m
    time_order = 2

    # Gradient symbol and wavefield symbols
    u0 = TimeFunction(name='u0', grid=model.grid, save=geometry.nt if save
                      else None, time_order=time_order, space_order=space_order)
    v0 = TimeFunction(name='v0', grid=model.grid, save=geometry.nt if save
                      else None, time_order=time_order, space_order=space_order)

    du = TimeFunction(name="du", grid=model.grid, save=None,
                      time_order=time_order, space_order=space_order)
    dv = TimeFunction(name="dv", grid=model.grid, save=None,
                      time_order=time_order, space_order=space_order)

    dm = Function(name="dm", grid=model.grid)

    rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    # FD kernels of the PDE
    FD_kernel = kernels[('centered', len(model.shape))]
    eqn = FD_kernel(model, du, dv, space_order, forward=False)

    dm_update = Inc(dm, - (u0 * du.dt2 + v0 * dv.dt2))

    # Add expression for receiver injection
    rec_term = rec.inject(field=du.backward, expr=rec * dt**2 / m)
    rec_term += rec.inject(field=dv.backward, expr=rec * dt**2 / m)

    # Substitute spacing terms to reduce flops
    return Operator(eqn + rec_term + [dm_update], subs=model.spacing_map,
                    name='GradientTTI', **kwargs)
示例#4
0
def AdjointOperator(model, source, receiver, space_order=4,
                    kernel='OT2', **kwargs):
    """
    Constructor method for the adjoint modelling operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    m, damp = model.m, model.damp

    v = TimeFunction(name='v', grid=model.grid, save=None,
                     time_order=2, space_order=space_order)
    srca = PointSource(name='srca', grid=model.grid, time_range=source.time_range,
                       npoint=source.npoint)
    rec = Receiver(name='rec', grid=model.grid, time_range=receiver.time_range,
                   npoint=receiver.npoint)

    s = model.grid.stepping_dim.spacing
    eqn = iso_stencil(v, m, s, damp, kernel, forward=False)

    # Construct expression to inject receiver values
    receivers = rec.inject(field=v.backward, expr=rec * s**2 / m,
                           offset=model.nbpml)

    # Create interpolation expression for the adjoint-source
    source_a = srca.interpolate(expr=v, offset=model.nbpml)

    # Substitute spacing terms to reduce flops
    return Operator(eqn + receivers + source_a, subs=model.spacing_map,
                    name='Adjoint', **kwargs)
示例#5
0
def GradientOperator(model, source, receiver, space_order=4, save=True,
                     kernel='OT2', **kwargs):
    """
    Constructor method for the gradient operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    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=source.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=receiver.time_range, npoint=receiver.npoint)

    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.laplace2(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)
示例#6
0
def AdjointOperator(model, geometry, space_order=4,
                    kernel='OT2', **kwargs):
    """
    Constructor method for the adjoint modelling operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    m, damp = model.m, model.damp

    v = TimeFunction(name='v', grid=model.grid, save=None,
                     time_order=2, space_order=space_order)
    srca = PointSource(name='srca', grid=model.grid, time_range=geometry.time_axis,
                       npoint=geometry.nsrc)
    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)

    # Construct expression to inject receiver values
    receivers = rec.inject(field=v.backward, expr=rec * s**2 / m)

    # Create interpolation expression for the adjoint-source
    source_a = srca.interpolate(expr=v)

    # Substitute spacing terms to reduce flops
    return Operator(eqn + receivers + source_a, subs=model.spacing_map,
                    name='Adjoint', **kwargs)
示例#7
0
def GradientOperator(model, geometry, space_order=4, save=True,
                     kernel='OT2', **kwargs):
    """
    Constructor method for the gradient operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    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.laplace2(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)
示例#8
0
def GradientOperator(model,
                     source,
                     receiver,
                     time_order=2,
                     space_order=4,
                     save=True,
                     **kwargs):
    """
    Constructor method for the gradient operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    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=save,
                     time_dim=source.nt if save else None,
                     time_order=2,
                     space_order=space_order)
    v = TimeFunction(name='v',
                     grid=model.grid,
                     save=False,
                     time_order=2,
                     space_order=space_order)
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=receiver.nt,
                   npoint=receiver.npoint)

    # Get computational time-step value
    dt = model.critical_dt * (1.73 if time_order == 4 else 1.0)

    s = model.grid.stepping_dim.spacing
    eqn = iso_stencil(v, time_order, m, s, damp, forward=False)

    if time_order == 2:
        gradient_update = Eq(grad, grad - u.dt2 * v)
    else:
        gradient_update = Eq(
            grad, grad - (u.dt2 + s**2 / 12.0 * u.laplace2(m**(-2))) * v)

    # Add expression for receiver injection
    receivers = rec.inject(field=v.backward,
                           expr=rec * dt**2 / m,
                           offset=model.nbpml)

    # Substitute spacing terms to reduce flops
    return Operator(eqn + receivers + [gradient_update],
                    subs=model.spacing_map,
                    time_axis=Backward,
                    name='Gradient',
                    **kwargs)
示例#9
0
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)
示例#10
0
def BornOperator(model, geometry, space_order=4, kernel='OT2', **kwargs):
    """
    Construct an Linearized Born 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.
    kernel : str, optional
        Type of discretization, centered or shifted.
    """
    m, damp = model.m, model.damp

    # Create source and receiver symbols
    src = Receiver(name='src',
                   grid=model.grid,
                   time_range=geometry.time_axis,
                   npoint=geometry.nsrc)

    rec = Receiver(name='rec',
                   grid=model.grid,
                   time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    # Create wavefields and a dm field
    u = TimeFunction(name="u",
                     grid=model.grid,
                     save=None,
                     time_order=2,
                     space_order=space_order)
    U = TimeFunction(name="U",
                     grid=model.grid,
                     save=None,
                     time_order=2,
                     space_order=space_order)
    dm = Function(name="dm", grid=model.grid, space_order=0)

    s = model.grid.stepping_dim.spacing
    eqn1 = iso_stencil(u, m, s, damp, kernel)
    eqn2 = iso_stencil(U, m, s, damp, kernel, q=-dm * u.dt2)

    # Add source term expression for u
    source = src.inject(field=u.forward, expr=src * s**2 / m)

    # Create receiver interpolation expression from U
    receivers = rec.interpolate(expr=U)

    # Substitute spacing terms to reduce flops
    return Operator(eqn1 + source + eqn2 + receivers,
                    subs=model.spacing_map,
                    name='Born',
                    **kwargs)
示例#11
0
def AdjointOperator(model, geometry, space_order=4, **kwargs):
    """
    Construct an adjoint modelling operator in an tti 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.
    """

    dt = model.grid.time_dim.spacing
    m = model.m
    time_order = 2

    # Create symbols for forward wavefield, source and receivers
    p = TimeFunction(name='p',
                     grid=model.grid,
                     save=None,
                     time_order=time_order,
                     space_order=space_order)
    r = TimeFunction(name='r',
                     grid=model.grid,
                     save=None,
                     time_order=time_order,
                     space_order=space_order)
    srca = PointSource(name='srca',
                       grid=model.grid,
                       time_range=geometry.time_axis,
                       npoint=geometry.nsrc)
    rec = Receiver(name='rec',
                   grid=model.grid,
                   time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    # FD kernels of the PDE
    FD_kernel = kernels[('centered', len(model.shape))]
    stencils = FD_kernel(model, p, r, space_order, forward=False)

    # Construct expression to inject receiver values
    stencils += rec.inject(field=p.backward, expr=rec * dt**2 / m)
    stencils += rec.inject(field=r.backward, expr=rec * dt**2 / m)

    # Create interpolation expression for the adjoint-source
    stencils += srca.interpolate(expr=p + r)

    # Substitute spacing terms to reduce flops
    return Operator(stencils,
                    subs=model.spacing_map,
                    name='AdjointTTI',
                    **kwargs)
示例#12
0
def GradientOperator(model, source, receiver, time_order=2, space_order=4, **kwargs):
    """
    Constructor method for the gradient operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    m, damp = model.m, model.damp

    # Gradient symbol and wavefield symbols
    grad = DenseData(name='grad', shape=model.shape_domain,
                     dtype=model.dtype)
    u = TimeData(name='u', shape=model.shape_domain, save=True,
                 time_dim=source.nt, time_order=time_order,
                 space_order=space_order, dtype=model.dtype)
    v = TimeData(name='v', shape=model.shape_domain, save=False,
                 time_order=time_order, space_order=space_order,
                 dtype=model.dtype)
    rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim,
                   npoint=receiver.npoint)

    if time_order == 2:
        biharmonic = 0
        dt = model.critical_dt
        gradient_update = Eq(grad, grad - u.dt2 * v)
    else:
        biharmonic = v.laplace2(1/m)
        biharmonicu = - u.laplace2(1/(m**2))
        dt = 1.73 * model.critical_dt
        gradient_update = Eq(grad, grad - (u.dt2 - s**2 / 12.0 * biharmonicu) * v)

    # Derive stencil from symbolic equation
    stencil = 1.0 / (2.0 * m + s * damp) * \
        (4.0 * m * v + (s * damp - 2.0 * m) *
         v.forward + 2.0 * s ** 2 * (v.laplace + s**2 / 12.0 * biharmonic))
    eqn = Eq(v.backward, stencil)

    # Add expression for receiver injection
    ti = v.indices[0]
    receivers = rec.inject(field=v, u_t=ti - 1, offset=model.nbpml,
                           expr=rec * dt * dt / m, p_t=time)

    return Operator([eqn] + [gradient_update] + receivers,
                    subs={s: dt, h: model.get_spacing()},
                    time_axis=Backward, name='Gradient', **kwargs)
示例#13
0
def AdjointOperator(model, geometry, space_order=4, kernel='OT2', **kwargs):
    """
    Construct an adjoint modelling 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.
    kernel : str, optional
        Type of discretization, centered or shifted.
    """
    m, damp = model.m, model.damp

    v = TimeFunction(name='v',
                     grid=model.grid,
                     save=None,
                     time_order=2,
                     space_order=space_order)
    srca = PointSource(name='srca',
                       grid=model.grid,
                       time_range=geometry.time_axis,
                       npoint=geometry.nsrc)
    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)

    # Construct expression to inject receiver values
    receivers = rec.inject(field=v.backward, expr=rec * s**2 / m)

    # Create interpolation expression for the adjoint-source
    source_a = srca.interpolate(expr=v)

    # Substitute spacing terms to reduce flops
    return Operator(eqn + receivers + source_a,
                    subs=model.spacing_map,
                    name='Adjoint',
                    **kwargs)
示例#14
0
def AdjointOperator(model, source, receiver, time_order=2, space_order=4, **kwargs):
    """
    Constructor method for the adjoint modelling operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    m, damp = model.m, model.damp

    v = TimeData(name='v', shape=model.shape_domain, save=False,
                 time_order=time_order, space_order=space_order,
                 dtype=model.dtype)
    srca = PointSource(name='srca', ntime=source.nt, ndim=source.ndim,
                       npoint=source.npoint)
    rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim,
                   npoint=receiver.npoint)

    if time_order == 2:
        biharmonic = 0
        dt = model.critical_dt
    else:
        biharmonic = v.laplace2(1/m)
        dt = 1.73 * model.critical_dt

    # Derive both stencils from symbolic equation
    stencil = 1 / (2 * m + s * damp) * (
        4 * m * v + (s * damp - 2 * m) * v.forward +
        2 * s**2 * (v.laplace + s**2 / 12 * biharmonic))
    eqn = Eq(v.backward, stencil)

    # Construct expression to inject receiver values
    ti = v.indices[0]
    receivers = rec.inject(field=v, u_t=ti - 1, offset=model.nbpml,
                           expr=rec * dt**2 / m, p_t=time)

    # Create interpolation expression for the adjoint-source
    source_a = srca.interpolate(expr=v, u_t=ti, offset=model.nbpml)

    return Operator([eqn] + receivers + source_a,
                    subs={s: dt, h: model.get_spacing()},
                    time_axis=Backward, name='Adjoint', **kwargs)
示例#15
0
def BornOperator(model, geometry, space_order=4,
                 kernel='OT2', **kwargs):
    """
    Constructor method for the Linearized Born operator in an acoustic media

    :param model: :class:`Model` object containing the physical parameters
    :param source: :class:`PointData` object containing the source geometry
    :param receiver: :class:`PointData` object containing the acquisition geometry
    :param time_order: Time discretization order
    :param space_order: Space discretization order
    """
    m, damp = model.m, model.damp

    # Create source and receiver symbols
    src = Receiver(name='src', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nsrc)

    rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis,
                   npoint=geometry.nrec)

    # Create wavefields and a dm field
    u = TimeFunction(name="u", grid=model.grid, save=None,
                     time_order=2, space_order=space_order)
    U = TimeFunction(name="U", grid=model.grid, save=None,
                     time_order=2, space_order=space_order)
    dm = Function(name="dm", grid=model.grid, space_order=0)

    s = model.grid.stepping_dim.spacing
    eqn1 = iso_stencil(u, m, s, damp, kernel)
    eqn2 = iso_stencil(U, m, s, damp, kernel, q=-dm*u.dt2)

    # Add source term expression for u
    source = src.inject(field=u.forward, expr=src * s**2 / m)

    # Create receiver interpolation expression from U
    receivers = rec.interpolate(expr=U)

    # Substitute spacing terms to reduce flops
    return Operator(eqn1 + source + eqn2 + receivers, subs=model.spacing_map,
                    name='Born', **kwargs)
示例#16
0
def subsampled_gradient(factor=1, tn=2000.):
    t0 = 0.  # Simulation starts a t=0

    shape = (100, 100)
    origin = (0., 0.)

    spacing = (15., 15.)

    space_order = 4

    vp = np.empty(shape, dtype=np.float64)
    vp[:, :51] = 1.5
    vp[:, 51:] = 2.5

    model = Model(vp=vp, origin=origin, shape=shape, spacing=spacing,
                  space_order=space_order, nbl=10)

    dt = model.critical_dt  # Time step from model grid spacing
    time_range = TimeAxis(start=t0, stop=tn, step=dt)
    nt = time_range.num  # number of time steps

    f0 = 0.010  # Source peak frequency is 10Hz (0.010 kHz)
    src = RickerSource(
        name='src',
        grid=model.grid,
        f0=f0,
        time_range=time_range)

    src.coordinates.data[0, :] = np.array(model.domain_size) * .5
    src.coordinates.data[0, -1] = 20.  # Depth is 20m

    rec = Receiver(
        name='rec',
        grid=model.grid,
        npoint=101,
        time_range=time_range)  # new
    rec.coordinates.data[:, 0] = np.linspace(0, model.domain_size[0], num=101)
    rec.coordinates.data[:, 1] = 20.  # Depth is 20m

    save_elements = (nt + factor - 1) // factor

    print(save_elements)

    time_subsampled = ConditionalDimension(
        't_sub', parent=model.grid.time_dim, factor=factor)
    usave = TimeFunction(name='usave', grid=model.grid, time_order=2,
                         space_order=space_order, save=save_elements,
                         time_dim=time_subsampled)

    u = TimeFunction(name="u", grid=model.grid, time_order=2,
                     space_order=space_order)
    pde = model.m * u.dt2 - u.laplace + model.damp * u.dt
    stencil = Eq(u.forward, solve(pde, u.forward))
    src_term = src.inject(
        field=u.forward,
        expr=src * dt**2 / model.m,
        offset=model.nbl)
    rec_term = rec.interpolate(expr=u, offset=model.nbl)

    fwd_op = Operator([stencil] + src_term + [Eq(usave, u)] + rec_term,
                      subs=model.spacing_map)  # operator with snapshots
    v = TimeFunction(name='v', grid=model.grid, save=None,
                     time_order=2, space_order=space_order)
    grad = Function(name='grad', grid=model.grid)

    rev_pde = model.m * v.dt2 - v.laplace + model.damp * v.dt.T
    rev_stencil = Eq(v.backward, solve(rev_pde, v.backward))
    gradient_update = Inc(grad, - usave.dt2 * v)

    s = model.grid.stepping_dim.spacing

    receivers = rec.inject(field=v.backward, expr=rec*s**2/model.m)
    rev_op = Operator([rev_stencil] + receivers + [gradient_update],
                      subs=model.spacing_map)

    fwd_op(time=nt - 2, dt=model.critical_dt)

    rev_op(dt=model.critical_dt, time=nt-16)

    return grad.data
示例#17
0
def fwi_gradient(vp_in):
    # AUTO
    grad = Function(name="grad", grid=model.grid)
    residual = Receiver(name='rec',
                        grid=model.grid,
                        time_range=geometry.time_axis,
                        coordinates=geometry.rec_positions)
    objective = 0.
    u0 = TimeFunction(name='u',
                      grid=model.grid,
                      time_order=2,
                      space_order=4,
                      save=geometry.nt)

    # MANUAL
    grad_manual = Function(name="grad", grid=model.grid)
    residual_man = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates)
    objective_manual = 0.
    u0_man = TimeFunction(name='u',
                          grid=model.grid,
                          time_order=2,
                          space_order=4,
                          save=nt)
    for i in range(9):
        # AUTO
        clear_cache()
        geometry.src_positions[0, :] = source_locations[i, :]
        true_d, _, _ = solver.forward(vp=model.vp)
        u0.data.fill(0.)
        smooth_d, _, _ = solver.forward(vp=vp_in, save=True, u=u0)
        residual.data[:] = smooth_d.data[:] - true_d.data[:]
        objective += .5 * np.linalg.norm(residual.data.flatten())**2
        solver.gradient(rec=residual, u=u0, vp=vp_in, grad=grad)

        # MANUAL
        # source
        src_true = RickerSource(name='src',
                                grid=model.grid,
                                time_range=time_axis,
                                coordinates=source_locations[i, :],
                                npoint=1,
                                f0=f0)
        src_term = src_true.inject(
            field=u.forward,
            expr=src_true * model.grid.stepping_dim.spacing**2 / model.m)

        # receiver
        rec_true = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates,
                            npoint=nreceivers)
        rec_term = rec_true.interpolate(expr=u)

        # operator
        op_fwd = Operator(eqn + src_term + rec_term,
                          subs=model.spacing_map,
                          name='Forward')
        op_fwd.apply(src=src_true,
                     rec=rec_true,
                     u=u0_man,
                     vp=model.vp,
                     dt=model.critical_dt)

        u0_man.data.fill(0.)
        rec_smooth = Receiver(name='rec',
                              grid=model.grid,
                              time_range=time_axis,
                              coordinates=rec_coordinates,
                              npoint=nreceivers)
        op_fwd.apply(src=src_true,
                     rec=rec_smooth,
                     u=u0_man,
                     vp=vp_in,
                     dt=model.critical_dt)

        # back-receiver
        rec_back = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates,
                            npoint=nreceivers)
        rec_back_term = rec_back.inject(
            field=v.backward,
            expr=rec_back * model.grid.stepping_dim.spacing**2 / model.m)

        # gradient
        gradient_update = Inc(grad_manual, -u.dt2 * v)
        op_grad = Operator(eqn_back + rec_back_term + [gradient_update],
                           subs=model.spacing_map,
                           name='Gradient')
        residual_man.data[:] = rec_smooth.data[:] - rec_true.data[:]
        objective_manual += .5 * np.linalg.norm(residual_man.data.flatten())**2
        op_grad.apply(rec=residual_man,
                      u=u0_man,
                      vp=vp_in,
                      dt=model.critical_dt,
                      grad=grad_manual)

        # sanity-check -> expect for 0!
        # plot_shotrecord(true_d.data[:] - rec_true.data[:], model, t0, tn)
        # plot_shotrecord(smooth_d.data[:] - rec_smooth.data[:], model, t0, tn)
    return objective, -grad.data, objective_manual, -grad_manual.data