Example #1
0
def gy(field, model):
    """
    Rotated first derivative in y

    Parameters
    ----------
    u: TimeFunction or Expr
        TTI field
    model: Model
        Model structure

    Returns
    ----------
    Expr
        du/dy in rotated coordinates
    """
    costheta, sintheta, cosphi, sinphi = angles_to_trig(model)
    dims = field.dimensions[1:model.dim + 1]
    o1 = field.space_order // 2

    Dy = (-sinphi *
          first_derivative(field, dim=dims[0], side=centered, fd_order=o1) +
          cosphi *
          first_derivative(field, dim=dims[1], side=centered, fd_order=o1))

    return Dy
Example #2
0
def gx(field, model):
    """
    Rotated first derivative in x
    Parameters
    ----------
    u: TimeFunction or Expr
        TTI field
    model: Model
        Model structure
    Returns
    ----------
    Expr
        du/dx in rotated coordinates
    """
    costheta, sintheta, cosphi, sinphi = angles_to_trig(model)
    dims = field.dimensions[1:model.dim + 1]
    order1 = field.space_order // 2

    Dx = (costheta * cosphi *
          first_derivative(field, dim=dims[0], side=left, fd_order=order1) -
          sintheta *
          first_derivative(field, dim=dims[-1], side=left, fd_order=order1))

    if len(dims) == 3:
        Dx += costheta * sinphi * first_derivative(
            field, dim=dims[1], side=left, fd_order=order1)
    return Dx
Example #3
0
def gy_T(field, model):
    """
    Rotated first derivative in y

    Parameters
    ----------
    u: TimeFunction or Expr
        TTI field
    model: Model
        Model structure

    Returns
    ----------
    Expr
        du/dy.T in rotated coordinates
    """
    if field == 0:
        return 0

    costheta, sintheta, cosphi, sinphi = angles_to_trig(model)
    dims = field.dimensions[1:model.dim + 1]
    order1 = field.space_order // 2

    Dy = (first_derivative(-sinphi * field,
                           dim=dims[0],
                           matvec=transpose,
                           side=centered,
                           fd_order=order1) +
          first_derivative(cosphi * field,
                           dim=dims[1],
                           matvec=transpose,
                           side=centered,
                           fd_order=order1))

    return Dy
