コード例 #1
0
ファイル: propagators.py プロジェクト: scdlresearch/JUDI.jl
def born(model, src_coords, rcv_coords, wavelet, space_order=8,
         save=False, q=None, free_surface=False, isic=False, ws=None):
    """
    Low level propagator, to be used through `interface.py`
    Compute adjoint wavefield v = adjoint(F(m))*y
    and related quantities (||v||_w, v(xsrc))
    """
    # Setting adjoint wavefield
    u = wavefield(model, space_order, save=save, nt=wavelet.shape[0])
    ul = wavefield(model, space_order, name="l")

    # Extended source
    q = q or wf_as_src(u, w=0)
    q = extented_src(model, ws, wavelet, q=q)

    # Set up PDE expression and rearrange
    pde, fsu = wave_kernel(model, u, fs=free_surface, q=q)
    pdel, fsul = wave_kernel(model, ul, q=lin_src(model, u, isic=isic), fs=free_surface)

    # Setup source and receiver
    geom_expr, _, _ = src_rec(model, u, src_coords=src_coords, wavelet=wavelet)
    geom_exprl, _, rcvl = src_rec(model, ul, rec_coords=rcv_coords, nt=wavelet.shape[0])

    # Create operator and run
    subs = model.spacing_map
    op = Operator(pde + geom_expr + pdel + geom_exprl + fsu + fsul,
                  subs=subs, name="born"+name(model))
    op(**op_kwargs(model, fs=free_surface))
    # Output
    return rcvl.data, u
コード例 #2
0
def forward(model,
            src_coords,
            rcv_coords,
            wavelet,
            space_order=8,
            save=False,
            q=None,
            return_op=False,
            freq_list=None,
            dft_sub=None,
            ws=None,
            t_sub=1,
            **kwargs):
    """
    Low level propagator, to be used through `interface.py`
    Compute forward wavefield u = A(m)^{-1}*f and related quantities (u(xrcv))
    """
    # Number of time steps
    nt = as_tuple(q)[0].shape[0] if wavelet is None else wavelet.shape[0]

    # Setting forward wavefield
    u = wavefield(model, space_order, save=save, nt=nt, t_sub=t_sub)

    # Expression for saving wavefield if time subsampling is used
    u_save, eq_save = wavefield_subsampled(model, u, nt, t_sub)

    # Add extended source
    q = q or wf_as_src(u, w=0)
    q = extented_src(model, ws, wavelet, q=q)

    # Set up PDE expression and rearrange
    pde = wave_kernel(model, u, q=q)

    # Setup source and receiver
    geom_expr, _, rcv = src_rec(model,
                                u,
                                src_coords=src_coords,
                                nt=nt,
                                rec_coords=rcv_coords,
                                wavelet=wavelet)

    # On-the-fly Fourier
    dft, dft_modes = otf_dft(u, freq_list, model.critical_dt, factor=dft_sub)

    # Create operator and run
    subs = model.spacing_map
    op = Operator(pde + dft + geom_expr + eq_save,
                  subs=subs,
                  name="forward" + name(model),
                  opt=opt_op(model))
    op.cfunction
    if return_op:
        return op, u, rcv

    summary = op()

    # Output
    return rcv, dft_modes or (u_save if t_sub > 1 else u), summary
コード例 #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
コード例 #4
0
def forward_grad(model,
                 src_coords,
                 rcv_coords,
                 wavelet,
                 v,
                 space_order=8,
                 q=None,
                 ws=None,
                 isic=False,
                 w=None,
                 freq=None,
                 **kwargs):
    """
    Low level propagator, to be used through `interface.py`
    Compute forward wavefield u = A(m)^{-1}*f and related quantities (u(xrcv))
    """
    # Number of time steps
    nt = as_tuple(q)[0].shape[0] if wavelet is None else wavelet.shape[0]

    # Setting forward wavefield
    u = wavefield(model, space_order, save=False)

    # Add extended source
    q = q or wf_as_src(u, w=0)
    q = extented_src(model, ws, wavelet, q=q)

    # Set up PDE expression and rearrange
    pde = wave_kernel(model, u, q=q)

    # Setup source and receiver
    geom_expr, _, rcv = src_rec(model,
                                u,
                                src_coords=src_coords,
                                nt=nt,
                                rec_coords=rcv_coords,
                                wavelet=wavelet)

    # Setup gradient wrt m
    gradm = Function(name="gradm", grid=model.grid)
    g_expr = grad_expr(gradm, v, u, model, w=w, isic=isic, freq=freq)

    # Create operator and run
    subs = model.spacing_map
    op = Operator(pde + geom_expr + g_expr,
                  subs=subs,
                  name="forward_grad" + name(model),
                  opt=opt_op(model))

    summary = op()

    # Output
    return rcv, gradm, summary
