Exemplo n.º 1
0
def from_scratch_gradient_test(shape=(70, 70), kernel='OT2', space_order=6):
    spacing = tuple(10. for _ in shape)
    wave = setup(shape=shape,
                 spacing=spacing,
                 dtype=np.float64,
                 kernel=kernel,
                 space_order=space_order,
                 nbl=40)
    v0 = Function(name='v0', grid=wave.model.grid, space_order=space_order)
    smooth(v0, wave.model.vp)
    v = wave.model.vp.data

    dm = np.float64(v**(-2) - v0.data**(-2))

    # Compute receiver data for the true velocity
    rec, _, _ = wave.forward()

    # Compute receiver data and full wavefield for the smooth velocity
    rec0, u0, _ = wave.forward(vp=v0, save=True)

    # Objective function value
    F0 = .5 * linalg.norm(rec0.data - rec.data)**2

    # Gradient: <J^T \delta d, dm>
    residual = Receiver(name='rec',
                        grid=wave.model.grid,
                        data=rec0.data - rec.data,
                        time_range=wave.geometry.time_axis,
                        coordinates=wave.geometry.rec_positions)

    gradient, _ = wave.jacobian_adjoint(residual, u0, vp=v0)
    v0 = v0.data
    basic_gradient_test(wave, space_order, v0, v, rec, F0, gradient, dm)
Exemplo n.º 2
0
    def test_gradientJ(self, shape, kernel, space_order):
        """
        This test ensures that the Jacobian computed with devito
        satisfies the Taylor expansion property:
        .. math::
            F(m0 + h dm) = F(m0) + \O(h) \\
            F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\

        with F the Forward modelling operator.
        :param dimensions: size of the domain in all dimensions
        in number of grid points
        :param time_order: order of the time discretization scheme
        :param space_order: order of the spacial discretization scheme
        :return: assertion that the Taylor properties are satisfied
        """
        spacing = tuple(15. for _ in shape)
        wave = setup(shape=shape, spacing=spacing, dtype=np.float64,
                     kernel=kernel, space_order=space_order,
                     tn=1000., nbpml=10+space_order/2)

        m0 = Function(name='m0', grid=wave.model.grid, space_order=space_order)
        smooth(m0, wave.model.m)
        dm = np.float64(wave.model.m.data - m0.data)
        linrec = Receiver(name='rec', grid=wave.model.grid,
                          time_range=wave.receiver.time_range,
                          coordinates=wave.receiver.coordinates.data)

        # Compute receiver data and full wavefield for the smooth velocity
        rec, u0, _ = wave.forward(m=m0, save=False)

        # Gradient: J dm
        Jdm, _, _, _ = wave.born(dm, rec=linrec, m=m0)
        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = m0.data + H[i] * dm
            mloc = Function(name='mloc', grid=wave.model.m.grid, space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(m=mloc)[0]
            delta_d = (d.data - rec.data).reshape(-1)
            # First order error F(m0 + hdm) - F(m0)

            error1[i] = np.linalg.norm(delta_d, 1)
            # Second order term F(m0 + hdm) - F(m0) - J dm
            error2[i] = np.linalg.norm(delta_d - H[i] * Jdm.data.reshape(-1), 1)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0) with slope: %s compared to 1' % (p1[0]))
        info('2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>with slope:'
             ' %s comapred to 2' % (p2[0]))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 3
