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
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
def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, nb=40, 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)

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

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

    return rec.data
Esempio n. 4
0
def adjoint_modeling(model,
                     src_coords,
                     rec_coords,
                     rec_data,
                     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

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

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

    # Adjoint source is injected at receiver locations
    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)

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

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

    return src.data
Esempio n. 5
0
    def __init__(self, shots, shape, origin, spacing, m0, dm, noise=0.0, device='cpu', sequential=False):
        super(wave_solver, self).__init__()
        
        self.forward_born = ForwardBorn()
        self.noise = noise
        self.device = device
        self.dm = dm
        self.spacing = spacing
        epsilon = np.sqrt(noise)*np.random.randn(shots.shape[0], shots.shape[1], shots.shape[2])
        self.shots = shots + epsilon

        self.model0 = Model(shape=shape, origin=origin, spacing=spacing, vp=1/np.sqrt(m0), 
            nbpml=40)
        self.T = self.mute_top(dm, mute_end=10, length=5)
        t0 = 0.
        tn = 1500.0
        dt = self.model0.critical_dt
        nt = int(1 + (tn-t0) / dt)
        self.time_range = np.linspace(t0,tn,nt)
        self.f0 = 0.030
        self.nsrc = 205
        self.nsimsrc = 205
        self.src = RickerSource(name='src', grid=self.model0.grid, f0=self.f0, time=self.time_range, 
            npoint=self.nsimsrc)
        self.src.coordinates.data[:,0] = np.linspace(0, self.model0.domain_size[0], num=self.nsimsrc)
        self.src.coordinates.data[:,-1] = 2.0*spacing[1]
        nrec = 410
        self.rec = Receiver(name='rec', grid=self.model0.grid, npoint=nrec, ntime=nt)
        self.rec.coordinates.data[:, 0] = np.linspace(0, self.model0.domain_size[0], num=nrec)
        self.rec.coordinates.data[:, 1] = 2.0*spacing[1]

        self.seq_src_idx = 0
        self.sequential = sequential
Esempio n. 6
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. 7
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. 8
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. 9
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. 10
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. 11
0
# Time axis
t0 = 0.
tn = 10000.
dt = model0.critical_dt
nt = int(1 + (tn - t0) / dt)
time_axis = np.linspace(t0, tn, nt)

# Source
f0 = 0.015
src = RickerSource(name='src', grid=model0.grid, f0=f0, time=time_axis)
src.coordinates.data[0, :] = np.array(4617.)
src.coordinates.data[0, -1] = 20.

# Receiver for observed data
rec_t = Receiver(name='rec_t', grid=model0.grid, npoint=1200, ntime=nt)
rec_t.coordinates.data[:, 0] = np.linspace(4717., 16617., num=1200)
rec_t.coordinates.data[:, 1] = 50.

# Compute LS-RTM gradient w/ on-the-fly DFTs
num_frequencies = [1, 2, 4, 8, 16, 32, 64, 128, 256]
timings = np.zeros(len(num_frequencies))
for j in range(len(num_frequencies)):
    f = np.linspace(0.01, 0.01, num_frequencies[j])  # always use 10 Hz
    t1 = time.time()
    d0, ufr, ufi = forward_freq_modeling(model0,
                                         src.coordinates.data,
                                         src.data,
                                         rec_t.coordinates.data,
                                         freq=f,
                                         dt=dt,
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
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
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
Esempio n. 15
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. 16
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. 17
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. 18
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
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. 20
0
# Time axis
t0 = 0.
tn = 1000.
dt = model.critical_dt
nt = int(1 + (tn - t0) / dt)
time = np.linspace(t0, tn, nt)

# Source
f0 = 0.010
src = RickerSource(name='src', grid=model.grid, f0=f0, time=time)
src.coordinates.data[0, :] = np.array(model.domain_size) * 0.5
src.coordinates.data[0, -1] = 20.

# Receiver for observed data
rec_t = Receiver(name='rec_t', grid=model.grid, npoint=101, ntime=nt)
rec_t.coordinates.data[:, 0] = np.linspace(0, model.domain_size[0], num=101)
rec_t.coordinates.data[:, 1] = 20.

# Observed data
dobs, utrue = forward_modeling(model, src.coordinates.data, src.data,
                               rec_t.coordinates.data)

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

# Receiver for predicted data
rec = Receiver(name='rec', grid=model0.grid, npoint=101, ntime=nt)
rec.coordinates.data[:, 0] = np.linspace(0, model0.domain_size[0], num=101)
rec.coordinates.data[:, 1] = 20.

# Save wavefields
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
# Time axis
t0 = 0.
tn = 1400.
dt = model.critical_dt
nt = int(1 + (tn - t0) / dt)
time_axis = np.linspace(t0, tn, nt)

# Source
f0 = 0.010
src = RickerSource(name='src', grid=model.grid, f0=f0, time=time_axis)
src.coordinates.data[0, :] = np.array(model.domain_size) * 0.5
src.coordinates.data[0, -1] = 20.

# Receiver for observed data
rec_t = Receiver(name='rec_t', grid=model.grid, npoint=401, ntime=nt)
rec_t.coordinates.data[:, 0] = np.linspace(100, 900, num=401)
rec_t.coordinates.data[:, 1] = 20.

# Linearized data
print("Forward J")
t1 = time.time()
dD_hat = forward_born(model_const,
                      src.coordinates.data,
                      src.data,
                      rec_t.coordinates.data,
                      isic=False,
                      dt=dt)
dm_hat = model0.dm.data
t2 = time.time()
print(t2 - t1)
Esempio n. 23
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
rec_coordinates = np.empty((nrec, ndims))
rec_coordinates[:, 0] = gx
rec_coordinates[:, 1] = gz

geometry = AcquisitionGeometry(model,
                               rec_coordinates,
                               src_coordinates,
                               t0=0.0,
                               tn=tn,
                               src_type='Ricker',
                               f0=f0)

# Resample input data to computational grid
dorig = resample(dorig, t0, tn, nt, nt_comp)
dobs = Receiver(name='rec_t',
                grid=model.grid,
                ntime=nt_comp,
                coordinates=rec_coordinates)
dobs.data[:] = dorig

# Predicted data
if iteration > 1:
    dpred, summary0 = forward_born(model,
                                   geometry.src_positions,
                                   geometry.src.data,
                                   geometry.rec_positions,
                                   space_order=space_order)
    # Residual and function value
    dpred = dpred - dobs
else:
    dpred = Receiver(name='rec',
                     grid=model.grid,
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