コード例 #5
0
def born(model,
         src_coords,
         rcv_coords,
         wavelet,
         space_order=8,
         save=False,
         q=None,
         isic=False,
         ws=None,
         t_sub=1):
    """
    Low level propagator, to be used through `interface.py`
    Compute adjoint wavefield v = adjoint(F(m))*y
    and related quantities (||v||_w, v(xsrc))
    """
    nt = wavelet.shape[0]
    # Setting wavefield
    u = wavefield(model, space_order, save=save, nt=nt, t_sub=t_sub)
    ul = wavefield(model, space_order, name="l")

    # Expression for saving wavefield if time subsampling is used
    u_save, eq_save = wavefield_subsampled(model, u, nt, t_sub)

    # Extended source
    q = q or wf_as_src(u, w=0)
    q = extented_src(model, ws, wavelet, q=q)

    # Set up PDE expression and rearrange
    pde, tmpu = wave_kernel(model, u, q=q)
    pdel, tmpul = wave_kernel(model, ul, q=lin_src(model, u, isic=isic))

    # Setup source and receiver
    geom_expr, _, _ = src_rec(model, u, src_coords=src_coords, wavelet=wavelet)
    geom_exprl, _, rcvl = src_rec(model,
                                  ul,
                                  rec_coords=rcv_coords,
                                  nt=wavelet.shape[0])

    # Create operator and run
    subs = model.spacing_map
    op = Operator(tmpu + tmpul + pde + geom_expr + geom_exprl + pdel + eq_save,
                  subs=subs,
                  name="born" + name(model),
                  opt=opt_op(model, no_ms=ws is not None))

    summary = op()

    # Output
    return rcvl, (u_save if t_sub > 1 else u), summary
