def adjoint_w(model, rec_coords, data, wavelet, space_order=8): """ Adjoint/backward modeling of a shot record (receivers as source) for an extended source setup Pw*F^T*Pr^T*d_obs. Parameters ---------- model: Model Physical model rec_coords: Array Coordiantes of the receiver(s) data: Array Shot gather wavelet: Array Time signature of the forward source for stacking along time space_order: Int (optional) Spatial discretization order, defaults to 8 Returns ---------- Array spatial distribution """ w, _ = adjoint(model, data, None, rec_coords, ws=wavelet, space_order=space_order) return w.data
def adjoint_no_rec(model, rec_coords, data, space_order=8): """ Adjoint/backward modeling of a shot record (receivers as source) without source sampling F^T*Pr^T*d_obs. Parameters ---------- model: Model Physical model rec_coords: Array Coordiantes of the receiver(s) data: Array Shot gather space_order: Int (optional) Spatial discretization order, defaults to 8 Returns ---------- Array Adjoint wavefield """ _, v, _ = adjoint(model, data, None, rec_coords, space_order=space_order, save=True) return v.data
def adjoint_rec(model, src_coords, rec_coords, data, space_order=8): """ Adjoint/backward modeling of a shot record (receivers as source) Ps*F^T*Pr^T*d. Parameters ---------- model: Model Physical model src_coords: Array Coordiantes of the source(s) rec_coords: Array Coordiantes of the receiver(s) data: Array Shot gather space_order: Int (optional) Spatial discretization order, defaults to 8 Returns ---------- Array Shot record (adjoint wavefield at source position(s)) """ rec, _, _ = adjoint(model, data, src_coords, rec_coords, space_order=space_order) return rec.data
def adjoint_wf_src_norec(model, u, space_order=8, free_surface=False): """ Adjoint/backward modeling of a full wavefield (full wavefield as adjoint source) F^T*u. Parameters ---------- model: Model Physical model u: Array or TimeFunction Time-space dependent source space_order: Int (optional) Spatial discretization order, defaults to 8 free_surface: Bool (optional) Whether or not to use a free surface Returns ---------- Array Adjoint wavefield """ wf_src = TimeFunction(name='wf_src', grid=model.grid, time_order=2, space_order=space_order, save=u.shape[0]) if isinstance(u, TimeFunction): wf_src._data = u._data else: wf_src.data[:] = u[:] _, v = adjoint(model, None, None, None, space_order=space_order, save=True, free_surface=free_surface, q=wf_src) return v.data
def adjoint_wf_src(model, u, src_coords, space_order=8, free_surface=False): """ Adjoint/backward modeling of a full wavefield (full wavefield as adjoint source) Ps*F^T*u. Parameters ---------- model: Model Physical model u: Array or TimeFunction Time-space dependent source src_coords: Array Source coordinates space_order: Int (optional) Spatial discretization order, defaults to 8 free_surface: Bool (optional) Whether or not to use a free surface Returns ---------- Array Shot record (sampled at source position(s)) """ wf_src = TimeFunction(name='wf_src', grid=model.grid, time_order=2, space_order=space_order, save=u.shape[0]) if isinstance(u, TimeFunction): wf_src._data = u._data else: wf_src.data[:] = u[:] rec, _ = adjoint(model, None, src_coords, None, space_order=space_order, free_surface=free_surface, q=wf_src) return rec.data
def adjoint_w(model, rec_coords, data, wavelet, space_order=8, free_surface=False): """ Adjoint/backward modeling of a shot record (receivers as source) for an extended source setup Pw*F^T*Pr^T*d_obs. Parameters ---------- model: Model Physical model rec_coords: Array Coordiantes of the receiver(s) data: Array Shot gather wavelet: Array Time signature of the forward source for stacking along time space_order: Int (optional) Spatial discretization order, defaults to 8 free_surface: Bool (optional) Whether or not to use a free surface Returns ---------- Array spatial distribution """ w = adjoint(model, data, None, rec_coords, ws=wavelet, space_order=space_order, free_surface=free_surface) slices = [slice(model.nbl, -model.nbl) for _ in range(model.dim)] return w.data[slices]
def wri_func(model, src_coords, wavelet, rec_coords, recin, yin, space_order=8, isic=False, ws=None, t_sub=1, grad="m", grad_corr=False, alpha_op=False, w_fun=None, eps=0): """ Time domain wavefield reconstruction inversion wrapper """ # F(m0) * q if y is not an input and compute y = r(m0) if yin is None or grad_corr: y, u0, _ = forward(model, src_coords, rec_coords, wavelet, save=grad_corr, space_order=space_order, ws=ws) ydat = recin[:] - y.data[:] else: ydat = yin # Compute wavefield vy = adjoint(F(m0))*y and norm on the fly srca, v, norm_v, _ = adjoint(model, ydat, src_coords, rec_coords, norm_v=True, w_fun=w_fun, save=grad is not None) c1 = 1 / (recin.shape[1]) c2 = np.log(np.prod(model.shape)) # <PTy, d-F(m)*f> = <PTy, d>-<adjoint(F(m))*PTy, f> ndt = np.sqrt(model.critical_dt) PTy_dot_r = ndt**2 * (np.dot(ydat.reshape(-1), recin.reshape(-1)) - np.dot(srca.data.reshape(-1), wavelet.reshape(-1))) norm_y = ndt * np.linalg.norm(ydat) # alpha α = compute_optalpha(c2*norm_y, c1*norm_v, eps, comp_alpha=alpha_op) # Lagrangian evaluation fun = -.5 * c1 * α**2 * norm_v + c2 * α * PTy_dot_r - eps * np.abs(α) * norm_y gradm = grady = None if grad is not None: w = weight_fun(w_fun, model, src_coords) w = c1*α/w**2 if w is not None else c1*α Q = wf_as_src(v, w=w) rcv, gradm, _ = forward_grad(model, src_coords, rec_coords, c2*wavelet, q=Q, v=v) # Compute gradient wrt y if grad_corr or grad in ["all", "y"]: grady = c2 * recin - rcv.data[:] if norm_y != 0: grady -= np.abs(eps) * ydat / norm_y # Correcting for reduced gradient if not grad_corr: gradm = gradm.data else: gradm_corr, _ = gradient(model, grady, rec_coords, u0) # Reduced gradient post-processing gradm = gradm.data + gradm_corr.data return fun, α * gradm, grady
t0 = 0. tn = 1300. dt = model.critical_dt nt = int(1 + (tn - t0) / dt) time_axis = np.linspace(t0, tn, nt) # Source f1 = 0.008 src1 = RickerSource(name='src', grid=model.grid, f0=f1, time=time_axis) src1.coordinates.data[0, :] = np.array(model.domain_size) * 0.5 src1.coordinates.data[0, -1] = 20. # Receiver for observed data rec_t = Receiver(name='rec_t', grid=model.grid, npoint=301, ntime=nt) rec_t.coordinates.data[:, 0] = np.linspace(0., 3000., num=301) rec_t.coordinates.data[:, 1] = 20. # Test data and source d_hat, u1, _ = forward(model, src1.coordinates.data, rec_t.coordinates.data, src1.data) # Adjoint q0, _, _ = adjoint(model, d_hat, src1.coordinates.data, rec_t.coordinates.data) # Adjoint test a = inner(d_hat, d_hat) b = inner(q0, src1) print("Adjoint test F") print("a = %2.2e, b = %2.2e, diff = %2.2e: " % (a, b, a - b)) print("Relative error: ", a / b - 1)