Example #1
0
def grad_fwi(model, recin, rec_coords, u, space_order=8, free_surface=False):
    """
    FWI gradient, i.e adjoint Jacobian on a data residual.

    Parameters
    ----------
    model: Model
        Physical model
    recin: Array
        Data residual
    rec_coords: Array
        Receivers coordinates
    u: TimeFunction
        Forward wavefield
    space_order: Int (optional)
        Spatial discretization order, defaults to 8
    free_surface: Bool (optional)
        Whether or not to use a free surface

    Returns
    ----------
    Array
        FWI gradient
    """
    g = gradient(model, recin, rec_coords, u, space_order=space_order,
                 free_surface=free_surface)
    return g.data
Example #2
0
def J_adjoint_freq(model, src_coords, wavelet, rec_coords, recin, space_order=8,
                   freq_list=[], is_residual=False, return_obj=False, nlind=False,
                   dft_sub=None, isic=False, ws=None, t_sub=1, born_fwd=False):
    """
    Jacobian (adjoint fo born modeling operator) operator on a shot record
    as a source (i.e data residual). Outputs the gradient with Frequency
    compression (on-the-fly DFT).

    Parameters
    ----------
    model: Model
        Physical model
    src_coords: Array
        Coordiantes of the source(s)
    wavelet: Array
        Source signature
    rec_coords: Array
        Coordiantes of the receiver(s)
    recin: Array
        Receiver data
    space_order: Int (optional)
        Spatial discretization order, defaults to 8
    freq_list: List
        List of frequencies for on-the-fly DFT
    dft_sub: Int
        Subsampling factor for on-the-fly DFT
    isic : Bool
        Whether or not to use ISIC imaging condition
    ws : Array
        Extended source spatial distribution
    is_residual: Bool
        Whether to treat the input as the residual or as the observed data
    born_fwd: Bool
        Whether to use the forward or linearized forward modeling operator
    nlind: Bool
        Whether to remove the non linear data from the input data. This option is
        only available in combination with `born_fwd`

    Returns
    ----------
    Array
        Adjoint jacobian on the input data (gradient)
    """
    rec, u, _ = op_fwd_J[born_fwd](model, src_coords, rec_coords, wavelet, save=False,
                                   space_order=space_order, freq_list=freq_list,
                                   ws=ws, dft_sub=dft_sub, nlind=nlind)
    # Residual and gradient
    if not is_residual:
        if nlind:
            recin[:] = rec[0].data[:] - (recin[:] - rec[1].data)  # input is observed data
        else:
            recin[:] = rec.data[:] - recin[:]   # input is observed data

    g, _ = gradient(model, recin, rec_coords, u, space_order=space_order, isic=isic,
                    freq=freq_list, dft_sub=dft_sub)
    if return_obj:
        return .5*model.critical_dt*np.linalg.norm(recin)**2, g.data
    return g.data
