def test_Fredholm1(par):
    """Dot-test and comparison with PyLops for Fredholm1 operator
    """
    _F = \
        da.arange(par['nsl'] * par['nx'] *
                  par['ny']).reshape(par['nsl'],
                                     par['nx'],
                                     par['ny']).rechunk((par['nsl']//2,
                                                         par['nx'],
                                                         par['ny']))
    F = _F - par['imag'] * _F
    dFop = dFredholm1(F,
                      nz=par['nz'],
                      saveGt=par['saveGt'],
                      compute=(True, True),
                      dtype=par['dtype'])
    assert dottest(dFop,
                   par['nsl'] * par['nx'] * par['nz'],
                   par['nsl'] * par['ny'] * par['nz'],
                   chunks=(((par['nsl'] * par['nx'] * par['ny']) // 2),
                           ((par['nsl'] * par['nx'] * par['ny']) // 2)),
                   complexflag=0 if par['imag'] == 0 else 3)

    x = da.ones((par['nsl'], par['ny'], par['nz']),
                chunks=(par['nsl'] // 2, par['ny'], par['nz'])) + \
        par['imag'] * da.ones((par['nsl'], par['ny'], par['nz']),
                              chunks=(par['nsl'] // 2, par['ny'], par['nz']))
    Fop = Fredholm1(F.compute(),
                    nz=par['nz'],
                    saveGt=par['saveGt'],
                    usematmul=True,
                    dtype=par['dtype'])
    dy = dFop * x.ravel()
    y = Fop * x.ravel().compute()
    assert_array_almost_equal(dy, y, decimal=5)
예제 #2
0
def test_Fredholm1(par):
    """Dot-test and inversion for Fredholm1 operator"""
    np.random.seed(10)

    _F = np.arange(par["nsl"] * par["nx"] * par["ny"]).reshape(
        par["nsl"], par["nx"], par["ny"]
    )
    F = _F - par["imag"] * _F

    x = np.ones((par["nsl"], par["ny"], par["nz"])) + par["imag"] * np.ones(
        (par["nsl"], par["ny"], par["nz"])
    )

    Fop = Fredholm1(
        F,
        nz=par["nz"],
        saveGt=par["saveGt"],
        usematmul=par["usematmul"],
        dtype=par["dtype"],
    )
    assert dottest(
        Fop,
        par["nsl"] * par["nx"] * par["nz"],
        par["nsl"] * par["ny"] * par["nz"],
        complexflag=0 if par["imag"] == 0 else 3,
    )
    xlsqr = lsqr(Fop, Fop * x.ravel(), damp=1e-20, iter_lim=30, show=0)[0]
    xlsqr = xlsqr.reshape(par["nsl"], par["ny"], par["nz"])
    assert_array_almost_equal(x, xlsqr, decimal=3)
예제 #3
0
def test_Fredholm1(par):
    """Dot-test and inversion for Fredholm1 operator
    """
    _F = np.arange(par['nsl'] * par['nx'] * par['ny']).reshape(par['nsl'],
                                                               par['nx'],
                                                               par['ny'])
    F = _F - par['imag'] * _F
    print(F)
    x = np.ones((par['nsl'], par['ny'], par['nz'])) + \
        par['imag'] * np.ones((par['nsl'], par['ny'], par['nz']))

    Fop = Fredholm1(F, nz=par['nz'], saveGt=par['saveGt'],
                    usematmul=par['usematmul'], dtype=par['dtype'])
    assert dottest(Fop, par['nsl']*par['nx']*par['nz'],
                   par['nsl']*par['ny']*par['nz'],
                   complexflag=0 if par['imag'] == 0 else 3)
    xlsqr = lsqr(Fop, Fop * x.flatten(), damp=1e-20,
                 iter_lim=30, show=0)[0]
    xlsqr = xlsqr.reshape(par['nsl'], par['ny'], par['nz'])
    assert_array_almost_equal(x, xlsqr, decimal=3)
예제 #4
0
파일: mdd.py 프로젝트: ETDelaney/pylops
def MDC(G,
        nt,
        nv,
        dt=1.,
        dr=1.,
        twosided=True,
        fast=None,
        dtype=None,
        fftengine='numpy',
        transpose=True,
        saveGt=True,
        conj=False):
    r"""Multi-dimensional convolution.

    Apply multi-dimensional convolution between two datasets. If
    ``transpose=True``, model and data should be provided after flattening
    2- or 3-dimensional arrays of size :math:`[n_r (\times n_{vs}) \times n_t]`
    and :math:`[n_s (\times n_{vs}) \times n_t]` (or :math:`2*n_t-1` for
    ``twosided=True``), respectively. If ``transpose=False``, model and data
    should be provided after flattening 2- or 3-dimensional arrays of size
    :math:`[n_t \times n_r (\times n_{vs})]` and
    :math:`[n_t \times n_s (\times n_{vs})]` (or :math:`2*n_t-1` for
    ``twosided=True``), respectively.

    .. warning:: A new implementation of MDC is provided in v1.5.0. This
      currently affects only the inner working of the operator and end-users
      can use the operator in the same way as they used to do with the previous
      one. Nevertheless, it is now reccomended to use the operator with
      ``transpose=False``, as this behaviour will become default in version
      v2.0.0 and the behaviour with ``transpose=True`` will be deprecated.

    Parameters
    ----------
    G : :obj:`numpy.ndarray`
        Multi-dimensional convolution kernel in frequency domain of size
        :math:`[\times n_s \times n_r \times n_{fmax}]` if ``transpose=True``
        or size :math:`[n_{fmax} \times n_s \times n_r]` if ``transpose=False``
    nt : :obj:`int`
        Number of samples along time axis
    nv : :obj:`int`
        Number of samples along virtual source axis
    dt : :obj:`float`, optional
        Sampling of time integration axis
    dr : :obj:`float`, optional
        Sampling of receiver integration axis
    twosided : :obj:`bool`, optional
        MDC operator has both negative and positive time (``True``) or
        only positive (``False``)
    fast : :obj:`bool`, optional
        *Deprecated*, will be removed in v2.0.0
    dtype : :obj:`str`, optional
        *Deprecated*, will be removed in v2.0.0
    fftengine : :obj:`str`, optional
        Engine used for fft computation (``numpy`` or ``fftw``)
    transpose : :obj:`bool`, optional
        Transpose ``G`` and inputs such that time/frequency is placed in first
        dimension. This allows back-compatibility with v1.4.0 and older but
        will be removed in v2.0.0 where time/frequency axis will be required
        to be in first dimension for efficiency reasons.
    saveGt : :obj:`bool`, optional
        Save ``G`` and ``G^H`` to speed up the computation of adjoint of
        :class:`pylops.signalprocessing.Fredholm1` (``True``) or create
        ``G^H`` on-the-fly (``False``) Note that ``saveGt=True`` will be
        faster but double the amount of required memory
    conj : :obj:`str`, optional
        Perform Fredholm integral computation with complex conjugate of ``G``

    See Also
    --------
    MDD : Multi-dimensional deconvolution

    Notes
    -----
    The so-called multi-dimensional convolution (MDC) is a chained
    operator [1]_. It is composed of a forward Fourier transform,
    a multi-dimensional integration, and an inverse Fourier transform:

    .. math::
        y(f, s, v) = \mathscr{F}^{-1} \Big( \int_S G(f, s, r)
        \mathscr{F}(x(f, r, v)) dr \Big)

    This operation can be discretized and performed by means of a
    linear operator

    .. math::
        \mathbf{D}= \mathbf{F}^H  \mathbf{G} \mathbf{F}

    where :math:`\mathbf{F}` is the Fourier transform applied along
    the time axis and :math:`\mathbf{G}` is the multi-dimensional
    convolution kernel.

    .. [1] Wapenaar, K., van der Neut, J., Ruigrok, E., Draganov, D., Hunziker,
       J., Slob, E., Thorbecke, J., and Snieder, R., "Seismic interferometry
       by crosscorrelation and by multi-dimensional deconvolution: a
       systematic comparison", Geophysical Journal International, vol. 185,
       pp. 1335-1364. 2011.

    """
    warnings.warn(
        'A new implementation of MDC is provided in v1.5.0. This '
        'currently affects only the inner working of the operator, '
        'end-users can continue using the operator in the same way. '
        'Nevertheless, it is now recommended to start using the '
        'operator with transpose=True, as this behaviour will '
        'become default in version v2.0.0 and the behaviour with '
        'transpose=False will be deprecated.', FutureWarning)

    if twosided and nt % 2 == 0:
        raise ValueError('nt must be odd number')

    # transpose G
    if transpose:
        G = np.transpose(G, axes=(2, 0, 1))

    # create Fredholm operator
    dtype = G[0, 0, 0].dtype
    fdtype = (G[0, 0, 0] + 1j * G[0, 0, 0]).dtype
    Frop = Fredholm1(dr * dt * np.sqrt(nt) * G,
                     nv,
                     saveGt=saveGt,
                     usematmul=False,
                     dtype=fdtype)
    if conj:
        Frop = Frop.conj()

    # create FFT operators
    nfmax, ns, nr = G.shape
    # ensure that nfmax is not bigger than allowed
    nfft = int(np.ceil((nt + 1) / 2))
    if nfmax > nfft:
        nfmax = nfft
        logging.warning('nfmax set equal to ceil[(nt+1)/2=%d]' % nfmax)

    Fop = FFT(dims=(nt, nr, nv),
              dir=0,
              real=True,
              fftshift=twosided,
              engine=fftengine,
              dtype=fdtype)
    F1op = FFT(dims=(nt, ns, nv),
               dir=0,
               real=True,
               fftshift=False,
               engine=fftengine,
               dtype=fdtype)

    # create Identity operator to extract only relevant frequencies
    Iop = Identity(N=nfmax * nr * nv,
                   M=nfft * nr * nv,
                   inplace=True,
                   dtype=dtype)
    I1op = Identity(N=nfmax * ns * nv,
                    M=nfft * ns * nv,
                    inplace=True,
                    dtype=dtype)
    F1opH = F1op.H
    I1opH = I1op.H

    # create transpose operator
    if transpose:
        dims = [nr, nt] if nv == 1 else [nr, nv, nt]
        axes = (1, 0) if nv == 1 else (2, 0, 1)
        Top = Transpose(dims, axes, dtype=dtype)

        dims = [nt, ns] if nv == 1 else [nt, ns, nv]
        axes = (1, 0) if nv == 1 else (1, 2, 0)
        TopH = Transpose(dims, axes, dtype=dtype)

    # create MDC operator
    MDCop = F1opH * I1opH * Frop * Iop * Fop
    if transpose:
        MDCop = TopH * MDCop * Top
    return MDCop