def adjoint_y_run(self, y, src_coords, rcv_coords, weight_fun_pars=None, save=False): v = wavefield(self.model, self.space_order, save=save, nt=y.shape[0], fw=False) kwargs = wf_kwargs(v) rcv = Receiver(name="rcv", grid=self.model.grid, ntime=y.shape[0], coordinates=src_coords) src = PointSource(name="src", grid=self.model.grid, ntime=y.shape[0], coordinates=rcv_coords) src.data[:, :] = y[:, :] adj = self.op_adj_y(weight_fun_pars=weight_fun_pars, save=save) i = Dimension(name="i", ) norm_v = Function(name="nvy2", shape=(1, ), dimensions=(i, ), grid=self.model.grid) adj(src=src, rcv=rcv, nvy2=norm_v, **kwargs) return norm_v.data[0], rcv.data, v
def forward_run(self, wav, src_coords, rcv_coords, save=False, q=0, v=None, w=0, grad=False): # Computing residual u = wavefield(self.model, self.space_order, save=save, nt=wav.shape[0]) kwargs = wf_kwargs(u) rcv = Receiver(name="rcv", grid=self.model.grid, ntime=wav.shape[0], coordinates=rcv_coords) src = PointSource(name="src", grid=self.model.grid, ntime=wav.shape[0], coordinates=src_coords) src.data[:] = wav[:] fwd = self.op_fwd(save=save, q=q, grad=grad) if grad: w = Constant(name="w", value=w) gradm = Function(name="gradm", grid=self.model.grid) kwargs.update({as_tuple(v)[0].name: as_tuple(v)[0]}) kwargs.update({w.name: w, gradm.name: gradm}) fwd(rcv=rcv, src=src, **kwargs) if grad: return rcv.data, u, gradm return rcv.data, u
# Time axis t0 = 0. tn = 1000. dt = model.critical_dt nt = int(1 + (tn - t0) / dt) time_axis = np.linspace(t0, tn, nt) # Source f1 = 0.010 # kHz src = RickerSource(name='src', grid=model.grid, f0=f1, time=time_axis) src.coordinates.data[0, :] = np.array(model.domain_size) * 0.5 src.coordinates.data[0, -1] = 20. # Receiver for observed data nrec = shape[0] rec_t = Receiver(name='rec_t', grid=model.grid, npoint=nrec, ntime=nt) rec_t.coordinates.data[:, 0] = np.linspace(0., (shape[0] - 1) * spacing[0], num=nrec) rec_t.coordinates.data[:, 1] = 20. # Interface (Level 1) d_obs = forward_rec(model, src.coordinates.data, src.data, rec_t.coordinates.data, space_order=8, free_surface=False) N = 1000 a = .003 b = .030
def J_adjoint_checkpointing(model, src_coords, wavelet, rec_coords, recin, space_order=8, is_residual=False, n_checkpoints=None, maxmem=None, return_obj=False, isic=False, ws=None, t_sub=1): """ Jacobian (adjoint fo born modeling operator) operator on a shot record as a source (i.e data residual). Outputs the gradient with Checkpointing. Parameters ---------- model: Model Physical model src_coords: Array Coordiantes of the source(s) wavelet: Array Source signature rec_coords: Array Coordiantes of the receiver(s) recin: Array Receiver data space_order: Int (optional) Spatial discretization order, defaults to 8 checkpointing: Bool Whether or not to use checkpointing n_checkpoints: Int Number of checkpoints for checkpointing maxmem: Float Maximum memory to use for checkpointing isic : Bool Whether or not to use ISIC imaging condition ws : Array Extended source spatial distribution is_residual: Bool Whether to treat the input as the residual or as the observed data Returns ---------- Array Adjoint jacobian on the input data (gradient) """ # Optimal checkpointing op_f, u, rec_g = forward(model, src_coords, rec_coords, wavelet, space_order=space_order, return_op=True, ws=ws) op, g, v = gradient(model, recin, rec_coords, u, space_order=space_order, return_op=True, isic=isic) nt = wavelet.shape[0] rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) cp = DevitoCheckpoint([uu for uu in as_tuple(u)]) if maxmem is not None: memsize = (cp.size * u.data.itemsize) n_checkpoints = int(np.floor(maxmem * 10**6 / memsize)) # Op arguments uk = {uu.name: uu for uu in as_tuple(u)} vk = {**uk, **{vv.name: vv for vv in as_tuple(v)}} uk.update({'rcv%s' % as_tuple(u)[0].name: rec_g}) vk.update({'src%s' % as_tuple(v)[0].name: rec}) # Wrapped ops wrap_fw = CheckpointOperator(op_f, vp=model.vp, **uk) wrap_rev = CheckpointOperator(op, vp=model.vp, **vk) # 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.data[:] = recin[:] else: rec.data[:] = rec.data[:] - recin[:] # input is observed data wrp.apply_reverse() if return_obj: return .5 * model.critical_dt * norm(rec)**2, g.data return g.data
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
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