0
def test_gradientJ(dimensions, time_order, space_order):
    """
    This test ensure that the Jacobian computed with devito
    satisfies the Taylor expansion property:
    .. math::
        F(m0 + h dm) = F(m0) + \O(h) \\
        F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\

    with F the Forward modelling operator.
    :param dimensions: size of the domain in all dimensions
    in number of grid points
    :param time_order: order of the time discretization scheme
    :param space_order: order of the spacial discretization scheme
    :return: assertion that the Taylor properties are satisfied
    """
    wave = setup(dimensions=dimensions, time_order=time_order,
                 space_order=space_order, tn=1000.,
                 nbpml=10+space_order/2)
    m0 = smooth10(wave.model.m.data, wave.model.shape_domain)
    dm = np.float32(wave.model.m.data - m0)
    linrec = Receiver(name='rec', ntime=wave.receiver.nt,
                      coordinates=wave.receiver.coordinates.data)
    # Compute receiver data and full wavefield for the smooth velocity
    rec, u0, _ = wave.forward(m=m0, save=False)
    # Gradient: J dm
    Jdm, _, _, _ = wave.born(dm, rec=linrec, m=m0)
    # FWI Gradient test
    H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
    error1 = np.zeros(7)
    error2 = np.zeros(7)
    for i in range(0, 7):
        # Add the perturbation to the model
        mloc = m0 + H[i] * dm
        # Data for the new model
        d = wave.forward(m=mloc)[0]
        # First order error F(m0 + hdm) - F(m0)
        error1[i] = np.linalg.norm(d.data - rec.data, 1)
        # Second order term F(m0 + hdm) - F(m0) - J dm
        error2[i] = np.linalg.norm(d.data - rec.data - H[i] * Jdm.data, 1)
        # print(F0, .5*linalg.norm(d - rec)**2, error1[i], H[i] *G, error2[i])
        # print('For h = ', H[i], '\nFirst order errors is : ', error1[i],
        #       '\nSecond order errors is ', error2[i])

    hh = np.zeros(7)
    for i in range(0, 7):
        hh[i] = H[i] * H[i]

    # Test slope of the  tests
    p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
    p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
    print(p1)
    print(p2)
    assert np.isclose(p1[0], 1.0, rtol=0.1)
    assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 4
0
    def test_gradientJ(self, shape, kernel, space_order):
        r"""
        This test ensures that the Jacobian computed with devito
        satisfies the Taylor expansion property:
        .. math::
            F(m0 + h dm) = F(m0) + \O(h) \\
            F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\

        with F the Forward modelling operator.
        """
        spacing = tuple(15. for _ in shape)
        wave = setup(shape=shape, spacing=spacing, dtype=np.float64,
                     kernel=kernel, space_order=space_order,
                     tn=1000., nbpml=10+space_order/2)

        m0 = Function(name='m0', grid=wave.model.grid, space_order=space_order)
        smooth(m0, wave.model.m)
        dm = np.float64(wave.model.m.data - m0.data)
        linrec = Receiver(name='rec', grid=wave.model.grid,
                          time_range=wave.geometry.time_axis,
                          coordinates=wave.geometry.rec_positions)

        # Compute receiver data and full wavefield for the smooth velocity
        rec, u0, _ = wave.forward(m=m0, save=False)

        # Gradient: J dm
        Jdm, _, _, _ = wave.born(dm, rec=linrec, m=m0)
        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = m0.data + H[i] * dm
            mloc = Function(name='mloc', grid=wave.model.m.grid, space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(m=mloc)[0]
            delta_d = (d.data - rec.data).reshape(-1)
            # First order error F(m0 + hdm) - F(m0)

            error1[i] = np.linalg.norm(delta_d, 1)
            # Second order term F(m0 + hdm) - F(m0) - J dm
            error2[i] = np.linalg.norm(delta_d - H[i] * Jdm.data.reshape(-1), 1)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0) with slope: %s compared to 1' % (p1[0]))
        info(r'2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>with slope:'
             ' %s comapred to 2' % (p2[0]))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 5
