Esempio n. 1
0
        def run(self, *args, **kwargs):
            clear_cache()

            gflopss, oi, timings, _ = self.func(*args, **kwargs)

            for key in timings.keys():
                self.register(gflopss[key], measure="gflopss", event=key)
                self.register(oi[key], measure="oi", event=key)
                self.register(timings[key], measure="timings", event=key)
Esempio n. 2
0
    def test_fd_space_staggered(self, space_order, stagger):
        """
        This test compares the discrete finite-difference scheme against polynomials
        For a given order p, the finite difference scheme should
        be exact for polynomials of order p
        :param derivative: name of the derivative to be tested
        :param space_order: space order of the finite difference stencil
        """
        clear_cache()
        # dummy axis dimension
        nx = 100
        xx = np.linspace(-1, 1, nx)
        dx = xx[1] - xx[0]
        # Symbolic data
        grid = Grid(shape=(nx,), dtype=np.float32)
        x = grid.dimensions[0]

        # Location of the staggered function
        if stagger == left:
            off = -.5
            side = -x
            xx2 = xx - off * dx
        elif stagger == right:
            off = .5
            side = x
            xx2 = xx[:-1] - off * dx
        else:
            off = 0
            side = NODE
            xx2 = xx

        u = Function(name="u", grid=grid, space_order=space_order, staggered=(side,))
        du = Function(name="du", grid=grid, space_order=space_order)
        # Define polynomial with exact fd
        coeffs = np.ones((space_order-1,), dtype=np.float32)
        polynome = sum([coeffs[i]*x**i for i in range(0, space_order-1)])
        polyvalues = np.array([polynome.subs(x, xi) for xi in xx2], np.float32)
        # Fill original data with the polynomial values
        u.data[:] = polyvalues
        # True derivative of the polynome
        Dpolynome = diff(polynome)
        Dpolyvalues = np.array([Dpolynome.subs(x, xi) for xi in xx], np.float32)
        # FD derivative, symbolic
        u_deriv = generic_derivative(u, deriv_order=1, fd_order=space_order,
                                     dim=x, stagger=stagger)
        # Compute numerical FD
        stencil = Eq(du, u_deriv)
        op = Operator(stencil, subs={x.spacing: dx})
        op.apply()

        # Check exactness of the numerical derivative except inside space_brd
        space_border = space_order
        error = abs(du.data[space_border:-space_border] -
                    Dpolyvalues[space_border:-space_border])

        assert np.isclose(np.mean(error), 0., atol=1e-3)
Esempio n. 3
0
def test_clear_cache(nx=1000, ny=1000):
    grid = Grid(shape=(nx, ny), dtype=np.float64)
    clear_cache()
    cache_size = len(_SymbolCache)

    for i in range(10):
        assert(len(_SymbolCache) == cache_size)

        Function(name='u', grid=grid, space_order=2)

        assert(len(_SymbolCache) == cache_size + 1)

        clear_cache()
Esempio n. 4
0
def bench(problem, **kwargs):
    """
    Complete benchmark with multiple simulation and performance parameters.
    """
    run = tti_run if problem == 'tti' else acoustic_run
    resultsdir = kwargs.pop('resultsdir')
    repeats = kwargs.pop('repeats')

    bench = get_ob_bench(problem, resultsdir, kwargs)
    bench.execute(get_ob_exec(run), warmups=0, repeats=repeats)
    bench.save()

    # Final clean up, just in case the benchmarker is used from external Python modules
    clear_cache()
Esempio n. 5
0
def test_symbol_cache_aliasing_reverse():
    """Test to assert that removing he original u[x, y] instance does
    not impede our alisaing cache or leaks memory.
    """

    # Ensure a clean cache to start with
    clear_cache()
    # FIXME: Currently not working, presumably due to our
    # failure to cache new instances?
    # assert(len(_SymbolCache) == 0)

    # Create first instance of u and fill its data
    grid = Grid(shape=(3, 4))
    u = Function(name='u', grid=grid)
    u.data[:] = 6.
    u_ref = weakref.ref(u.data)

    # Create derivative and delete orignal u[x, y]
    dx = u.dx
    del u
    clear_cache()
    # We still have a references to u
    # FIXME: Unreliable cache sizes
    # assert len(_SymbolCache) == 1
    # Ensure u[x + h, y] still holds valid data
    assert np.allclose(dx.args[0].args[1].data, 6.)

    del dx
    clear_cache()
    # FIXME: Unreliable cache sizes
    # assert len(_SymbolCache) == 0  # We still have a reference to u_h
    assert u_ref() is None
Esempio n. 6
0
def test_operator_leakage_sparse():
    """
    Test to ensure that Operator creation does not cause memory leaks for
    SparseTimeFunctions.
    """
    grid = Grid(shape=(5, 6))
    a = Function(name='a', grid=grid)
    s = SparseTimeFunction(name='s', grid=grid, npoint=1, nt=1)
    w_a = weakref.ref(a)
    w_s = weakref.ref(s)

    # Create operator and delete everything again
    op = Operator(s.interpolate(a))
    w_op = weakref.ref(op)
    del op
    del s
    del a
    clear_cache()

    # Test whether things are still hanging around
    assert w_a() is None
    assert w_s() is None
    assert w_op() is None
Esempio n. 7
0
def test_operator_leakage_function():
    """
    Test to ensure that Operator creation does not cause memory leaks for (Time)Functions.
    """
    grid = Grid(shape=(5, 6))
    f = Function(name='f', grid=grid)
    g = TimeFunction(name='g', grid=grid)

    # Take weakrefs to test whether symbols are dead or alive
    w_f = weakref.ref(f)
    w_g = weakref.ref(g)

    # Create operator and delete everything again
    op = Operator(Eq(f, 2 * g))
    w_op = weakref.ref(op)
    del op
    del f
    del g
    clear_cache()

    # Test whether things are still hanging around
    assert w_f() is None
    assert w_g() is None
    assert w_op() is None