Example #3
0
def wri_func(model, src_coords, wavelet, rec_coords, recin, yin, space_order=8,
             isic=False, ws=None, t_sub=1, grad="m", grad_corr=False,
             alpha_op=False, w_fun=None, eps=0):
    """
    Time domain wavefield reconstruction inversion wrapper
    """
    # F(m0) * q if y is not an input and compute y = r(m0)
    if yin is None or grad_corr:
        y, u0, _ = forward(model, src_coords, rec_coords, wavelet, save=grad_corr,
                           space_order=space_order, ws=ws)
        ydat = recin[:] - y.data[:]
    else:
        ydat = yin

    # Compute wavefield vy = adjoint(F(m0))*y and norm on the fly
    srca, v, norm_v, _ = adjoint(model, ydat, src_coords, rec_coords,
                                 norm_v=True, w_fun=w_fun,
                                 save=grad is not None)
    c1 = 1 / (recin.shape[1])
    c2 = np.log(np.prod(model.shape))
    # <PTy, d-F(m)*f> = <PTy, d>-<adjoint(F(m))*PTy, f>
    ndt = np.sqrt(model.critical_dt)
    PTy_dot_r = ndt**2 * (np.dot(ydat.reshape(-1), recin.reshape(-1)) -
                          np.dot(srca.data.reshape(-1), wavelet.reshape(-1)))
    norm_y = ndt * np.linalg.norm(ydat)

    # alpha
    α = compute_optalpha(c2*norm_y, c1*norm_v, eps, comp_alpha=alpha_op)

    # Lagrangian evaluation
    fun = -.5 * c1 * α**2 * norm_v + c2 * α * PTy_dot_r - eps * np.abs(α) * norm_y

    gradm = grady = None
    if grad is not None:
        w = weight_fun(w_fun, model, src_coords)
        w = c1*α/w**2 if w is not None else c1*α
        Q = wf_as_src(v, w=w)
        rcv, gradm, _ = forward_grad(model, src_coords, rec_coords, c2*wavelet, q=Q, v=v)

        # Compute gradient wrt y
        if grad_corr or grad in ["all", "y"]:
            grady = c2 * recin - rcv.data[:]
            if norm_y != 0:
                grady -= np.abs(eps) * ydat / norm_y

        # Correcting for reduced gradient
        if not grad_corr:
            gradm = gradm.data
        else:
            gradm_corr, _ = gradient(model, grady, rec_coords, u0)
            # Reduced gradient post-processing
            gradm = gradm.data + gradm_corr.data

    return fun, α * gradm, grady
Example #4
0
def J_adjoint_freq(model, src_coords, wavelet, rec_coords, recin, space_order=8,
                   free_surface=False, freq_list=[], is_residual=False, return_obj=False,
                   dft_sub=None, isic=False, ws=None, t_sub=1):
    """
    Jacobian (adjoint fo born modeling operator) operator on a shot record
    as a source (i.e data residual). Outputs the gradient with Frequency
    compression (on-the-fly DFT).

    Parameters
    ----------
    model: Model
        Physical model
    src_coords: Array
        Coordiantes of the source(s)
    wavelet: Array
        Source signature
    rec_coords: Array
        Coordiantes of the receiver(s)
    recin: Array
        Receiver data
    space_order: Int (optional)
        Spatial discretization order, defaults to 8
    free_surface: Bool (optional)
        Whether or not to use a free surface
    freq_list: List
        List of frequencies for on-the-fly DFT
    dft_sub: Int
        Subsampling factor for on-the-fly DFT
    isic : Bool
        Whether or not to use ISIC imaging condition
    ws : Array
        Extended source spatial distribution
    is_residual: Bool
        Whether to treat the input as the residual or as the observed data

    Returns
    ----------
    Array
        Adjoint jacobian on the input data (gradient)
    """
    rec, u = forward(model, src_coords, rec_coords, wavelet, save=False,
                     space_order=space_order, free_surface=free_surface,
                     freq_list=freq_list, dft_sub=dft_sub, ws=ws)
    # Residual and gradient
    if not is_residual:
        recin[:] = rec.data[:] - recin[:]   # input is observed data

    g = gradient(model, recin, rec_coords, u, space_order=space_order, isic=isic,
                 free_surface=free_surface, freq=freq_list, dft_sub=dft_sub)
    if return_obj:
        return .5*model.critical_dt*np.linalg.norm(recin)**2, g.data
    return g.data