0
    def test_gradient_checkpointing(self, shape, kernel, space_order):
        """
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        :param dimensions: size of the domain in all dimensions
        in number of grid points
        :param time_order: order of the time discretization scheme
        :param space_order: order of the spacial discretization scheme
        :return: assertion that the Taylor properties are satisfied
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape,
                     spacing=spacing,
                     dtype=np.float64,
                     kernel=kernel,
                     space_order=space_order,
                     nbpml=40)

        m0 = Function(name='m0',
                      grid=wave.model.m.grid,
                      space_order=space_order)
        m0.data[:] = smooth10(wave.model.m.data, wave.model.m.shape_domain)

        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(m=m0, save=True)

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec',
                            grid=wave.model.grid,
                            data=rec0.data - rec.data,
                            time_range=rec.time_range,
                            coordinates=rec0.coordinates.data)

        gradient, _ = wave.gradient(residual, u0, m=m0, checkpointing=True)
        gradient2, _ = wave.gradient(residual, u0, m=m0, checkpointing=False)
        assert np.allclose(gradient.data, gradient2.data)
Exemplo n.º 6
0
    def test_gradient_checkpointing(self, dtype, opt, space_order):
        """
        This test ensures that the FWI gradient computed with checkpointing matches
        the one without checkpointing. Note that this test fails with dynamic openmp
        scheduling enabled so this test disables it.
        """
        wave = setup(shape=(70, 80),
                     spacing=(10., 10.),
                     dtype=dtype,
                     kernel='OT2',
                     space_order=space_order,
                     nbl=40,
                     opt=opt)

        v0 = Function(name='v0',
                      grid=wave.model.grid,
                      space_order=space_order,
                      dtype=dtype)
        smooth(v0, wave.model.vp)

        # Compute receiver data for the true velocity
        rec, _, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(vp=v0, save=True)

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec',
                            grid=wave.model.grid,
                            data=rec0.data - rec.data,
                            time_range=wave.geometry.time_axis,
                            coordinates=wave.geometry.rec_positions,
                            dtype=dtype)

        grad = Function(name='grad', grid=wave.model.grid, dtype=dtype)
        gradient, _ = wave.jacobian_adjoint(residual,
                                            u0,
                                            vp=v0,
                                            checkpointing=True,
                                            grad=grad)

        grad = Function(name='grad', grid=wave.model.grid, dtype=dtype)
        gradient2, _ = wave.jacobian_adjoint(residual,
                                             u0,
                                             vp=v0,
                                             checkpointing=False,
                                             grad=grad)

        assert np.allclose(gradient.data, gradient2.data, atol=0, rtol=0)
Exemplo n.º 7
0
    def test_gradient_checkpointing(self, shape, kernel, space_order):
        r"""
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape,
                     spacing=spacing,
                     dtype=np.float64,
                     kernel=kernel,
                     space_order=space_order,
                     nbl=40)

        v0 = Function(name='v0', grid=wave.model.grid, space_order=space_order)
        smooth(v0, wave.model.vp)

        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(vp=v0, save=True)

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec',
                            grid=wave.model.grid,
                            data=rec0.data - rec.data,
                            time_range=wave.geometry.time_axis,
                            coordinates=wave.geometry.rec_positions)

        gradient, _ = wave.jacobian_adjoint(residual,
                                            u0,
                                            vp=v0,
                                            checkpointing=True)
        gradient2, _ = wave.jacobian_adjoint(residual,
                                             u0,
                                             vp=v0,
                                             checkpointing=False)
        assert np.allclose(gradient.data, gradient2.data)
Exemplo n.º 8
0
def test_acoustic(dimensions, time_order, space_order):
    solver = setup(dimensions=dimensions, time_order=time_order,
                   space_order=space_order, nbpml=10+space_order/2)
    srca = PointSource(name='srca', ntime=solver.source.nt,
                       coordinates=solver.source.coordinates.data)

    # Run forward and adjoint operators
    rec, _, _ = solver.forward(save=False)
    solver.adjoint(rec=rec, srca=srca)

    # Actual adjoint test
    term1 = np.dot(srca.data.reshape(-1), solver.source.data)
    term2 = linalg.norm(rec.data) ** 2
    print(term1, term2, ("%12.12f") % (term1 - term2), term1 / term2)
    assert np.isclose(term1 / term2, 1.0, atol=0.001)