Esempio n. 8
0
def test_symbol_cache_aliasing():
    """Test to assert that our aliasing cache isn't defeated by sympys
    non-aliasing symbol cache.

    For further explanation consider the symbol u[x, y] and it's first
    derivative in x, which includes the symbols u[x, y] and u[x + h, y].
    The two functions are aliased in devito's caching mechanism to allow
    multiple stencil indices pointing at the same data object u, but
    SymPy treats these two instances as separate functions and thus is
    allowed to delete one or the other when the cache is cleared.

    The test below asserts that u[x + h, y] is deleted, the data on u
    is still intact through our own caching mechanism."""

    # Ensure a clean cache to start with
    clear_cache()
    # FIXME: Currently not working, presumably due to our
    # failure to cache new instances?
    # assert(len(_SymbolCache) == 0)

    # Create first instance of u and fill its data
    grid = Grid(shape=(3, 4))
    u = Function(name='u', grid=grid)
    u.data[:] = 6.
    u_ref = weakref.ref(u.data)

    # Create u[x + h, y] and delete it again
    dx = u.dx  # Contains two u symbols: u[x, y] and u[x + h, y]
    del dx
    clear_cache()
    # FIXME: Unreliable cache sizes
    # assert len(_SymbolCache) == 1  # We still have a reference to u
    assert np.allclose(u.data, 6.)  # u.data is alive and well

    # Remove the final instance and ensure u.data got deallocated
    del u
    clear_cache()
    assert u_ref() is None
Esempio n. 9
0
    def test(self, args):

        init_op = tf.global_variables_initializer()
        self.sess.run(init_op)
        if self.load(args.checkpoint_dir):
            print(" [*] Load SUCCESS")
        else:
            print(" [!] Load failed...")

        self.update_devito(velIndex=0)
        batch_idxs = list(range(0, self.shape[0]))
        xsrc = 201  #choice(batch_idxs)

        if not os.path.isfile(
                os.path.join(self.sample_dir, 'LearnedFwdSimPrediction.hdf5')):
            datasetSize = (self.output_c_dim, self.image_size0, self.image_size1, \
                self.virtSteps)
            self.file_prediction = h5py.File(os.path.join(self.sample_dir, \
                'LearnedFwdSimPrediction.hdf5'), 'w-')
            self.dataset_CNN = self.file_prediction.create_dataset(
                "result", datasetSize)
            self.dataset_HF = self.file_prediction.create_dataset(
                "HF", datasetSize)
            self.dataset_LF = self.file_prediction.create_dataset(
                "LF", datasetSize)
        else:
            self.file_prediction = h5py.File(os.path.join(self.sample_dir, \
                'LearnedFwdSimPrediction.hdf5'), 'r+')
            self.dataset_CNN = self.file_prediction["result"]
            self.dataset_HF = self.file_prediction["HF"]
            self.dataset_LF = self.file_prediction["LF"]

        print('Processing shot number: ' + str(xsrc))
        HF_wave_history = []
        CNN_wave_history = []
        CNN_input_history = []
        LF_wave_history = []
        Rec_SNR = []

        self.src.coordinates.data[0, :] = np.array([xsrc*self.spacing[0], \
            2*self.spacing[1]]).astype(np.float32)
        self.rec.coordinates.data[:, 0] = np.linspace(0., self.model.domain_size[0], \
            num=self.num_rec)
        self.rec.coordinates.data[:, 1:] = self.src.coordinates.data[0, 1:]

        self.u_HF.data.fill(0.)
        self.u_LF.data.fill(0.)

        for time_index in range(self.virtSteps):
            clear_cache()

            self.solverLF.forward(m=self.model.m, src=self.src, time_m=time_index*\
                self.virt_timestep, time=(time_index+1)*self.virt_timestep, u=self.u_LF)
            LF_wave_history.append(
                np.transpose(np.array(self.u_LF.data[:, :, :]),
                             (1, 2, 0)).astype(np.float32)[None, :, :, :])

            CNN_wave_history.append(
                self.sess.run(
                    [self.CNN_wave],
                    feed_dict={self.Noisy_wave[0]: LF_wave_history[-1]})[0])

            self.solverHF.forward(m=self.model.m, src=self.src, time_m=time_index*\
                self.virt_timestep, time=(time_index+1)*self.virt_timestep, u=self.u_HF)
            HF_wave_history.append(
                np.transpose(np.array(self.u_HF.data[:, :, :]),
                             (1, 2, 0)).astype(np.float32)[None, :, :, :])

        for iG in range(self.virtSteps):

            self.dataset_CNN[:, :, :, iG] = np.transpose(CNN_wave_history[iG][0][0, :, :, :], \
                (2, 0 , 1))
            self.dataset_HF[:, :, :,
                            iG] = np.transpose(HF_wave_history[iG][0, :, :, :],
                                               (2, 0, 1))
            self.dataset_LF[:, :, :,
                            iG] = np.transpose(LF_wave_history[iG][0, :, :, :],
                                               (2, 0, 1))
        self.file_prediction.close()
def forward(model,
            src_coords,
            rcv_coords,
            wav,
            dt=None,
            space_order=8,
            save=False):
    "Compute forward wavefield u = A(m)^{-1}*f and related quantities (u(xrcv))"

    clear_cache()

    # Setting time sampling
    if dt is None:
        dt = model.critical_dt

    # Physical parameters
    m, rho, damp = model.m, model.rho, model.damp

    # Setting adjoint wavefield
    nt = wav.shape[0]
    u = TimeFunction(name="u",
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order,
                     save=None if not save else nt)

    # Set up PDE expression and rearrange
    ulaplace, rho = laplacian(u, rho)
    stencil = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace)
    expression = [Eq(u.forward, stencil)]

    # Setup adjoint source injected at receiver locations
    src = PointSource(name="src",
                      grid=model.grid,
                      ntime=nt,
                      coordinates=src_coords)
    src.data[:] = wav[:]
    src_term = src.inject(field=u.forward, expr=src * rho * dt**2 / m)
    expression += src_term

    # Setup adjoint wavefield sampling at source locations
    rcv = Receiver(name="rcv",
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rcv_coords)
    adj_rcv = rcv.interpolate(expr=u)
    expression += adj_rcv

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

    # Output
    if save:
        return rcv.data, u
    else:
        return rcv.data, None
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)"

    clear_cache()

    # 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)

    # Normalization constants
    nx = np.float32(model.m.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**np.float32(
        2) * c1 * norm_vPTy2 + alpha * c2 * PTy_dot_r - np.abs(
            alpha) * c3 * norm_y

    # Gradient computation
    if mode == "grad":

        # Physical parameters
        m, rho, damp = model.m, model.rho, model.damp

        # Create the forward wavefield
        u = TimeFunction(name="u",
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)

        # Set up PDE and rearrange
        ulaplace, rho = laplacian(u, rho)
        if weight_fun_pars is None:
            stencil = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m *
                              (ulaplace + 2.0 * c1 / c2 * alpha * vPTy))
        else:
            weight = weight_fun(weight_fun_pars, model, src_coords)
            stencil = damp * (
                2.0 * u - damp * u.backward + dt**2 * rho / m *
                (ulaplace + 2.0 * c1 / c2 * alpha * vPTy / weight**2))
        expression = [Eq(u.forward, stencil)]

        # Setup source with wavelet
        nt = wav.shape[0]
        src = PointSource(name="src",
                          grid=model.grid,
                          ntime=nt,
                          coordinates=src_coords)
        src.data[:] = wav[:]
        src_term = src.inject(field=u.forward,
                              expr=src * rho * dt**2 / m)  #######
        expression += src_term

        # Setup data sampling at receiver locations
        rcv = Receiver(name="rcv",
                       grid=model.grid,
                       ntime=nt,
                       coordinates=rcv_coords)
        rcv_term = rcv.interpolate(expr=u)
        expression += rcv_term

        # Setup gradient wrt m
        gradm = Function(name="gradm", grid=model.grid)
        expression += [Inc(gradm, alpha * c2 * vPTy * u.dt2)]

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

        # Compute gradient wrt y
        if not y_was_None or grad_corr:
            norm_y = npla.norm(y)
            if norm_y == 0:
                grady_data = alpha * c2 * applyfilt(dat - rcv.data, Filter)
            else:
                grady_data = alpha * c2 * applyfilt(
                    dat - rcv.data, Filter) - 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:

            # Compute wavefield vy_ = adjoint(F(m))*grady
            _, _, vy_ = adjoint_y(model,
                                  applyfilt_transp(grady_data, Filter),
                                  src_coords,
                                  rcv_coords,
                                  dt=dt,
                                  space_order=space_order,
                                  save=True)

            # Setup reduced gradient wrt m
            gradm_corr = Function(name="gradmcorr", grid=model.grid)
            expression = [Inc(gradm_corr, vy_ * u0.dt2)]

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

            # 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