Example #5
0
def J_adjoint_standard(model, src_coords, wavelet, rec_coords, recin, space_order=8,
                       free_surface=False, is_residual=False, return_obj=False,
                       isic=False, ws=None, t_sub=1):
    """
    Adjoint Jacobian (adjoint fo born modeling operator) operator on a shot record
    as a source (i.e data residual). Outputs the gradient with standard
    zero lag cross correlation over time.

    Parameters
    ----------
    model: Model
        Physical model
    src_coords: Array
        Coordiantes of the source(s)
    wavelet: Array
        Source signature
    rec_coords: Array
        Coordiantes of the receiver(s)
    recin: Array
        Receiver data
    space_order: Int (optional)
        Spatial discretization order, defaults to 8
    free_surface: Bool (optional)
        Whether or not to use a free surface
    isic : Bool
        Whether or not to use ISIC imaging condition
    ws : Array
        Extended source spatial distribution
    is_residual: Bool
        Whether to treat the input as the residual or as the observed data

    Returns
    ----------
    Array
        Adjoint jacobian on the input data (gradient)
    """
    rec, u = forward(model, src_coords, rec_coords, wavelet, save=True, ws=ws,
                     space_order=space_order, free_surface=free_surface, t_sub=t_sub)
    # Residual and gradient
    if not is_residual:
        recin[:] = rec.data[:] - recin[:]   # input is observed data

    g = gradient(model, recin, rec_coords, u, space_order=space_order,
                 free_surface=free_surface, isic=isic)
    if return_obj:
        return .5*model.critical_dt*np.linalg.norm(recin)**2, g.data
    return g.data
Example #6
0
def grad_fwi(model, recin, rec_coords, u, space_order=8):
    """
    FWI gradient, i.e adjoint Jacobian on a data residual.

    Parameters
    ----------
    model: Model
        Physical model
    recin: Array
        Data residual
    rec_coords: Array
        Receivers coordinates
    u: TimeFunction
        Forward wavefield
    space_order: Int (optional)
        Spatial discretization order, defaults to 8

    Returns
    ----------
    Array
        FWI gradient
    """
    g, _ = gradient(model, recin, rec_coords, u, space_order=space_order)
    return g.data
Example #7
0
    dt = new_time_range.step
    to_interp = np.asarray(rec.data)
    data = np.zeros((num, to_interp.shape[1]))
    for i in range(to_interp.shape[1]):
        tck = interpolate.splrep(time, to_interp[:, i], k=3)
        data[:, i] = interpolate.splev(new_time_range.time_values, tck)
    coords_loc = np.asarray(rec.coordinates.data)
    # Return new object
    return data, coords_loc


# Devito operator
d_obs, u0, summary1 = forward(model,
                              src.coordinates.data,
                              rec_coords,
                              src.data,
                              save=True,
                              t_sub=12)
grad, summary2 = gradient(model, d_obs, rec_coords, u0, isic=True)

grad.data[:, 0:66] = 0  # mute water column

