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