Exemple #1
0
 def gradient_operator(self):
     return GradientOperator(self.model,
                             self.src,
                             self.rec_g,
                             time_order=self.time_order,
                             spc_order=self.space_order,
                             save=False)
def run(dimensions=(50, 50, 50),
        tn=750.0,
        time_order=2,
        space_order=4,
        nbpml=40,
        dse='noop',
        dle='noop'):
    ndim = len(dimensions)
    origin = tuple([0.] * ndim)
    spacing = tuple([15.] * ndim)
    f0 = .010
    t0 = 0.0
    # True velocity
    true_vp = np.ones(dimensions) + .5
    true_vp[..., int(dimensions[-1] / 2):] = 2.

    # Smooth velocity - we use this as our initial m
    initial_vp = smooth10(true_vp, dimensions)
    # Model perturbation
    model = Model(origin, spacing, true_vp.shape, true_vp, nbpml=nbpml)
    m0 = np.float32(model.pad(initial_vp**-2))
    dm = np.float32(model.m.data - m0)
    dt = model.critical_dt
    if time_order == 4:
        dt *= 1.73

    nt = int(1 + (tn - t0) / dt)

    # Source geometry
    time_series = np.zeros((nt, 1), dtype=np.float32)
    time_series[:, 0] = source(np.linspace(t0, tn, nt), f0)

    # Source location
    location = np.zeros((1, ndim), dtype=np.float32)
    location[0, :-1] = [
        origin[i] + dimensions[i] * spacing[i] * .5 for i in range(ndim - 1)
    ]
    location[0, -1] = origin[-1] + 2 * spacing[-1]
    # Receivers locations
    receiver_coords = np.zeros((dimensions[0], ndim), dtype=np.float32)
    receiver_coords[:, 0] = np.linspace(0,
                                        origin[0] +
                                        (dimensions[0] - 1) * spacing[0],
                                        num=dimensions[0])
    receiver_coords[:, 1:] = location[0, 1:]

    # Create source symbol
    src = PointSource(name="src", data=time_series, coordinates=location)

    # Receiver for true model
    rec_t = Receiver(name="rec", ntime=nt, coordinates=receiver_coords)
    # Receiver for smoothed model
    rec_s = Receiver(name="rec", ntime=nt, coordinates=receiver_coords)

    # Create the forward wavefield to use (only 3 timesteps)
    # Once checkpointing is in, this will be the only wavefield we need
    u_nosave = TimeData(name="u",
                        shape=model.shape_domain,
                        time_dim=nt,
                        time_order=time_order,
                        space_order=space_order,
                        save=False,
                        dtype=model.dtype)

    # Forward wavefield where all timesteps are stored
    # With checkpointing this should go away <----
    u_save = TimeData(name="u",
                      shape=model.shape_domain,
                      time_dim=nt,
                      time_order=time_order,
                      space_order=space_order,
                      save=True,
                      dtype=model.dtype)

    # Forward Operators - one with save = True and one with save = False
    fw = ForwardOperator(model,
                         src,
                         rec_t,
                         time_order=time_order,
                         spc_order=space_order,
                         save=True,
                         dse=dse,
                         dle=dle)

    fw_nosave = ForwardOperator(model,
                                src,
                                rec_t,
                                time_order=time_order,
                                spc_order=space_order,
                                save=False,
                                dse=dse,
                                dle=dle)

    # Calculate receiver data for true velocity
    fw_nosave.apply(u=u_nosave, rec=rec_t, src=src)

    # Smooth velocity
    # This is the pass that needs checkpointing <----
    fw.apply(u=u_save, rec=rec_s, m=m0, src=src)

    # Objective function value
    F0 = .5 * linalg.norm(rec_s.data - rec_t.data)**2
    # Receiver for Gradient
    # Confusing nomenclature because this is actually the source for the adjoint
    # mode
    rec_g = Receiver(name="rec",
                     coordinates=rec_s.coordinates.data,
                     data=rec_s.data - rec_t.data)
    # Gradient symbol
    grad = DenseData(name="grad", shape=model.shape_domain, dtype=model.dtype)
    # Reusing u_nosave from above as the adjoint wavefield since it is a temp var anyway
    gradop = GradientOperator(model,
                              src,
                              rec_g,
                              time_order=time_order,
                              spc_order=space_order,
                              dse=dse,
                              dle=dle)

    # Clear the wavefield variable to reuse it
    # This time it represents the adjoint field
    u_nosave.data.fill(0)
    # Apply the gradient operator to calculate the gradient
    # This is the pass that requires the checkpointed data
    gradop.apply(u=u_save, v=u_nosave, m=m0, rec=rec_g, grad=grad)
    # The result is in grad
    gradient = grad.data

    # <J^T \delta d, dm>
    G = np.dot(gradient.reshape(-1), dm.reshape(-1))
    # FWI Gradient test
    H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125]
    error1 = np.zeros(7)
    error2 = np.zeros(7)

    for i in range(0, 7):
        # Add the perturbation to the model
        mloc = m0 + H[i] * dm
        # Set field to zero (we're re-using it)
        u_nosave.data.fill(0)
        # Receiver data for the new model
        # Results will be in rec_s
        fw_nosave.apply(u=u_nosave, rec=rec_s, m=mloc, src=src)
        d = rec_s.data
        # First order error Phi(m0+dm) - Phi(m0)
        error1[i] = np.absolute(.5 * linalg.norm(d - rec_t.data)**2 - F0)
        # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm>
        error2[i] = np.absolute(.5 * linalg.norm(d - rec_t.data)**2 - F0 -
                                H[i] * G)

    # Test slope of the  tests
    p1 = np.polyfit(np.log10(H), np.log10(error1), 1)
    p2 = np.polyfit(np.log10(H), np.log10(error2), 1)
    assert np.isclose(p1[0], 1.0, rtol=0.1)
    assert np.isclose(p2[0], 2.0, rtol=0.1)
 def gradient_operator(self):
     return GradientOperator(self.model,
                             self.src,
                             self.rec_g,
                             kernel=self.kernel,
                             spc_order=self.space_order)