Esempio n. 12
0
 def setup_class(cls):
     clear_cache()
def adjoint_y(model,
              y,
              src_coords,
              rcv_coords,
              weight_fun_pars=None,
              dt=None,
              space_order=8,
              save=False):
    "Compute adjoint wavefield v = adjoint(F(m))*y and related quantities (||v||_w, v(xsrc))"

    clear_cache()

    # Setting time sampling
    if dt is None:
        dt = model.critical_dt

    # Physical parameters
    m, rho, damp = model.m, model.rho, model.damp

    # Setting adjoint wavefield
    nt = y.shape[0]
    v = TimeFunction(name="v",
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order,
                     save=None if not save else nt)

    # Set up PDE expression and rearrange
    vlaplace, rho = laplacian(v, rho)
    stencil = damp * (2.0 * v - damp * v.forward + dt**2 * rho / m * vlaplace)
    expression = [Eq(v.backward, stencil)]

    # Setup adjoint source injected at receiver locations
    rcv = Receiver(name="rcv",
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rcv_coords)
    rcv.data[:] = y[:]
    adj_src = rcv.inject(field=v.backward, expr=rcv * rho * dt**2 / m)
    expression += adj_src

    # Setup adjoint wavefield sampling at source locations
    src = PointSource(name="src",
                      grid=model.grid,
                      ntime=nt,
                      coordinates=src_coords)
    adj_rcv = src.interpolate(expr=v)
    expression += adj_rcv

    # Setup ||v||_w computation
    norm_vy2_t = Function(name="nvy2t", grid=model.grid)
    expression += [Inc(norm_vy2_t, Pow(v, 2))]
    i = Dimension(name="i", )
    norm_vy2 = Function(name="nvy2",
                        shape=(1, ),
                        dimensions=(i, ),
                        grid=model.grid)
    if weight_fun_pars is None:
        expression += [Inc(norm_vy2[0], norm_vy2_t)]
    else:
        weight = weight_fun(weight_fun_pars, model, src_coords)
        expression += [Inc(norm_vy2[0], norm_vy2_t / weight**2)]

    # Create operator and run
    subs = model.spacing_map
    subs[v.grid.time_dim.spacing] = dt
    op = Operator(expression,
                  subs=subs,
                  dse="advanced",
                  dle="advanced",
                  name="adjoint_y")
    op()

    # Output
    if save:
        return norm_vy2.data[0], src.data, v
    else:
        return norm_vy2.data[0], src.data, None
Esempio n. 14
0
def forward_freq_modeling(model,
                          src_coords,
                          wavelet,
                          rec_coords,
                          freq,
                          space_order=8,
                          dt=None,
                          factor=None,
                          free_surface=False):
    # Forward modeling with on-the-fly DFT of forward wavefields
    clear_cache()

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

    freq_dim = Dimension(name='freq_dim')
    time = model.grid.time_dim
    if factor is None:
        factor = int(1 / (dt * 4 * np.max(freq)))
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    if factor == 1:
        tsave = time
    else:
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    print("DFT subsampling factor: ", factor)

    # Create wavefields
    nfreq = freq.shape[0]
    u = TimeFunction(name='u',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    f = Function(name='f', dimensions=(freq_dim, ), shape=(nfreq, ))
    f.data[:] = freq[:]
    ufr = Function(name='ufr',
                   dimensions=(freq_dim, ) + u.indices[1:],
                   shape=(nfreq, ) + model.shape_domain)
    ufi = Function(name='ufi',
                   dimensions=(freq_dim, ) + u.indices[1:],
                   shape=(nfreq, ) + model.shape_domain)

    ulaplace, rho = acoustic_laplacian(u, rho)

    # Set up PDE and rearrange
    stencil = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace)
    expression = [Eq(u.forward, stencil)]
    expression += [
        Eq(ufr, ufr + factor * u * cos(2 * np.pi * f * tsave * factor * dt))
    ]
    expression += [
        Eq(ufi, ufi - factor * u * sin(2 * np.pi * f * tsave * factor * dt))
    ]

    # Source symbol with input 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 * dt**2 / m)

    # Data is sampled at receiver locations
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    rec_term = rec.interpolate(expr=u)

    # Create operator and run

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

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

    return rec.data, ufr, ufi