コード例 #6
0
def objTWRIdual_devito(model, y, src_coords, rcv_coords, wav,
                       dat, Filter, eps, mode="eval", objfact=np.float32(1),
                       comp_alpha=True, grad_corr=False, weight_fun_pars=None,
                       dt=None, space_order=8):
    """
    Evaluate TWRI objective functional/gradients for current (m, y)
    """
    # Setting time sampling
    if dt is None:
        dt = model.critical_dt

    # Computing y in reduced mode (= residual) if not provided
    u0 = None
    y_was_None = y is None
    if y_was_None:
        u0rcv, u0 = forward(model, src_coords, rcv_coords, wav, dt=dt,
                            space_order=space_order, save=(mode == "grad") and grad_corr)
        y = applyfilt(dat-u0rcv, Filter)
        PTy = applyfilt_transp(y, Filter)
    else:
        PTy = y
    # Normalization constants
    nx = np.float32(model.vp.size)
    nt, nr = np.float32(y.shape)
    etaf = npla.norm(wav.reshape(-1)) / np.sqrt(nt * nx)
    etad = npla.norm(applyfilt(dat, Filter).reshape(-1)) / np.sqrt(nt * nr)

    # Compute wavefield vy = adjoint(F(m))*Py
    norm_vPTy2, vPTy_src, vPTy = adjoint_y(model, PTy, src_coords, rcv_coords,
                                           weight_fun_pars=weight_fun_pars, dt=dt,
                                           space_order=space_order, save=(mode == "grad"))

    # <PTy, d-F(m)*f> = <PTy, d>-<adjoint(F(m))*PTy, f>
    PTy_dot_r = (np.dot(PTy.reshape(-1), dat.reshape(-1)) -
                 np.dot(vPTy_src.reshape(-1), wav.reshape(-1)))

    # ||y||
    norm_y = npla.norm(y.reshape(-1))

    # Optimal alpha
    c1 = etaf**np.float32(2) / (np.float32(4) * etad**np.float32(2) * nx * nt)
    c2 = np.float32(1) / (etad * nr * nt)
    c3 = eps / np.sqrt(nr * nt)
    alpha = compute_optalpha(c1*norm_vPTy2, c2*PTy_dot_r, c3*norm_y,
                             comp_alpha=comp_alpha)

    # Lagrangian evaluation
    fun = (alpha * (-alpha * c1 * norm_vPTy2 + c2 * PTy_dot_r) -
           np.abs(alpha) * c3 * norm_y)
    # Gradient computation
    if mode == "grad":
        # Set up extebded source
        w = 2.0 * c1 / c2 * alpha
        if weight_fun_pars is not None:
            w /= weight_fun(weight_fun_pars, model, src_coords)**2
        Q = wf_as_src(vPTy, w=w)

        # Setup gradient wrt m
        u = wavefield(model, space_order)
        gradm = Function(name="gradm", grid=model.grid)
        g_exp = grad_expr(gradm, u, vPTy, w=alpha * c2)
        rcv, _ = forward(model, src_coords, rcv_coords, wav, dt=dt,
                         space_order=space_order, q=Q, extra_expr=g_exp, u=u)

        # Compute gradient wrt y
        if not y_was_None or grad_corr:
            norm_y = npla.norm(y)
            grady_data = alpha * c2 * applyfilt(dat - rcv.data, Filter)
            if norm_y != 0:
                grady_data -= np.abs(alpha) * c3 * y / norm_y

        # Correcting for reduced gradient
        if not y_was_None or (y_was_None and not grad_corr):
            gradm_data = gradm.data
        else:
            gradm_corr = gradient(model, applyfilt_transp(grady_data, Filter), rcv_coords,
                                  u0, dt=dt, space_order=space_order, w=1)
            # Reduced gradient post-processing
            gradm_data = gradm.data + gradm_corr.data

    # Return output

    if mode == "eval":
        return fun / objfact
    elif mode == "grad" and y_was_None:
        return fun / objfact, gradm_data / objfact
    elif mode == "grad" and not y_was_None:
        return fun / objfact, gradm_data / objfact, grady_data / objfact
コード例 #7
0
def born(model,
         src_coords,
         rcv_coords,
         wavelet,
         space_order=8,
         save=False,
         q=None,
         return_op=False,
         isic=False,
         freq_list=None,
         dft_sub=None,
         ws=None,
         t_sub=1,
         nlind=False):
    """
    Low level propagator, to be used through `interface.py`
    Compute linearized wavefield U = J(m)* δ m
    and related quantities.
    """
    nt = wavelet.shape[0]
    # Setting wavefield
    u = wavefield(model, space_order, save=save, nt=nt, t_sub=t_sub)
    ul = wavefield(model, space_order, name="l")

    # Expression for saving wavefield if time subsampling is used
    u_save, eq_save = wavefield_subsampled(model, u, nt, t_sub)

    # Extended source
    q = q or wf_as_src(u, w=0)
    q = extented_src(model, ws, wavelet, q=q)

    # Set up PDE expression and rearrange
    pde = wave_kernel(model, u, q=q)
    if model.dm == 0:
        pdel = []
    else:
        pdel = wave_kernel(model, ul, q=lin_src(model, u, isic=isic))
    # Setup source and receiver
    geom_expr, _, rcvnl = src_rec(model,
                                  u,
                                  rec_coords=rcv_coords if nlind else None,
                                  src_coords=src_coords,
                                  wavelet=wavelet)
    geom_exprl, _, rcvl = src_rec(model, ul, rec_coords=rcv_coords, nt=nt)

    # On-the-fly Fourier
    dft, dft_modes = otf_dft(u, freq_list, model.critical_dt, factor=dft_sub)

    # Create operator and run
    subs = model.spacing_map
    op = Operator(pde + geom_expr + geom_exprl + pdel + dft + eq_save,
                  subs=subs,
                  name="born" + name(model),
                  opt=opt_op(model))
    op.cfunction
    outrec = (rcvl, rcvnl) if nlind else rcvl
    if return_op:
        return op, u, outrec

    summary = op()

    # Output
    return outrec, dft_modes or (u_save if t_sub > 1 else u), summary