def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, nb=40, isic=False, dt=None, free_surface=False):
    clear_cache()

    # Parameters
    nt = wavelet.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, rho, dm, damp = model.m, model.rho, model.dm, model.damp

    # Create the forward and linearized wavefield
    u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=space_order)
    du = TimeFunction(name="du", grid=model.grid, time_order=2, space_order=space_order)
    if len(model.shape) == 2:
        x,y = u.space_dimensions
    else:
        x,y,z = u.space_dimensions

    # Set up PDEs and rearrange
    ulaplace, rho = acoustic_laplacian(u, rho)
    dulaplace, _ = acoustic_laplacian(du, rho)

    if isic:
        # Sum ((u.dx * d, / rho).dx for x in dimensions)
        # space_order//2  so that u.dx.dx has the same radius as u.laplace
        du_aux = sum([first_derivative(first_derivative(u, dim=d, fd_order=space_order//2) * dm / rho, fd_order=space_order//2, dim=d)
                      for d in u.space_dimensions])
        lin_source = dm /rho * u.dt2 * m - du_aux
    else:
        lin_source = dm / rho * u.dt2

    stencil_u = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace)
    stencil_du = damp * (2.0 * du - damp * du.backward + dt**2 * rho / m * (dulaplace - lin_source))

    expression_u = [Eq(u.forward, stencil_u)]
    expression_du = [Eq(du.forward, stencil_du)]

    # Define source symbol with 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 * rho * dt**2 / m)

    # Define receiver symbol
    rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords)
    rec_term = rec.interpolate(expr=du)

    expression = expression_u + expression_du + src_term + rec_term

    # Free surface
    if free_surface is True:
        expression += freesurface(u, space_order//2, model.nbpml)
        expression += freesurface(du, space_order//2, model.nbpml)

    # Create operator and run
    set_log_level('ERROR')
    subs = model.spacing_map
    subs[u.grid.time_dim.spacing] = dt
    op = Operator(expression, subs=subs, dse='advanced', dle='advanced')
    op()

    return rec.data
def acoustic_laplacian(v, rho):
    if rho is None:
        Lap = v.laplace
        rho = 1
    else:
        if isinstance(rho, Function):
            Lap = sum([first_derivative(first_derivative(v, fd_order=int(v.space_order/2), side=left, dim=d) / rho,
                       fd_order=int(v.space_order/2), dim=d, side=right) for d in v.space_dimensions])
        else:
            Lap = 1 / rho * v.laplace
    return Lap, rho
Example #6
0
def gz_T(field, model):
    """
    Rotated first derivative in z

    Parameters
    ----------
    u: TimeFunction or Expr
        TTI field
    model: Model
        Model structure

    Returns
    ----------
    Expr
        du/dz.T in rotated coordinates
    """
    if field == 0:
        return 0

    costheta, sintheta, cosphi, sinphi = angles_to_trig(model)
    dims = field.dimensions[1:model.dim + 1]
    order1 = field.space_order // 2

    Dz = -(first_derivative(sintheta * cosphi * field,
                            dim=dims[0],
                            side=right,
                            fd_order=order1,
                            matvec=transpose) +
           first_derivative(costheta * field,
                            dim=dims[-1],
                            side=right,
                            fd_order=order1,
                            matvec=transpose))

    if len(dims) == 3:
        Dz += first_derivative(sintheta * sinphi * field,
                               dim=dims[1],
                               side=right,
                               fd_order=order1,
                               matvec=transpose)
    return Dz
Example #7
0
def Gzz2d(field, costheta, sintheta, irho):
    """
    3D rotated second order derivative in the direction z

    Parameters
    ----------
    field: symbolic data whose derivative we are computing
    costheta: cosine of the tilt angle
    sintheta:  sine of the tilt angle
    cosphi: cosine of the azymuth angle
    sinphi: sine of the azymuth angle
    space_order: discretization order

    Returns
    -------
    rotated second order derivative wrt ztranspose
    """
    if sintheta == 0:
        return getattr(field, 'd%s2' % field.grid.dimensions[-1])

    order1 = field.space_order // 2
    x, z = field.grid.dimensions
    Gz = -(sintheta * first_derivative(
        field, dim=x, side=centered, fd_order=order1) + costheta *
           first_derivative(field, dim=z, side=centered, fd_order=order1))
    Gzz = (first_derivative(Gz * sintheta * irho,
                            dim=x,
                            side=centered,
                            fd_order=order1,
                            matvec=transpose) +
           first_derivative(Gz * costheta * irho,
                            dim=z,
                            side=centered,
                            fd_order=order1,
                            matvec=transpose))
    return Gzz
Example #8
0
def adjoint_born(model,
                 rec_coords,
                 rec_data,
                 u=None,
                 op_forward=None,
                 is_residual=False,
                 space_order=8,
                 nb=40,
                 isic=False,
                 dt=None,
                 n_checkpoints=None,
                 maxmem=None):
    clear_cache()

    # Parameters
    nt = rec_data.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, rho, damp = model.m, model.rho, model.damp

    # Create adjoint wavefield and gradient
    v = TimeFunction(name='v',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    gradient = Function(name='gradient', grid=model.grid)

    # Set up PDE and rearrange
    vlaplace, rho = acoustic_laplacian(v, rho)
    H = symbols('H')
    eqn = m / rho * v.dt2 - H - damp * v.dt
    stencil = solve(eqn, v.backward, simplify=False, rational=False)[0]
    expression = [Eq(v.backward, stencil.subs({H: vlaplace}))]

    # Data at receiver locations as adjoint source
    rec_g = Receiver(name='rec_g',
                     grid=model.grid,
                     ntime=nt,
                     coordinates=rec_coords)
    if op_forward is None:
        rec_g.data[:] = rec_data[:]
    adj_src = rec_g.inject(field=v.backward,
                           offset=model.nbpml,
                           expr=rec_g * rho * dt**2 / m)

    # Gradient update
    if u is None:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)
    if isic is not True:
        gradient_update = [Eq(gradient, gradient - dt * u.dt2 / rho * v)]
    else:
        # sum u.dx * v.dx fo x in dimensions.
        # space_order//2
        diff_u_v = sum([
            first_derivative(u, dim=d, order=space_order // 2) *
            first_derivative(v, dim=d, order=space_order // 2)
            for d in u.space_dimensions
        ])
        gradient_update = [
            Eq(gradient, gradient - dt * (u * v.dt2 * m + diff_u_v) / rho)
        ]

    # Create operator and run
    set_log_level('ERROR')
    expression += adj_src + gradient_update
    subs = model.spacing_map
    subs[u.grid.time_dim.spacing] = dt
    op = Operator(expression,
                  subs=subs,
                  dse='advanced',
                  dle='advanced',
                  name="Gradient%s" % randint(1e5))

    # Optimal checkpointing
    if op_forward is not None:
        rec = Receiver(name='rec',
                       grid=model.grid,
                       ntime=nt,
                       coordinates=rec_coords)
        cp = DevitoCheckpoint([u])
        if maxmem is not None:
            n_checkpoints = int(
                np.floor(maxmem * 10**6 / (cp.size * u.data.itemsize)))
        wrap_fw = CheckpointOperator(op_forward, u=u, m=model.m, rec=rec)
        wrap_rev = CheckpointOperator(op, u=u, v=v, m=model.m, rec_g=rec_g)

        # Run forward
        wrp = Revolver(cp, wrap_fw, wrap_rev, n_checkpoints, nt - 2)
        wrp.apply_forward()

        # Residual and gradient
        if is_residual is True:  # input data is already the residual
            rec_g.data[:] = rec_data[:]
        else:
            rec_g.data[:] = rec.data[:] - rec_data[:]  # input is observed data
            fval = .5 * np.dot(rec_g.data[:].flatten(),
                               rec_g.data[:].flatten()) * dt
        wrp.apply_reverse()
    else:
        op()
    clear_cache()

    if op_forward is not None and is_residual is not True:
        return fval, gradient.data
    else:
        return gradient.data
Example #9
0
def forward_born(model,
                 src_coords,
                 wavelet,
                 rec_coords,
                 space_order=8,
                 nb=40,
                 isic=False,
                 dt=None):
    clear_cache()

    # Parameters
    nt = wavelet.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, rho, dm, damp = model.m, model.rho, model.dm, model.damp

    # Create the forward and linearized wavefield
    u = TimeFunction(name="u",
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    du = TimeFunction(name="du",
                      grid=model.grid,
                      time_order=2,
                      space_order=space_order)
    if len(model.shape) == 2:
        x, y = u.space_dimensions
    else:
        x, y, z = u.space_dimensions

    # Set up PDEs and rearrange
    ulaplace, rho = acoustic_laplacian(u, rho)
    dulaplace, _ = acoustic_laplacian(du, rho)
    H = symbols('H')
    S = symbols('S')
    eqn = m / rho * u.dt2 - H + damp * u.dt
    stencil1 = solve(eqn, u.forward, simplify=False, rational=False)[0]
    eqn_lin = m / rho * du.dt2 - H + damp * du.dt + S
    if isic:
        # Sum ((u.dx * d, / rho).dx for x in dimensions)
        # space_order//2  so that u.dx.dx has the same radius as u.laplace
        du_aux = sum([
            first_derivative(
                first_derivative(u, dim=d, order=space_order // 2) * dm / rho,
                order=space_order // 2,
                dim=d) for d in u.space_dimensions
        ])
        lin_source = dm / rho * u.dt2 * m - du_aux
    else:
        lin_source = dm / rho * u.dt2

    stencil2 = solve(eqn_lin, du.forward, simplify=False, rational=False)[0]
    expression_u = [Eq(u.forward, stencil1.subs({H: ulaplace}))]
    expression_du = [
        Eq(du.forward, stencil2.subs({
            H: dulaplace,
            S: lin_source
        }))
    ]

    # Define source symbol with wavelet
    src = PointSource(name='src',
                      grid=model.grid,
                      ntime=nt,
                      coordinates=src_coords)
    src.data[:] = wavelet[:]
    src_term = src.inject(field=u.forward,
                          offset=model.nbpml,
                          expr=src * rho * dt**2 / m)

    # Define receiver symbol
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    rec_term = rec.interpolate(expr=du, offset=model.nbpml)

    # Create operator and run
    set_log_level('ERROR')
    expression = expression_u + src_term + expression_du + rec_term
    subs = model.spacing_map
    subs[u.grid.time_dim.spacing] = dt
    op = Operator(expression,
                  subs=subs,
                  dse='advanced',
                  dle='advanced',
                  name="Born%s" % randint(1e5))
    op()

    return rec.data
Example #10
0
def forward_born(model,
                 src_coords,
                 wavelet,
                 rec_coords,
                 space_order=8,
                 nb=40,
                 isic=False,
                 dt=None):
    clear_cache()

    # Parameters
    nt = wavelet.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, dm, damp = model.m, model.dm, model.damp

    # Create the forward and linearized wavefield
    u = TimeFunction(name="u",
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    du = TimeFunction(name="du",
                      grid=model.grid,
                      time_order=2,
                      space_order=space_order)
    if len(model.shape) == 2:
        x, y = u.space_dimensions
    else:
        x, y, z = u.space_dimensions

    # Set up PDEs and rearrange
    eqn = m * u.dt2 - u.laplace + damp * u.dt
    stencil1 = solve(eqn, u.forward)[0]
    if isic is not True:
        eqn_lin = m * du.dt2 - du.laplace + damp * du.dt + dm * u.dt2  # born modeling
    else:
        du_aux = sum([
            first_derivative(
                first_derivative(u, dim=d, order=space_order // 2) * dm,
                order=space_order // 2,
                dim=d) for d in u.space_dimensions
        ])
        eqn_lin = m * du.dt2 - du.laplace + damp * du.dt + (dm * u.dt2 * m -
                                                            du_aux)

    if isic is not True:
        stencil2 = solve(eqn_lin, du.forward)[0]
    else:
        stencil2 = solve(eqn_lin, du.forward, simplify=False,
                         rational=False)[0]

    expression_u = [Eq(u.forward, stencil1)]
    expression_du = [Eq(du.forward, stencil2)]

    # Define source symbol with wavelet
    src = PointSource(name='src',
                      grid=model.grid,
                      ntime=nt,
                      coordinates=src_coords)
    src.data[:] = wavelet[:]
    src_term = src.inject(field=u.forward,
                          offset=model.nbpml,
                          expr=src * dt**2 / m)

    # Define receiver symbol
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    rec_term = rec.interpolate(expr=du, offset=model.nbpml)

    # Create operator and run
    set_log_level('ERROR')
    expression = expression_u + src_term + expression_du + rec_term
    op = Operator(expression,
                  subs=model.spacing_map,
                  dse='advanced',
                  dle='advanced',
                  name="Born%s" % randint(1e5))
    op(dt=dt)

    return rec.data
def adjoint_born(model, rec_coords, rec_data, u=None, op_forward=None, is_residual=False,
                 space_order=8, isic=False, dt=None, n_checkpoints=None, maxmem=None,
                 free_surface=False, tsub_factor=1, checkpointing=False):
    clear_cache()

    # Parameters
    nt = rec_data.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, rho, damp = model.m, model.rho, model.damp

    # Create adjoint wavefield and gradient
    v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order)
    gradient = Function(name='gradient', grid=model.grid)

    # Set up PDE and rearrange
    vlaplace, rho = acoustic_laplacian(v, rho)
    stencil = damp * (2.0 * v - damp * v.forward + dt**2 * rho / m * vlaplace)
    expression = [Eq(v.backward, stencil)]
    # Data at receiver locations as adjoint source
    rec_g = Receiver(name='rec_g', grid=model.grid, ntime=nt, coordinates=rec_coords)
    if op_forward is None:
        rec_g.data[:] = rec_data[:]
    adj_src = rec_g.inject(field=v.backward, expr=rec_g * rho * dt**2 / m)

    # Gradient update
    if u is None:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order)
    if isic is not True:
        gradient_update = [Inc(gradient, - dt * u.dt2 / rho * v)]
    else:
        # sum u.dx * v.dx fo x in dimensions.
        # space_order//2
        diff_u_v = sum([first_derivative(u, dim=d, fd_order=space_order//2)*
                        first_derivative(v, dim=d, fd_order=space_order//2)
                        for d in u.space_dimensions])
        gradient_update = [Inc(gradient, - tsub_factor * dt * (u * v.dt2 * m + diff_u_v) / rho)]

    # Create operator and run

    # Free surface
    if free_surface is True:
        expression += freesurface(v, space_order//2, model.nbpml, forward=False)

    expression += adj_src + gradient_update
    subs = model.spacing_map
    subs[u.grid.time_dim.spacing] = dt
    op = Operator(expression, subs=subs, dse='advanced', dle='advanced')

    # Optimal checkpointing
    summary1 = None
    summary2 = None
    if op_forward is not None and checkpointing is True:
        rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords)
        cp = DevitoCheckpoint([u])
        if maxmem is not None:
            n_checkpoints = int(np.floor(maxmem * 10**6 / (cp.size * u.data.itemsize)))
        wrap_fw = CheckpointOperator(op_forward, u=u, m=model.m, rec=rec)
        wrap_rev = CheckpointOperator(op, u=u, v=v, m=model.m, rec_g=rec_g)

        # Run forward
        wrp = Revolver(cp, wrap_fw, wrap_rev, n_checkpoints, nt-2)
        wrp.apply_forward()

        # Residual and gradient
        if is_residual is True:  # input data is already the residual
            rec_g.data[:] = rec_data[:]
        else:
            rec_g.data[:] = rec.data[:] - rec_data[:]   # input is observed data
            fval = .5*np.dot(rec_g.data[:].flatten(), rec_g.data[:].flatten()) * dt
        wrp.apply_reverse()

    elif op_forward is not None and checkpointing is False:

        # Compile first
        cf1 = op_forward.cfunction
        cf2 = op.cfunction

        # Run forward and adjoint
        summary1 = op_forward.apply()
        if is_residual is True:
            rec_g.data[:] = rec_data[:]
        else:
            rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords)
            rec_g.data[:] = rec.data[:] - rec_data[:]
            fval = .5*np.dot(rec_g.data[:].flatten(), rec_g.data[:].flatten()) * dt
        summary2 = op.apply()
    else:
        cf = op.cfunction
        summary1 = op.apply()
    clear_cache()

    if op_forward is not None and is_residual is not True:
        if summary2 is not None:
            return fval, gradient.data, summary1, summary2
        elif summary1 is not None:
            return fval, gradient.data, summary1
        else:
            return fval, gradient.data
    else:
        if summary2 is not None:
            return gradient.data, summary1, summary2
        elif summary1 is not None:
            return gradient.data, summary1
        else:
            return gradient.data