Esempio n. 15
0
def fwi_gradient(vp_in):
    # AUTO
    grad = Function(name="grad", grid=model.grid)
    residual = Receiver(name='rec',
                        grid=model.grid,
                        time_range=geometry.time_axis,
                        coordinates=geometry.rec_positions)
    objective = 0.
    u0 = TimeFunction(name='u',
                      grid=model.grid,
                      time_order=2,
                      space_order=4,
                      save=geometry.nt)

    # MANUAL
    grad_manual = Function(name="grad", grid=model.grid)
    residual_man = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates)
    objective_manual = 0.
    u0_man = TimeFunction(name='u',
                          grid=model.grid,
                          time_order=2,
                          space_order=4,
                          save=nt)
    for i in range(9):
        # AUTO
        clear_cache()
        geometry.src_positions[0, :] = source_locations[i, :]
        true_d, _, _ = solver.forward(vp=model.vp)
        u0.data.fill(0.)
        smooth_d, _, _ = solver.forward(vp=vp_in, save=True, u=u0)
        residual.data[:] = smooth_d.data[:] - true_d.data[:]
        objective += .5 * np.linalg.norm(residual.data.flatten())**2
        solver.gradient(rec=residual, u=u0, vp=vp_in, grad=grad)

        # MANUAL
        # source
        src_true = RickerSource(name='src',
                                grid=model.grid,
                                time_range=time_axis,
                                coordinates=source_locations[i, :],
                                npoint=1,
                                f0=f0)
        src_term = src_true.inject(
            field=u.forward,
            expr=src_true * model.grid.stepping_dim.spacing**2 / model.m)

        # receiver
        rec_true = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates,
                            npoint=nreceivers)
        rec_term = rec_true.interpolate(expr=u)

        # operator
        op_fwd = Operator(eqn + src_term + rec_term,
                          subs=model.spacing_map,
                          name='Forward')
        op_fwd.apply(src=src_true,
                     rec=rec_true,
                     u=u0_man,
                     vp=model.vp,
                     dt=model.critical_dt)

        u0_man.data.fill(0.)
        rec_smooth = Receiver(name='rec',
                              grid=model.grid,
                              time_range=time_axis,
                              coordinates=rec_coordinates,
                              npoint=nreceivers)
        op_fwd.apply(src=src_true,
                     rec=rec_smooth,
                     u=u0_man,
                     vp=vp_in,
                     dt=model.critical_dt)

        # back-receiver
        rec_back = Receiver(name='rec',
                            grid=model.grid,
                            time_range=time_axis,
                            coordinates=rec_coordinates,
                            npoint=nreceivers)
        rec_back_term = rec_back.inject(
            field=v.backward,
            expr=rec_back * model.grid.stepping_dim.spacing**2 / model.m)

        # gradient
        gradient_update = Inc(grad_manual, -u.dt2 * v)
        op_grad = Operator(eqn_back + rec_back_term + [gradient_update],
                           subs=model.spacing_map,
                           name='Gradient')
        residual_man.data[:] = rec_smooth.data[:] - rec_true.data[:]
        objective_manual += .5 * np.linalg.norm(residual_man.data.flatten())**2
        op_grad.apply(rec=residual_man,
                      u=u0_man,
                      vp=vp_in,
                      dt=model.critical_dt,
                      grad=grad_manual)

        # sanity-check -> expect for 0!
        # plot_shotrecord(true_d.data[:] - rec_true.data[:], model, t0, tn)
        # plot_shotrecord(smooth_d.data[:] - rec_smooth.data[:], model, t0, tn)
    return objective, -grad.data, objective_manual, -grad_manual.data
Esempio n. 16
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
Esempio n. 17
0
def forward_freq_modeling(model,
                          src_coords,
                          wavelet,
                          rec_coords,
                          freq,
                          space_order=8,
                          nb=40,
                          dt=None,
                          factor=None):
    # Forward modeling with on-the-fly DFT of forward wavefields
    clear_cache()

    # Parameters
    nt = wavelet.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, damp = model.m, model.damp
    freq_dim = Dimension(name='freq_dim')
    time = model.grid.time_dim
    if factor is None:
        factor = int(1 / (dt * 4 * np.max(freq)))
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    if factor == 1:
        tsave = time
    else:
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    print("DFT subsampling factor: ", factor)

    # Create wavefields
    nfreq = freq.shape[0]
    u = TimeFunction(name='u',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    f = Function(name='f', dimensions=(freq_dim, ), shape=(nfreq, ))
    f.data[:] = freq[:]
    ufr = Function(name='ufr',
                   dimensions=(freq_dim, ) + u.indices[1:],
                   shape=(nfreq, ) + model.shape_domain)
    ufi = Function(name='ufi',
                   dimensions=(freq_dim, ) + u.indices[1:],
                   shape=(nfreq, ) + model.shape_domain)

    # Set up PDE and rearrange
    eqn = m * u.dt2 - u.laplace + damp * u.dt
    stencil = solve(eqn, u.forward, simplify=False, rational=False)[0]
    expression = [Eq(u.forward, stencil)]
    expression += [
        Eq(ufr, ufr + factor * u * cos(2 * np.pi * f * tsave * factor * dt))
    ]
    expression += [
        Eq(ufi, ufi - factor * u * sin(2 * np.pi * f * tsave * factor * dt))
    ]

    # Source symbol with input 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)

    # Data is sampled at receiver locations
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    rec_term = rec.interpolate(expr=u, offset=model.nbpml)

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

    return rec.data, ufr, ufi
Esempio n. 18
0
 def setup_method(self, method):
     # Some of these tests are memory intensive as it requires to store the entire
     # forward wavefield to compute the gradient (nx.ny.nz.nt). We therefore call
     # 'clear_cache()' to release any remaining memory from the previous tests or
     # previous instances (different parametrizations) of these tests
     clear_cache()
Esempio n. 19
0
def adjoint_modeling(model,
                     src_coords,
                     rec_coords,
                     rec_data,
                     space_order=8,
                     nb=40,
                     free_surface=False,
                     dt=None):
    clear_cache()

    # If wavelet is file, read it
    if isinstance(rec_data, str):
        rec_data = np.load(rec_data)

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

    # Create the adjoint wavefield
    if src_coords is not None:
        v = TimeFunction(name="v",
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)
    else:
        v = TimeFunction(name="v",
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)

    # Set up PDE and rearrange
    vlaplace, rho = acoustic_laplacian(v, rho)
    H = symbols('H')
    eqn = m / rho * v.dt2 - H - damp * v.dt

    # Input data is wavefield
    if isinstance(rec_data, TimeFunction):
        wf_rec = TimeFunction(name='wf_rec',
                              grid=model.grid,
                              time_order=2,
                              space_order=space_order,
                              save=nt)
        wf_rec._data = rec_data._data
        eqn -= wf_rec

    stencil = solve(eqn, v.backward, simplify=False, rational=False)[0]
    expression = [Eq(v.backward, stencil.subs({H: vlaplace}))]

    # Free surface
    if free_surface is True:
        fs = DefaultDimension(name="fs", default_value=int(space_order / 2))
        expression += [
            Eq(v.forward.subs({v.indices[-1]: model.nbpml - fs - 1}),
               -v.forward.subs({v.indices[-1]: model.nbpml + fs + 1}))
        ]

    # Adjoint source is injected at receiver locations
    if rec_coords is not None:
        rec = Receiver(name='rec',
                       grid=model.grid,
                       ntime=nt,
                       coordinates=rec_coords)
        rec.data[:] = rec_data[:]
        adj_src = rec.inject(field=v.backward,
                             offset=model.nbpml,
                             expr=rec * rho * dt**2 / m)
        expression += adj_src

    # Data is sampled at source locations
    if src_coords is not None:
        src = PointSource(name='src',
                          grid=model.grid,
                          ntime=nt,
                          coordinates=src_coords)
        adj_rec = src.interpolate(expr=v, offset=model.nbpml)
        expression += adj_rec

    # Create operator and run
    set_log_level('ERROR')
    subs = model.spacing_map
    subs[v.grid.time_dim.spacing] = dt
    op = Operator(expression,
                  subs=subs,
                  dse='advanced',
                  dle='advanced',
                  name="Backward%s" % randint(1e5))
    op()
    if src_coords is None:
        return v
    else:
        return src.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
def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, 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)

    # Create operator and run

    expression = expression_u + src_term + expression_du + 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)

    subs = model.spacing_map
    subs[u.grid.time_dim.spacing] = dt
    op = Operator(expression, subs=subs, dse='advanced', dle='advanced')
    cf = op.cfunction
    summary = op.apply()

    return rec.data, summary