コード例 #8
0
    def twri_fun(self,
                 y,
                 src_coords,
                 rcv_coords,
                 wav,
                 dat,
                 Filter,
                 eps,
                 mode="eval",
                 objfact=np.float32(1),
                 comp_alpha=True,
                 grad_corr=False,
                 weight_fun_pars=None):
        """
        Evaluate TWRI objective functional/gradients for current (m, y)
        """
        clear_cache()
        dt = self.model.critical_dt

        # Computing y in reduced mode (= residual) if not provided
        u0 = None
        y_was_None = y is None
        if y_was_None:
            u0rcv, u0 = self.forward_run(wav,
                                         src_coords,
                                         rcv_coords,
                                         save=(mode == "grad") and grad_corr)
            y = applyfilt(dat - u0rcv, Filter)
            PTy = applyfilt_transp(y, Filter)
        else:
            PTy = y
        # Normalization constants
        nx = np.float32(self.model.vp.size)
        nt, nr = np.float32(y.shape)
        etaf = npla.norm(wav.reshape(-1)) / np.sqrt((nt * dt) * nx)
        etad = npla.norm(applyfilt(dat, Filter).reshape(-1)) / np.sqrt(
            (nt * dt) * nr)

        # Compute wavefield vy = adjoint(F(m))*Py
        norm_vPTy2, vPTy_src, vPTy = self.adjoint_y_run(
            PTy,
            src_coords,
            rcv_coords,
            weight_fun_pars=weight_fun_pars,
            save=(mode == "grad"))

        # <PTy, d-F(m)*f> = <PTy, d>-<adjoint(F(m))*PTy, f>
        PTy_dot_r = (np.dot(PTy.reshape(-1), dat.reshape(-1)) -
                     np.dot(vPTy_src.reshape(-1), wav.reshape(-1)))

        # ||y||
        norm_y = np.sqrt(dt) * npla.norm(y.reshape(-1))

        # Optimal alpha
        c1 = etaf**np.float32(2) / (np.float32(4) * etad**np.float32(2) * nx *
                                    (nt * dt))
        c2 = np.float32(1) / (etad * nr * (nt * dt))
        c3 = eps / np.sqrt(nr * (nt * dt))
        alpha = compute_optalpha(c1 * norm_vPTy2,
                                 c2 * PTy_dot_r,
                                 c3 * norm_y,
                                 comp_alpha=comp_alpha)
        # Lagrangian evaluation
        fun = (alpha * (-alpha * c1 * norm_vPTy2 + c2 * PTy_dot_r) -
               np.abs(alpha) * c3 * norm_y)
        # Gradient computation
        if mode == "grad":
            # Set up extebded source
            w = 2.0 * c1 / c2 * alpha
            if weight_fun_pars is not None:
                w /= weight_fun(weight_fun_pars, self.model, src_coords)**2
            Q = wf_as_src(vPTy, w=w)

            # Setup gradient wrt m
            rcv, _, gradm = self.forward_run(wav,
                                             src_coords,
                                             rcv_coords,
                                             q=Q,
                                             grad=True,
                                             w=alpha * c2,
                                             v=vPTy)
            # Compute gradient wrt y
            if not y_was_None or grad_corr:
                norm_y = npla.norm(y)
                grady_data = alpha * c2 * applyfilt(dat - rcv.data, Filter)
                if norm_y != 0:
                    grady_data -= np.abs(alpha) * c3 * y / norm_y

            # Correcting for reduced gradient
            if not y_was_None or (y_was_None and not grad_corr):
                gradm_data = gradm.data
            else:
                gradm_corr = self.grad_run(
                    rcv_coords, applyfilt_transp(grady_data, Filter), u0)
                # Reduced gradient post-processing
                gradm_data = gradm.data + gradm_corr.data

        # Return output
        if mode == "eval":
            return fun / objfact
        elif mode == "grad" and y_was_None:
            return fun / objfact, -gradm_data / objfact
        elif mode == "grad" and not y_was_None:
            return fun / objfact, -gradm_data / objfact, grady_data / objfact