# Remove pml and pad
rtm = grad.data[model.nbl:-model.nbl, model.nbl:-model.nbl]  # remove padding
rtm = extent_gradient(shape_full, origin_full, shape, origin, spacing, rtm)
plt.figure()
plt.imshow(d_obs.data, vmin=-1e-1, vmax=1e-1, cmap='gray', aspect='auto')
plt.figure()
plt.imshow(np.transpose(rtm), vmin=-2e0, vmax=2e0, cmap='gray', aspect='auto')
plt.show()
Example #8
0
def J_adjoint_checkpointing(model,
                            src_coords,
                            wavelet,
                            rec_coords,
                            recin,
                            space_order=8,
                            is_residual=False,
                            n_checkpoints=None,
                            maxmem=None,
                            return_obj=False,
                            isic=False,
                            ws=None,
                            t_sub=1):
    """
    Jacobian (adjoint fo born modeling operator) operator on a shot record
    as a source (i.e data residual). Outputs the gradient with Checkpointing.

    Parameters
    ----------
    model: Model
        Physical model
    src_coords: Array
        Coordiantes of the source(s)
    wavelet: Array
        Source signature
    rec_coords: Array
        Coordiantes of the receiver(s)
    recin: Array
        Receiver data
    space_order: Int (optional)
        Spatial discretization order, defaults to 8
    checkpointing: Bool
        Whether or not to use checkpointing
    n_checkpoints: Int
        Number of checkpoints for checkpointing
    maxmem: Float
        Maximum memory to use for checkpointing
    isic : Bool
        Whether or not to use ISIC imaging condition
    ws : Array
        Extended source spatial distribution
    is_residual: Bool
        Whether to treat the input as the residual or as the observed data

    Returns
    ----------
     Array
        Adjoint jacobian on the input data (gradient)
    """
    # Optimal checkpointing
    op_f, u, rec_g = forward(model,
                             src_coords,
                             rec_coords,
                             wavelet,
                             space_order=space_order,
                             return_op=True,
                             ws=ws)
    op, g, v = gradient(model,
                        recin,
                        rec_coords,
                        u,
                        space_order=space_order,
                        return_op=True,
                        isic=isic)

    nt = wavelet.shape[0]
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    cp = DevitoCheckpoint([uu for uu in as_tuple(u)])
    if maxmem is not None:
        memsize = (cp.size * u.data.itemsize)
        n_checkpoints = int(np.floor(maxmem * 10**6 / memsize))
    # Op arguments
    uk = {uu.name: uu for uu in as_tuple(u)}
    vk = {**uk, **{vv.name: vv for vv in as_tuple(v)}}
    uk.update({'rcv%s' % as_tuple(u)[0].name: rec_g})
    vk.update({'src%s' % as_tuple(v)[0].name: rec})
    # Wrapped ops
    wrap_fw = CheckpointOperator(op_f, vp=model.vp, **uk)
    wrap_rev = CheckpointOperator(op, vp=model.vp, **vk)

    # 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.data[:] = recin[:]
    else:
        rec.data[:] = rec.data[:] - recin[:]  # input is observed data

    wrp.apply_reverse()

    if return_obj:
        return .5 * model.critical_dt * norm(rec)**2, g.data
    return g.data
Example #9
0
                      src.coordinates.data,
                      rec_t.coordinates.data,
                      src.data,
                      save=True)

# Forward
print("Forward")
_, u0, _ = forward(model,
                   src.coordinates.data,
                   rec_t.coordinates.data,
                   src.data,
                   save=True)

# gradient
print("Adjoint J")
dm_hat, _ = gradient(model, dD_hat, rec_t.coordinates.data, u0)

# Adjoint test
a = model.critical_dt * inner(dD_hat, dD_hat)
b = inner(dm_hat, model.dm)

if is_tti:
    c = np.linalg.norm(u0[0].data.flatten() - u0l[0].data.flatten(), np.inf)
else:
    c = np.linalg.norm(u0.data.flatten() - u0l.data.flatten(), np.inf)

print("Difference between saving with forward and born", c)

print("Adjoint test J")
print("a = %2.2e, b = %2.2e, diff = %2.2e: " % (a, b, a - b))
print("Relative error: ", a / b - 1)
Example #10
0
#########################################################################################

# Source wavelet
tn = 1000.
dt_shot = model.critical_dt
nt = int(tn / dt_shot)
time_s = np.linspace(0, tn, nt)
wavelet = Ricker(0.015, time_s)

#########################################################################################

# Devito operator
d_obs = born(model, src_coords, rec_coords, wavelet, save=False)[0]

u0 = forward(model, src_coords, rec_coords, wavelet, save=True, t_sub=8)[1]
grad_dist = gradient(model, d_obs, d_obs.coordinates, u0, isic=False)[0]

if rank > 0:
    # Send result to master
    comm.send(model.m.local_indices, dest=0, tag=10)
    comm.send(grad_dist.data, dest=0, tag=11)

else:  # Master
    # Initialize full array
    grad = np.empty(shape=model.m.shape_global, dtype='float32')
    grad[model.m.local_indices] = grad_dist.data

    # Collect gradients
    for j in range(1, size):
        local_indices = comm.recv(source=j, tag=10)
        glocal = comm.recv(source=j, tag=11)