Esempio n. 22
0
def gradient(model,
             save=False,
             space_order=12,
             sub=None,
             fs=False,
             isic=False):
    clear_cache()

    # Parameters
    s = model.grid.stepping_dim.spacing
    nt = 10
    time_range = TimeAxis(start=0, num=nt, step=1)
    m, damp, epsilon, delta, theta, phi, rho = (model.m, model.damp,
                                                model.epsilon, model.delta,
                                                model.theta, model.phi,
                                                model.rho)
    m = m * rho
    # Tilt and azymuth setup
    ang0 = cos(theta)
    ang1 = sin(theta)
    ang2 = cos(phi)
    ang3 = sin(phi)

    # Create the forward wavefield
    f_h = f_t = 1
    if sub is not None and (sub[0] > 1 or sub[1] > 1):
        f_h = sub[1]
        f_t = sub[0]
        u, v = subsampled(model,
                          nt,
                          space_order,
                          t_sub=sub[0],
                          space_sub=sub[1])
    else:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)
        v = TimeFunction(name='v',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)
    p = TimeFunction(name='p',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    q = TimeFunction(name='q',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)

    H0, H1 = kernel_zhang_fwd(p, q, ang0, ang1, ang2, ang3, epsilon, delta,
                              rho)

    # Stencils
    s = model.grid.stepping_dim.spacing
    stencilp = damp * (2 * p - damp * p.forward + s**2 / m * H0)
    stencilr = damp * (2 * q - damp * q.forward + s**2 / m * H1)
    first_stencil = Eq(p.backward, stencilp)
    second_stencil = Eq(q.backward, stencilr)
    expression = [first_stencil, second_stencil]

    # Source symbol with input wavelet
    src = Receiver(name='src',
                   grid=model.grid,
                   time_range=time_range,
                   npoint=1)
    src_term = src.inject(field=p.backward, expr=src.dt * s**2 / m)
    src_term += src.inject(field=q.backward, expr=src.dt * s**2 / m)
    expression += src_term

    if fs:
        expression += freesurface(p, model.nbpml, forward=False)
        expression += freesurface(q, model.nbpml, forward=False)
    grad = Function(name="grad", grid=u.grid, space_order=0)
    expression += [
        Inc(grad,
            rho * f_t * f_h * imaging_condition(model, u, v, p, q, isic=isic))
    ]

    op = Operator(expression,
                  subs=model.spacing_map,
                  dse='aggressive',
                  dle='advanced',
                  name="gradient")

    return op
Esempio n. 23
0
 def setup_method(self, method):
     # Some of these tests are memory intensive as it requires to store the entire
     # forward wavefield to compute the gradient (nx.ny.nz.nt). We therefore call
     # 'clear_cache()' to release any remaining memory from the previous tests or
     # previous instances (different parametrizations) of these tests
     clear_cache()
Esempio n. 24
0
# Create image symbol and instantiate the previously defined imaging operator
image = Function(name='image', grid=model.grid)
op_imaging = ImagingOperator(model, image)

# Create a wavefield for saving to avoid memory overload
u0 = TimeFunction(name='u',
                  grid=model0.grid,
                  time_order=2,
                  space_order=4,
                  save=geometry.nt)

for i in range(nshots):
    # Important: We force previous wavefields to be destroyed,
    # so that we may reuse the memory.
    clear_cache()

    print('Imaging source %d out of %d' % (i + 1, nshots))

    # Update source location
    geometry.src_positions[0, :] = source_locations[i, :]

    # Generate synthetic data from true model
    true_d, _, _ = solver.forward(vp=model.vp)

    # Compute smooth data and full forward wavefield u0
    u0.data.fill(0.)
    smooth_d, _, _ = solver.forward(vp=model0.vp, save=True, u=u0)

    # Compute gradient from the data residual
    v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=4)
def adjoint_freq_born(model, rec_coords, rec_data, freq, ufr, ufi, space_order=8, dt=None, isic=False, factor=None,
                      free_surface=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
    nfreq = ufr.shape[0]
    time = model.grid.time_dim
    if factor is None:
        factor = int(1 / (dt*4*np.max(freq)))
        tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor)
    if factor==1:
        tsave = time
    else:
        tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor)
    dtf = factor * dt
    ntf = factor / nt
    print("DFT subsampling factor: ", factor)

    # Create the forward and adjoint wavefield
    v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order)
    f = Function(name='f', dimensions=(ufr.indices[0],), shape=(nfreq,))
    f.data[:] = freq[:]
    gradient = Function(name="gradient", grid=model.grid)
    vlaplace, rho = acoustic_laplacian(v, rho)

    # Set up PDE and rearrange
    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 = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords)
    rec.data[:] = rec_data[:]
    adj_src = rec.inject(field=v.backward, expr=rec * dt**2 / m)

    # Gradient update
    if isic is True:
        if len(model.shape) == 2:
            gradient_update = [Eq(gradient, gradient + (2*np.pi*f)**2*ntf*(ufr*cos(2*np.pi*f*tsave*dtf) - ufi*sin(2*np.pi*f*tsave*dtf))*v*model.m -
                                                       (ufr.dx*cos(2*np.pi*f*tsave*dtf) - ufi.dx*sin(2*np.pi*f*tsave*dtf))*v.dx*ntf -
                                                       (ufr.dy*cos(2*np.pi*f*tsave*dtf) - ufi.dy*sin(2*np.pi*f*tsave*dtf))*v.dy*ntf)]
        else:
            gradient_update = [Eq(gradient, gradient + (2*np.pi*f)**2*ntf*(ufr*cos(2*np.pi*f*tsave*dtf) - ufi*sin(2*np.pi*f*tsave*dtf))*v*model.m -
                                                       (ufr.dx*cos(2*np.pi*f*tsave*dtf) - ufi.dx*sin(2*np.pi*f*tsave*dtf))*v.dx*ntf -
                                                       (ufr.dy*cos(2*np.pi*f*tsave*dtf) - ufi.dy*sin(2*np.pi*f*tsave*dtf))*v.dy*ntf -
                                                       (ufr.dz*cos(2*np.pi*f*tsave*dtf) - ufi.dz*sin(2*np.pi*f*tsave*dtf))*v.dz*ntf)]
    else:
        gradient_update = [Eq(gradient, gradient + (2*np.pi*f)**2/nt*(ufr*cos(2*np.pi*f*tsave*dtf) - ufi*sin(2*np.pi*f*tsave*dtf))*v)]

    # 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[v.grid.time_dim.spacing] = dt
    op = Operator(expression, subs=subs, dse='advanced', dle='advanced')
    cf = op.cfunction
    op()
    clear_cache()
    return gradient.data