Exemplo n.º 9
0
def test_acousticJ(dimensions, space_order):
    solver = setup(dimensions=dimensions,
                   space_order=space_order,
                   nbpml=10+space_order/2)
    initial_vp = np.ones(solver.model.shape_domain) + .5
    m0 = np.float32(initial_vp**-2)
    dm = np.float32(solver.model.m.data - m0)

    # Compute the full wavefield
    _, u0, _ = solver.forward(save=True, m=m0)

    du, _, _, _ = solver.born(dm, m=m0)
    im, _ = solver.gradient(du, u0, m=m0)

    # Actual adjoint test
    term1 = np.dot(im.data.reshape(-1), dm.reshape(-1))
    term2 = linalg.norm(du.data)**2
    print(term1, term2, term1 - term2, term1 / term2)
    assert np.isclose(term1 / term2, 1.0, atol=0.001)
Exemplo n.º 10
0
    def test_gradient_checkpointing(self, shape, kernel, space_order):
        r"""
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape, spacing=spacing, dtype=np.float64,
                     kernel=kernel, space_order=space_order,
                     nbpml=40)

        m0 = Function(name='m0', grid=wave.model.grid, space_order=space_order)
        smooth(m0, wave.model.m)

        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(m=m0, save=True)

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec', grid=wave.model.grid, data=rec0.data - rec.data,
                            time_range=wave.geometry.time_axis,
                            coordinates=wave.geometry.rec_positions)

        gradient, _ = wave.gradient(residual, u0, m=m0, checkpointing=True)
        gradient2, _ = wave.gradient(residual, u0, m=m0, checkpointing=False)
        assert np.allclose(gradient.data, gradient2.data)
Exemplo n.º 11
0
    def test_gradientFWI(self, shape, kernel, space_order, checkpointing):
        """
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        :param dimensions: size of the domain in all dimensions
        in number of grid points
        :param time_order: order of the time discretization scheme
        :param space_order: order of the spacial discretization scheme
        :return: assertion that the Taylor properties are satisfied
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape,
                     spacing=spacing,
                     dtype=np.float64,
                     kernel=kernel,
                     space_order=space_order,
                     nbpml=40)

        m0 = Function(name='m0',
                      grid=wave.model.m.grid,
                      space_order=space_order)
        m0.data[:] = smooth10(wave.model.m.data, wave.model.m.shape_domain)
        dm = np.float32(wave.model.m.data - m0.data)

        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(m=m0, save=True)

        # Objective function value
        F0 = .5 * linalg.norm(rec0.data - rec.data)**2

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec',
                            grid=wave.model.grid,
                            data=rec0.data - rec.data,
                            time_range=rec.time_range,
                            coordinates=rec0.coordinates.data)

        gradient, _ = wave.gradient(residual,
                                    u0,
                                    m=m0,
                                    checkpointing=checkpointing)
        G = np.dot(gradient.data.reshape(-1), dm.reshape(-1))

        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = m0.data + H[i] * dm

            mloc = Function(name='mloc',
                            grid=wave.model.m.grid,
                            space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(m=mloc)[0]
            # First order error Phi(m0+dm) - Phi(m0)
            error1[i] = np.absolute(.5 * linalg.norm(d.data - rec.data)**2 -
                                    F0)
            # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm>
            error2[i] = np.absolute(.5 * linalg.norm(d.data - rec.data)**2 -
                                    F0 - H[i] * G)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0): %s' % (p1))
        info('2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>: %s'
             % (p2))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 12