Esempio n. 26
0
def adjoint_modeling(model,
                     src_coords,
                     rec_coords,
                     rec_data,
                     space_order=8,
                     free_surface=False,
                     dt=None):
    clear_cache()

    # If wavelet is file, read it
    if isinstance(rec_data, str):
        rec_data = np.load(rec_data)

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

    # Create the adjoint wavefield
    if src_coords is not None:
        v = TimeFunction(name="v",
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)
    else:
        v = TimeFunction(name="v",
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)

    # Set up PDE and rearrange
    vlaplace, rho = acoustic_laplacian(v, rho)

    # Input data is wavefield
    full_q = 0
    if isinstance(rec_data, TimeFunction):
        wf_rec = TimeFunction(name='wf_rec',
                              grid=model.grid,
                              time_order=2,
                              space_order=space_order,
                              save=nt)
        wf_rec._data = rec_data._data
        full_q = wf_rec

    stencil = damp * (2.0 * v - damp * v.forward + dt**2 * rho / m *
                      (vlaplace + full_q))
    expression = [Eq(v.backward, stencil)]

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

    # Adjoint source is injected at receiver locations
    if rec_coords is not None:
        rec = Receiver(name='rec',
                       grid=model.grid,
                       ntime=nt,
                       coordinates=rec_coords)
        rec.data[:] = rec_data[:]
        adj_src = rec.inject(field=v.backward, expr=rec * rho * dt**2 / m)
        expression += adj_src

    # Data is sampled at source locations
    if src_coords is not None:
        src = PointSource(name='src',
                          grid=model.grid,
                          ntime=nt,
                          coordinates=src_coords)
        adj_rec = src.interpolate(expr=v)
        expression += adj_rec

    # Create operator and run

    subs = model.spacing_map
    subs[v.grid.time_dim.spacing] = dt
    op = Operator(expression, subs=subs, dse='advanced', dle='advanced')
    cf = op.cfunction
    summary = op.apply()
    if src_coords is None:
        return v, summary
    else:
        return src.data, summary
Esempio n. 27
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
Esempio n. 28
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
Esempio n. 29
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
Esempio n. 30
0
def forward_modeling(model,
                     src_coords,
                     wavelet,
                     rec_coords,
                     save=False,
                     space_order=8,
                     nb=40,
                     op_return=False,
                     dt=None):
    clear_cache()

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

    # Create the forward wavefield
    if save is False:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)
    else:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)

    # Set up PDE and rearrange
    eqn = m * u.dt2 - u.laplace + damp * u.dt
    stencil = solve(eqn, u.forward)[0]
    expression = [Eq(u.forward, stencil)]

    # Source symbol with input 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)

    # Data is sampled at receiver locations
    rec = Receiver(name='rec',
                   grid=model.grid,
                   ntime=nt,
                   coordinates=rec_coords)
    rec_term = rec.interpolate(expr=u, offset=model.nbpml)

    # Create operator and run
    set_log_level('ERROR')
    expression += src_term + rec_term
    op = Operator(expression,
                  subs=model.spacing_map,
                  dse='advanced',
                  dle='advanced',
                  name="Forward%s" % randint(1e5))
    if op_return is False:
        op(dt=dt)
        return rec.data, u
    else:
        return op
Esempio n. 31
0
def forward_modeling(model,
                     src_coords,
                     wavelet,
                     rec_coords,
                     save=False,
                     space_order=8,
                     nb=40,
                     free_surface=False,
                     op_return=False,
                     dt=None):
    clear_cache()

    # If wavelet is file, read it
    if isinstance(wavelet, str):
        wavelet = np.load(wavelet)

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

    # Create the forward wavefield
    if save is False and rec_coords is not None:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order)
    else:
        u = TimeFunction(name='u',
                         grid=model.grid,
                         time_order=2,
                         space_order=space_order,
                         save=nt)

    # Set up PDE and rearrange
    ulaplace, rho = acoustic_laplacian(u, rho)
    H = symbols('H')
    eqn = m / rho * u.dt2 - H + damp * u.dt

    # Input source is wavefield
    if isinstance(wavelet, TimeFunction):
        wf_src = TimeFunction(name='wf_src',
                              grid=model.grid,
                              time_order=2,
                              space_order=space_order,
                              save=nt)
        wf_src._data = wavelet._data
        eqn -= wf_src

    # Rearrange expression
    stencil = solve(eqn, u.forward, simplify=False, rational=False)[0]
    expression = [Eq(u.forward, stencil.subs({H: ulaplace}))]

    # Free surface
    if free_surface is True:
        fs = DefaultDimension(name="fs", default_value=int(space_order / 2))
        expression += [
            Eq(u.forward.subs({u.indices[-1]: model.nbpml - fs - 1}),
               -u.forward.subs({u.indices[-1]: model.nbpml + fs + 1}))
        ]

    # Source symbol with input wavelet
    if src_coords is not None:
        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)
        expression += src_term

    # Data is sampled at receiver locations
    if rec_coords is not None:
        rec = Receiver(name='rec',
                       grid=model.grid,
                       ntime=nt,
                       coordinates=rec_coords)
        rec_term = rec.interpolate(expr=u, offset=model.nbpml)
        expression += rec_term

    # 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',
                  name="Forward%s" % randint(1e5))
    if op_return is False:
        op()
        if rec_coords is None:
            return u
        else:
            return rec.data, u
    else:
        return op
Esempio n. 32
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):
    clear_cache()

    # Parameters
    nt = rec_data.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, damp = model.m, 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
    eqn = m * v.dt2 - v.laplace - damp * v.dt
    stencil = solve(eqn, v.backward)[0]
    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,
                           offset=model.nbpml,
                           expr=rec_g * 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 - u * v.dt2)
                           ]  # zero-lag cross-correlation imaging condition
    else:
        # linearized inverse scattering imaging condition (Op't Root et al. 2010; Whitmore and Crawley 2012)
        if len(model.shape) == 2:
            gradient_update = [
                Eq(gradient,
                   gradient - (u * v.dt2 * m + u.dx * v.dx + u.dy * v.dy))
            ]
        else:
            gradient_update = [
                Eq(
                    gradient, gradient -
                    (u * v.dt2 * m + u.dx * v.dx + u.dy * v.dy + u.dz * v.dz))
            ]

    # Create operator and run
    set_log_level('ERROR')
    expression += adj_src + gradient_update
    op = Operator(expression,
                  subs=model.spacing_map,
                  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])
        n_checkpoints = None
        wrap_fw = CheckpointOperator(op_forward,
                                     u=u,
                                     m=model.m.data,
                                     rec=rec,
                                     dt=dt)
        wrap_rev = CheckpointOperator(op,
                                      u=u,
                                      v=v,
                                      m=model.m.data,
                                      rec_g=rec_g,
                                      dt=dt)

        # 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.linalg.norm(rec_g.data[:])**2
        wrp.apply_reverse()
    else:
        op(dt=dt)
    clear_cache()

    if op_forward is not None and is_residual is not True:
        return fval, gradient.data
    else:
        return gradient.data
Esempio n. 33
0
def adjoint_freq_born(model,
                      rec_coords,
                      rec_data,
                      freq,
                      ufr,
                      ufi,
                      space_order=8,
                      nb=40,
                      dt=None,
                      isic=False,
                      factor=None):
    clear_cache()

    # Parameters
    nt = rec_data.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, damp = model.m, model.damp
    nfreq = ufr.shape[0]
    time = model.grid.time_dim
    if factor is None:
        factor = int(1 / (dt * 4 * np.max(freq)))
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    if factor == 1:
        tsave = time
    else:
        tsave = ConditionalDimension(name='tsave',
                                     parent=model.grid.time_dim,
                                     factor=factor)
    dtf = factor * dt
    ntf = factor / nt
    print("DFT subsampling factor: ", factor)

    # Create the forward and adjoint wavefield
    v = TimeFunction(name='v',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    f = Function(name='f', dimensions=(ufr.indices[0], ), shape=(nfreq, ))
    f.data[:] = freq[:]
    gradient = Function(name="gradient", grid=model.grid)

    # Set up PDE and rearrange
    eqn = m * v.dt2 - v.laplace - damp * v.dt
    stencil = solve(eqn, v.backward, simplify=False, rational=False)[0]
    expression = [Eq(v.backward, stencil)]

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

    # Gradient update
    if isic is True:
        if len(model.shape) == 2:
            gradient_update = [
                Eq(
                    gradient, gradient + (2 * np.pi * f)**2 * ntf *
                    (ufr * cos(2 * np.pi * f * tsave * dtf) -
                     ufi * sin(2 * np.pi * f * tsave * dtf)) * v * model.m -
                    (ufr.dx * cos(2 * np.pi * f * tsave * dtf) -
                     ufi.dx * sin(2 * np.pi * f * tsave * dtf)) * v.dx * ntf -
                    (ufr.dy * cos(2 * np.pi * f * tsave * dtf) -
                     ufi.dy * sin(2 * np.pi * f * tsave * dtf)) * v.dy * ntf)
            ]
        else:
            gradient_update = [
                Eq(
                    gradient, gradient + (2 * np.pi * f)**2 * ntf *
                    (ufr * cos(2 * np.pi * f * tsave * dtf) -
                     ufi * sin(2 * np.pi * f * tsave * dtf)) * v * model.m -
                    (ufr.dx * cos(2 * np.pi * f * tsave * dtf) -
                     ufi.dx * sin(2 * np.pi * f * tsave * dtf)) * v.dx * ntf -
                    (ufr.dy * cos(2 * np.pi * f * tsave * dtf) -
                     ufi.dy * sin(2 * np.pi * f * tsave * dtf)) * v.dy * ntf -
                    (ufr.dz * cos(2 * np.pi * f * tsave * dtf) -
                     ufi.dz * sin(2 * np.pi * f * tsave * dtf)) * v.dz * ntf)
            ]
    else:
        gradient_update = [
            Eq(
                gradient, gradient + (2 * np.pi * f)**2 / nt *
                (ufr * cos(2 * np.pi * f * tsave * dtf) -
                 ufi * sin(2 * np.pi * f * tsave * dtf)) * v)
        ]

    # Create operator and run
    set_log_level('ERROR')
    expression += adj_src + gradient_update
    subs = model.spacing_map
    subs[v.grid.time_dim.spacing] = dt
    op = Operator(expression,
                  subs=subs,
                  dse='advanced',
                  dle='advanced',
                  name="Gradient%s" % randint(1e5))
    op()
    clear_cache()
    return gradient.data
Esempio n. 34
0
def adjoint_freq_born(model,
                      rec_coords,
                      rec_data,
                      freq,
                      ufr,
                      ufi,
                      space_order=8,
                      nb=40,
                      dt=None):
    clear_cache()

    # Parameters
    nt = rec_data.shape[0]
    if dt is None:
        dt = model.critical_dt
    m, damp = model.m, model.damp
    nfreq = ufr.shape[0]
    time = model.grid.time_dim

    # Create the forward and adjoint wavefield
    v = TimeFunction(name='v',
                     grid=model.grid,
                     time_order=2,
                     space_order=space_order)
    f = Function(name='f', dimensions=(ufr.indices[0], ), shape=(nfreq, ))
    f.data[:] = freq[:]
    gradient = Function(name="gradient", grid=model.grid)

    # Set up PDE and rearrange
    eqn = m * v.dt2 - v.laplace - damp * v.dt
    stencil = solve(eqn, v.backward)[0]
    expression = [Eq(v.backward, stencil)]

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

    # Gradient update
    gradient_update = [
        Eq(
            gradient, gradient + (2 * np.pi * f)**2 / nt *
            (ufr * cos(2 * np.pi * f * time * dt) -
             ufi * sin(2 * np.pi * f * time * dt)) * v)
    ]

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

    return gradient.data
Esempio n. 35
0
 def setup_class(cls):
     clear_cache()
Esempio n. 36
0
 def setup_method(self, method):
     clear_cache()
Esempio n. 37
0
 def setup_method(self, method):
     clear_cache()
def forward_modeling(model, src_coords, wavelet, rec_coords, save=False, space_order=8, nb=40, free_surface=False, op_return=False, u_return=False, dt=None, tsub_factor=1):
    clear_cache()

    # If wavelet is file, read it
    if isinstance(wavelet, str):
        wavelet = np.load(wavelet)

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

    # Create the forward wavefield
    if save is False and rec_coords is not None:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order)
        eqsave = []
    elif save is True and tsub_factor > 1:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order)
        time_subsampled = ConditionalDimension(name='t_sub', parent=u.grid.time_dim, factor=tsub_factor)
        nsave = (nt-1)//tsub_factor + 2
        usave = TimeFunction(name='us', grid=model.grid, time_order=2, space_order=space_order, time_dim=time_subsampled, save=nsave)
        eqsave = [Eq(usave.forward, u.forward)]
    else:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order, save=nt)
        eqsave = []

    # Set up PDE
    ulaplace, rho = acoustic_laplacian(u, rho)
    stencil = damp * ( 2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace)

    # Input source is wavefield
    if isinstance(wavelet, TimeFunction):
        wf_src = TimeFunction(name='wf_src', grid=model.grid, time_order=2, space_order=space_order, save=nt)
        wf_src._data = wavelet._data
        stencil -= wf_src

    # Rearrange expression
    expression = [Eq(u.forward, stencil)]

     # Data is sampled at receiver locations
    if rec_coords is not None:
        rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords)
        rec_term = rec.interpolate(expr=u)
        expression += rec_term

    # Create operator and run
    if save:
        expression += eqsave

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

    # Source symbol with input wavelet
    if src_coords is not None:
        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)
        expression += src_term

    # 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')

    # Return data and wavefields
    if op_return is False:
        op()
        if save is True and tsub_factor > 1:
            if rec_coords is None:
                return usave
            else:
                return rec.data, usave
        else:
            if rec_coords is None:
                return u
            else:
                return rec.data, u

    # For optimal checkpointing, return operator only
    else:
        return op