0
    def test_gradientFWI(self, shape, kernel, space_order, checkpointing):
        r"""
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape,
                     spacing=spacing,
                     dtype=np.float64,
                     kernel=kernel,
                     space_order=space_order,
                     nbl=40)

        v0 = Function(name='v0', grid=wave.model.grid, space_order=space_order)
        smooth(v0, wave.model.vp)
        v = wave.model.vp.data
        dm = np.float64(wave.model.vp.data**(-2) - v0.data**(-2))
        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(vp=v0, save=True)

        # Objective function value
        F0 = .5 * linalg.norm(rec0.data - rec.data)**2

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec',
                            grid=wave.model.grid,
                            data=rec0.data - rec.data,
                            time_range=wave.geometry.time_axis,
                            coordinates=wave.geometry.rec_positions)

        gradient, _ = wave.gradient(residual,
                                    u0,
                                    vp=v0,
                                    checkpointing=checkpointing)
        G = np.dot(gradient.data.reshape(-1), dm.reshape(-1))

        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = np.sqrt(v0.data**2 * v**2 /
                                  ((1 - H[i]) * v**2 + H[i] * v0.data**2))

            vloc = Function(name='vloc',
                            grid=wave.model.grid,
                            space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(vp=vloc)[0]
            # First order error Phi(m0+dm) - Phi(m0)
            F_i = .5 * linalg.norm((d.data - rec.data).reshape(-1))**2
            error1[i] = np.absolute(F_i - F0)
            # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm>
            error2[i] = np.absolute(F_i - F0 - H[i] * G)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0): %s' % (p1))
        info(
            r'2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>: %s'
            % (p2))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 13
0
    def test_gradientJ(self, shape, kernel, space_order):
        r"""
        This test ensures that the Jacobian computed with devito
        satisfies the Taylor expansion property:
        .. math::
            F(m0 + h dm) = F(m0) + \O(h) \\
            F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\

        with F the Forward modelling operator.
        """
        spacing = tuple(15. for _ in shape)
        wave = setup(shape=shape,
                     spacing=spacing,
                     dtype=np.float64,
                     kernel=kernel,
                     space_order=space_order,
                     tn=1000.,
                     nbl=10 + space_order / 2)

        v0 = Function(name='v0', grid=wave.model.grid, space_order=space_order)
        smooth(v0, wave.model.vp)
        v = wave.model.vp.data
        dm = np.float64(wave.model.vp.data**(-2) - v0.data**(-2))
        linrec = Receiver(name='rec',
                          grid=wave.model.grid,
                          time_range=wave.geometry.time_axis,
                          coordinates=wave.geometry.rec_positions)

        # Compute receiver data and full wavefield for the smooth velocity
        rec, u0, _ = wave.forward(vp=v0, save=False)

        # Gradient: J dm
        Jdm, _, _, _ = wave.born(dm, rec=linrec, vp=v0)
        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = np.sqrt(v0.data**2 * v**2 /
                                  ((1 - H[i]) * v**2 + H[i] * v0.data**2))

            vloc = Function(name='vloc',
                            grid=wave.model.grid,
                            space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(vp=vloc)[0]
            delta_d = (d.data - rec.data).reshape(-1)
            # First order error F(m0 + hdm) - F(m0)

            error1[i] = np.linalg.norm(delta_d, 1)
            # Second order term F(m0 + hdm) - F(m0) - J dm
            error2[i] = np.linalg.norm(delta_d - H[i] * Jdm.data.reshape(-1),
                                       1)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0) with slope: %s compared to 1'
             % (p1[0]))
        info(
            r'2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>with slope:'
            ' %s comapred to 2' % (p2[0]))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 14
0
def test_gradientFWI(dimensions, time_order, space_order):
    """
    This test ensure that the FWI gradient computed with devito
    satisfies the Taylor expansion property:
    .. math::
        \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
        \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
        \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

    where
    .. math::
        \nabla \Phi(m0) = <J^T \delta d, dm> \\
        \delta d = F(m0+ h dm) - D \\

    with F the Forward modelling operator.
    :param dimensions: size of the domain in all dimensions
    in number of grid points
    :param time_order: order of the time discretization scheme
    :param space_order: order of the spacial discretization scheme
    :return: assertion that the Taylor properties are satisfied
    """
    wave = setup(dimensions=dimensions, time_order=time_order,
                 space_order=space_order, nbpml=10+space_order/2)
    m0 = smooth10(wave.model.m.data, wave.model.shape_domain)
    dm = np.float32(wave.model.m.data - m0)

    # Compute receiver data for the true velocity
    rec, u, _ = wave.forward()
    # Compute receiver data and full wavefield for the smooth velocity
    rec0, u0, _ = wave.forward(m=m0, save=True)

    # Objective function value
    F0 = .5*linalg.norm(rec0.data - rec.data)**2
    # Gradient: <J^T \delta d, dm>
    residual = Receiver(name='rec', data=rec0.data - rec.data,
                        coordinates=rec0.coordinates.data)
    gradient, _ = wave.gradient(residual, u0, m=m0)
    G = np.dot(gradient.data.reshape(-1), dm.reshape(-1))

    # FWI Gradient test
    H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
    error1 = np.zeros(7)
    error2 = np.zeros(7)
    for i in range(0, 7):
        # Add the perturbation to the model
        mloc = m0 + H[i] * dm
        # Data for the new model
        d = wave.forward(m=mloc)[0]
        # First order error Phi(m0+dm) - Phi(m0)
        error1[i] = np.absolute(.5*linalg.norm(d.data - rec.data)**2 - F0)
        # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm>
        error2[i] = np.absolute(.5*linalg.norm(d.data - rec.data)**2 - F0 - H[i] * G)
        # print(F0, .5*linalg.norm(d - rec)**2, error1[i], H[i] *G, error2[i])
        # print('For h = ', H[i], '\nFirst order errors is : ', error1[i],
        #       '\nSecond order errors is ', error2[i])

    hh = np.zeros(7)
    for i in range(0, 7):
        hh[i] = H[i] * H[i]

    # Test slope of the  tests
    p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
    p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
    print(p1)
    print(p2)
    assert np.isclose(p1[0], 1.0, rtol=0.1)
    assert np.isclose(p2[0], 2.0, rtol=0.1)
Exemplo n.º 15
0
    def test_gradientFWI(self, shape, kernel, space_order, checkpointing):
        r"""
        This test ensures that the FWI gradient computed with devito
        satisfies the Taylor expansion property:
        .. math::
            \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\
            \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\
            \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2

        where
        .. math::
            \nabla \Phi(m0) = <J^T \delta d, dm> \\
            \delta d = F(m0+ h dm) - D \\

        with F the Forward modelling operator.
        """
        spacing = tuple(10. for _ in shape)
        wave = setup(shape=shape, spacing=spacing, dtype=np.float64,
                     kernel=kernel, space_order=space_order,
                     nbpml=40)

        m0 = Function(name='m0', grid=wave.model.grid, space_order=space_order)
        smooth(m0, wave.model.m)
        dm = np.float32(wave.model.m.data[:] - m0.data[:])

        # Compute receiver data for the true velocity
        rec, u, _ = wave.forward()

        # Compute receiver data and full wavefield for the smooth velocity
        rec0, u0, _ = wave.forward(m=m0, save=True)

        # Objective function value
        F0 = .5*linalg.norm(rec0.data - rec.data)**2

        # Gradient: <J^T \delta d, dm>
        residual = Receiver(name='rec', grid=wave.model.grid, data=rec0.data - rec.data,
                            time_range=wave.geometry.time_axis,
                            coordinates=wave.geometry.rec_positions)

        gradient, _ = wave.gradient(residual, u0, m=m0, checkpointing=checkpointing)
        G = np.dot(gradient.data.reshape(-1), dm.reshape(-1))

        # FWI Gradient test
        H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
        error1 = np.zeros(7)
        error2 = np.zeros(7)
        for i in range(0, 7):
            # Add the perturbation to the model
            def initializer(data):
                data[:] = m0.data + H[i] * dm
            mloc = Function(name='mloc', grid=wave.model.m.grid, space_order=space_order,
                            initializer=initializer)
            # Data for the new model
            d = wave.forward(m=mloc)[0]
            # First order error Phi(m0+dm) - Phi(m0)
            F_i = .5*linalg.norm((d.data - rec.data).reshape(-1))**2
            error1[i] = np.absolute(F_i - F0)
            # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm>
            error2[i] = np.absolute(F_i - F0 - H[i] * G)

        # Test slope of the  tests
        p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
        p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
        info('1st order error, Phi(m0+dm)-Phi(m0): %s' % (p1))
        info(r'2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>: %s' % (p2))
        assert np.isclose(p1[0], 1.0, rtol=0.1)
        assert np.isclose(p2[0], 2.0, rtol=0.1)