Esempio n. 39
0
    def test_fd_space_staggered(self, space_order, stagger):
        """
        This test compares the discrete finite-difference scheme against polynomials
        For a given order p, the finite difference scheme should
        be exact for polynomials of order p
        """
        clear_cache()
        # dummy axis dimension
        nx = 100
        xx = np.linspace(-1, 1, nx)
        dx = xx[1] - xx[0]
        # Symbolic data
        grid = Grid(shape=(nx, ), dtype=np.float32)
        x = grid.dimensions[0]

        # Location of the staggered function
        if stagger == left:
            off = -.5
            side = -x
            xx2 = xx - off * dx
        elif stagger == right:
            off = .5
            side = x
            xx2 = xx[:-1] - off * dx
        else:
            off = 0
            side = NODE
            xx2 = xx

        u = Function(name="u",
                     grid=grid,
                     space_order=space_order,
                     staggered=(side, ))
        du = Function(name="du", grid=grid, space_order=space_order)
        # Define polynomial with exact fd
        coeffs = np.ones((space_order - 1, ), dtype=np.float32)
        polynome = sum([coeffs[i] * x**i for i in range(0, space_order - 1)])
        polyvalues = np.array([polynome.subs(x, xi) for xi in xx2], np.float32)
        # Fill original data with the polynomial values
        u.data[:] = polyvalues
        # True derivative of the polynome
        Dpolynome = diff(polynome)
        Dpolyvalues = np.array([Dpolynome.subs(x, xi) for xi in xx],
                               np.float32)
        # FD derivative, symbolic
        u_deriv = generic_derivative(u,
                                     deriv_order=1,
                                     fd_order=space_order,
                                     dim=x,
                                     stagger=stagger)
        # Compute numerical FD
        stencil = Eq(du, u_deriv)
        op = Operator(stencil, subs={x.spacing: dx})
        op.apply()

        # Check exactness of the numerical derivative except inside space_brd
        space_border = space_order
        error = abs(du.data[space_border:-space_border] -
                    Dpolyvalues[space_border:-space_border])

        assert np.isclose(np.mean(error), 0., atol=1e-3)
Esempio n. 40
0
def forward(model, save=False, space_order=12, sub=None, norec=False, fs=False):
    clear_cache()

    # Parameters
    s = model.grid.stepping_dim.spacing
    nt = 10
    time_range = TimeAxis(start=0, num=nt, step=1)
    m, damp, epsilon, delta, theta, phi, rho = (model.m, model.damp, model.epsilon,
                                                model.delta, model.theta, model.phi,
                                                model.rho)
    m = m * rho
    # Tilt and azymuth setup
    ang0 = cos(theta)
    ang1 = sin(theta)
    ang2 = cos(phi)
    ang3 = sin(phi)

    # Create the forward wavefield
    if sub is not None and (sub[0] > 1 or sub[1] > 1):
        usave, vsave = subsampled(model, nt, space_order, t_sub=sub[0], space_sub=sub[1])
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order)
        v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order)
        eq_save = [Eq(usave, u), Eq(vsave, v)]
    elif save:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order,
                         save=nt)
        v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order,
                         save=nt)
        eq_save = []
    else:
        u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order)
        v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order)
        eq_save = []

    H0, H1 = kernel_zhang_fwd(u, v, ang0, ang1, ang2, ang3, epsilon, delta, rho)

    # Stencils
    s = model.grid.stepping_dim.spacing
    stencilp = damp * (2 * u - damp * u.backward + s**2 / m * H0)
    stencilr = damp * (2 * v - damp * v.backward + s**2 / m * H1)
    first_stencil = Eq(u.forward, stencilp)
    second_stencil = Eq(v.forward, stencilr)
    expression = [first_stencil, second_stencil]

    # Source symbol with input wavelet
    src = Receiver(name='src', grid=model.grid, time_range=time_range, npoint=1)
    src_term = src.inject(field=u.forward, expr=src.dt * s**2 / m)
    src_term += src.inject(field=v.forward, expr=src.dt * s**2 / m)
    expression += src_term

    if fs:
        expression += freesurface(u, model.nbpml)
        expression += freesurface(v, model.nbpml)
    if not norec:
        rec = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=2)
        expression += rec.interpolate(expr=u + v)

    kwargs = {'dse': 'aggressive', 'dle': 'advanced'}
    op = Operator(expression + eq_save, subs=model.spacing_map,
                  name="forward", **kwargs)

    return op