def simulate_seismic_topo (topo, circles_list, not_circles, vmax=5, vmin=1, f0 = 0.02500, dx=10, dy=10, t0=0, tn=700, pmlthickness=40, sigma_x=2, sigma_y=2, n_frames = 50): if circles_list == []: circles_list = [[int(topo.shape[0]/2),int(topo.shape[1]/2)]] circles = np.array(circles_list) topo = topo.astype(np.float32) topoRescale = scale_linear(topo, vmax, vmin) veltopo=smooth_topo( topoRescale, sigma_x, sigma_y ) if not_circles != []: veltopo[not_circles] = vmax * 1.8 # Define the model model = Model(vp=veltopo, # A velocity model. origin=(0, 0), # Top left corner. shape=veltopo.shape, # Number of grid points. spacing=(dx, dy), # Grid spacing in m. nbpml=pmlthickness) # boundary layer. dt = model.critical_dt # Time step from model grid spacing nt = int(1 + (tn-t0) / dt) # Discrete time axis length time = np.linspace(t0, tn, nt) # Discrete modelling time u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=2, save=True, time_dim=nt) pde = model.m * u.dt2 - u.laplace + model.damp * u.dt stencil = Eq(u.forward, solve(pde, u.forward)[0]) src_coords = np.multiply(circles[0],[dx,dy]) src = RickerSource(name='src0', grid=model.grid, f0=f0, time=time, coordinates=src_coords) src_term = src.inject(field=u.forward, expr=src * dt**2 / model.m, offset=model.nbpml) if circles.shape[0]>1: for idx, row in enumerate(circles[1:,:]): namesrc = 'src' + str(idx+1) src_coords = np.multiply(row,[dx,dy]) src_temp = RickerSource(name=namesrc, grid=model.grid, f0=f0, time=time, coordinates=src_coords) src_term_temp = src_temp.inject(field=u.forward, expr=src * dt**2 / model.m, offset=model.nbpml) src_term += src_term_temp op_fwd = Operator( [stencil] + src_term ) op_fwd(time=nt, dt=model.critical_dt) wf_data = u.data[:,pmlthickness:-pmlthickness,pmlthickness:-pmlthickness] wf_data_normalize = wf_data/np.amax(wf_data) framerate=np.int(np.ceil(wf_data.shape[0]/n_frames)) return wf_data_normalize[0::framerate,:,:]
def reference_shot(model, time_range, f0): """ Produce a reference shot gather with a level, conventional free-surface implementation. """ src = RickerSource(name='src', grid=model.grid, f0=f0, npoint=1, time_range=time_range) # First, position source centrally in all dimensions, then set depth src.coordinates.data[0, :] = np.array(model.domain_size) * .5 # Remember that 0, 0, 0 is top left corner # Depth is 100m from free-surface boundary src.coordinates.data[0, -1] = 600. # Create symbol for 101 receivers rec = Receiver(name='rec', grid=model.grid, npoint=101, time_range=time_range) # Prescribe even spacing for receivers along the x-axis rec.coordinates.data[:, 0] = np.linspace(0, model.domain_size[0], num=101) rec.coordinates.data[:, 1] = 500. # Centered on y axis rec.coordinates.data[:, 2] = 650. # Depth is 150m from free surface # Define the wavefield with the size of the model and the time dimension u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=4) # We can now write the PDE pde = model.m * u.dt2 - u.laplace + model.damp * u.dt stencil = Eq(u.forward, solve(pde, u.forward)) # Finally we define the source injection and receiver read function src_term = src.inject(field=u.forward, expr=src * model.critical_dt**2 / model.m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u.forward) x, y, z = model.grid.dimensions time = u.grid.stepping_dim # Throw a free surface in here free_surface_0 = Eq(u[time + 1, x, y, 60], 0) free_surface_1 = Eq(u[time + 1, x, y, 59], -u[time + 1, x, y, 61]) free_surface_2 = Eq(u[time + 1, x, y, 58], -u[time + 1, x, y, 62]) free_surface = [free_surface_0, free_surface_1, free_surface_2] op = Operator([stencil] + src_term + rec_term + free_surface) op(time=time_range.num - 1, dt=model.critical_dt) return rec.data
def iso_acoustic(self, opt): shape = (101, 101) extent = (1000, 1000) origin = (0., 0.) v = np.empty(shape, dtype=np.float32) v[:, :51] = 1.5 v[:, 51:] = 2.5 grid = Grid(shape=shape, extent=extent, origin=origin) t0 = 0. tn = 1000. dt = 1.6 time_range = TimeAxis(start=t0, stop=tn, step=dt) f0 = 0.010 src = RickerSource(name='src', grid=grid, f0=f0, npoint=1, time_range=time_range) domain_size = np.array(extent) src.coordinates.data[0, :] = domain_size * .5 src.coordinates.data[0, -1] = 20. rec = Receiver(name='rec', grid=grid, npoint=101, time_range=time_range) rec.coordinates.data[:, 0] = np.linspace(0, domain_size[0], num=101) rec.coordinates.data[:, 1] = 20. u = TimeFunction(name="u", grid=grid, time_order=2, space_order=2) m = Function(name='m', grid=grid) m.data[:] = 1. / (v * v) pde = m * u.dt2 - u.laplace stencil = Eq(u.forward, solve(pde, u.forward)) src_term = src.inject(field=u.forward, expr=src * dt**2 / m) rec_term = rec.interpolate(expr=u.forward) op = Operator([stencil] + src_term + rec_term, opt=opt, language='openmp') # Make sure we've indeed generated OpenMP offloading code assert 'omp target' in str(op) op(time=time_range.num - 1, dt=dt) assert np.isclose(norm(rec), 490.55, atol=1e-2, rtol=0)
#============================================================================== # Construção Receivers Homogeneo #============================================================================== rec0 = Receiver(name='rec0', grid=model0.grid,npoint=nrec,time_range=time_range0) rec0.coordinates.data[:,0] = nxrecpos rec0.coordinates.data[:,1] = nzrecpos #============================================================================== #============================================================================== # Construção dos Campos Modelo Homogêneo #============================================================================== u0 = TimeFunction(name="u0",grid=model0.grid,time_order=tou,space_order=sou) pde0 = model0.m * u0.dt2 - u0.laplace + model0.damp * u0.dt stencil0 = Eq(u0.forward, solve(pde0, u0.forward)) src_term0 = src0.inject(field=u0.forward, expr=src0* dt0**2 / model0.m) rec_term0 = rec0.interpolate(expr=u0) #============================================================================== #============================================================================== # Construção do Operador do Modelo Homogeneo #============================================================================== op0 = Operator([stencil0] + src_term0 + rec_term0, subs=model0.spacing_map) #============================================================================== #============================================================================== # For para o Número de Fontes #============================================================================== for k in range(0,number_xfontpos): #============================================================================== print("Homogen Source:", k)
# space-varying field (m, Function) from devito import TimeFunction, Buffer # Define the wavefield with the size of the model and the time dimension u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=2, save=Buffer(time_range.num + 1)) # We can now write the PDE pde = model.m * u.dt2 - u.laplace + model.damp * u.dt # The PDE representation is as on paper from devito import Eq, solve stencil = Eq(u.forward, solve(pde, u.forward)) # Finally we define the source injection and receiver read function to generate the corresponding code src_term = src.inject(field=u.forward, expr=src * dt**2 / model.m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u.forward) from devito import Operator op = Operator([stencil] + src_term + rec_term, subs=model.spacing_map) op(time=time_range.num - 1, dt=model.critical_dt)
def subsampled_gradient(factor=1, tn=2000.): t0 = 0. # Simulation starts a t=0 shape = (100, 100) origin = (0., 0.) spacing = (15., 15.) space_order = 4 vp = np.empty(shape, dtype=np.float64) vp[:, :51] = 1.5 vp[:, 51:] = 2.5 model = Model(vp=vp, origin=origin, shape=shape, spacing=spacing, space_order=space_order, nbl=10) dt = model.critical_dt # Time step from model grid spacing time_range = TimeAxis(start=t0, stop=tn, step=dt) nt = time_range.num # number of time steps f0 = 0.010 # Source peak frequency is 10Hz (0.010 kHz) src = RickerSource( name='src', grid=model.grid, f0=f0, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 20. # Depth is 20m rec = Receiver( name='rec', grid=model.grid, npoint=101, time_range=time_range) # new rec.coordinates.data[:, 0] = np.linspace(0, model.domain_size[0], num=101) rec.coordinates.data[:, 1] = 20. # Depth is 20m save_elements = (nt + factor - 1) // factor print(save_elements) time_subsampled = ConditionalDimension( 't_sub', parent=model.grid.time_dim, factor=factor) usave = TimeFunction(name='usave', grid=model.grid, time_order=2, space_order=space_order, save=save_elements, time_dim=time_subsampled) u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=space_order) pde = model.m * u.dt2 - u.laplace + model.damp * u.dt stencil = Eq(u.forward, solve(pde, u.forward)) src_term = src.inject( field=u.forward, expr=src * dt**2 / model.m, offset=model.nbl) rec_term = rec.interpolate(expr=u, offset=model.nbl) fwd_op = Operator([stencil] + src_term + [Eq(usave, u)] + rec_term, subs=model.spacing_map) # operator with snapshots v = TimeFunction(name='v', grid=model.grid, save=None, time_order=2, space_order=space_order) grad = Function(name='grad', grid=model.grid) rev_pde = model.m * v.dt2 - v.laplace + model.damp * v.dt.T rev_stencil = Eq(v.backward, solve(rev_pde, v.backward)) gradient_update = Inc(grad, - usave.dt2 * v) s = model.grid.stepping_dim.spacing receivers = rec.inject(field=v.backward, expr=rec*s**2/model.m) rev_op = Operator([rev_stencil] + receivers + [gradient_update], subs=model.spacing_map) fwd_op(time=nt - 2, dt=model.critical_dt) rev_op(dt=model.critical_dt, time=nt-16) return grad.data
# First, position source centrally in all dimensions, then set depth stx = 0.1 ste = 0.9 stepx = (ste - stx) / int(np.sqrt(src.npoint)) src.coordinates.data[:, :2] = np.array( np.meshgrid(np.arange(stx, ste, stepx), np.arange( stx, ste, stepx))).T.reshape(-1, 2) * np.array(model.domain_size[:1]) src.coordinates.data[:, -1] = 20 # Depth is 20m # f : perform source injection on an empty grid f = TimeFunction(name="f", grid=model.grid, space_order=so, time_order=2) src_f = src.inject(field=f.forward, expr=src * dt**2 / model.m) # op_f = Operator([src_f], opt=('advanced', {'openmp': True})) op_f = Operator([src_f]) op_f.apply(time=time_range.num - 1) normf = norm(f) print("==========") print(normf) print("===========") # uref : reference solution # uref = TimeFunction(name="uref", grid=model.grid, space_order=so, time_order=2) # src_term_ref = src.inject(field=uref.forward, expr=src * dt**2 / model.m) # pde_ref = model.m * uref.dt2 - uref.laplace + model.damp * uref.dt # stencil_ref = Eq(uref.forward, solve(pde_ref, uref.forward)) #Get the nonzero indices
def fwi_gradient(vp_in): # AUTO grad = Function(name="grad", grid=model.grid) residual = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, coordinates=geometry.rec_positions) objective = 0. u0 = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=4, save=geometry.nt) # MANUAL grad_manual = Function(name="grad", grid=model.grid) residual_man = Receiver(name='rec', grid=model.grid, time_range=time_axis, coordinates=rec_coordinates) objective_manual = 0. u0_man = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=4, save=nt) for i in range(9): # AUTO clear_cache() geometry.src_positions[0, :] = source_locations[i, :] true_d, _, _ = solver.forward(vp=model.vp) u0.data.fill(0.) smooth_d, _, _ = solver.forward(vp=vp_in, save=True, u=u0) residual.data[:] = smooth_d.data[:] - true_d.data[:] objective += .5 * np.linalg.norm(residual.data.flatten())**2 solver.gradient(rec=residual, u=u0, vp=vp_in, grad=grad) # MANUAL # source src_true = RickerSource(name='src', grid=model.grid, time_range=time_axis, coordinates=source_locations[i, :], npoint=1, f0=f0) src_term = src_true.inject( field=u.forward, expr=src_true * model.grid.stepping_dim.spacing**2 / model.m) # receiver rec_true = Receiver(name='rec', grid=model.grid, time_range=time_axis, coordinates=rec_coordinates, npoint=nreceivers) rec_term = rec_true.interpolate(expr=u) # operator op_fwd = Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward') op_fwd.apply(src=src_true, rec=rec_true, u=u0_man, vp=model.vp, dt=model.critical_dt) u0_man.data.fill(0.) rec_smooth = Receiver(name='rec', grid=model.grid, time_range=time_axis, coordinates=rec_coordinates, npoint=nreceivers) op_fwd.apply(src=src_true, rec=rec_smooth, u=u0_man, vp=vp_in, dt=model.critical_dt) # back-receiver rec_back = Receiver(name='rec', grid=model.grid, time_range=time_axis, coordinates=rec_coordinates, npoint=nreceivers) rec_back_term = rec_back.inject( field=v.backward, expr=rec_back * model.grid.stepping_dim.spacing**2 / model.m) # gradient gradient_update = Inc(grad_manual, -u.dt2 * v) op_grad = Operator(eqn_back + rec_back_term + [gradient_update], subs=model.spacing_map, name='Gradient') residual_man.data[:] = rec_smooth.data[:] - rec_true.data[:] objective_manual += .5 * np.linalg.norm(residual_man.data.flatten())**2 op_grad.apply(rec=residual_man, u=u0_man, vp=vp_in, dt=model.critical_dt, grad=grad_manual) # sanity-check -> expect for 0! # plot_shotrecord(true_d.data[:] - rec_true.data[:], model, t0, tn) # plot_shotrecord(smooth_d.data[:] - rec_smooth.data[:], model, t0, tn) return objective, -grad.data, objective_manual, -grad_manual.data
from examples.seismic import RickerSource # Define the time parameters of our simulation t0 = 0.0 # Start time tn = 400. # Final time dt = 4.2 # Timestep size in ms nt = int(1 + (tn - t0) / dt) # Number of timesteps time_values = np.linspace(t0, tn, nt) # Discretized time axis grid = Grid(shape=(120, 120), extent=(1800., 1800.)) # Define source geometry (slightly above the center) src = RickerSource(name='src', grid=grid, f0=0.01, time=time_values) src.coordinates.data[0, :] = [900., 550.] u = TimeFunction(name='u', grid=grid, space_order=2, time_order=2) m = Function(name='m', grid=grid) m.data[:] = 1. / 1.5**2 eqn = Eq(m * u.dt2 - u.laplace) stencil = solve(eqn, u.forward)[0] update = Eq(u.forward, stencil) source = src.inject(field=u.forward, expr=src * dt**2 / m) op = Operator([update] + source) # Run for warm-up time; make sure it's % 3 op(t=51, dt=dt) np.save('wavefield', u.data)
vnz = nz + 20 # Set symbolics for the wavefield object `u`, setting save on all time steps # (which can occupy a lot of memory), to later collect snapshots (naive method): u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=2, save=time_range.num) # Set symbolics of the operator, source and receivers: pde = model.m * u.dt2 - u.laplace + model.damp * u.dt stencil = Eq(u.forward, solve(pde, u.forward)) src_term = src.inject(field=u.forward, expr=src * dt**2 / model.m, offset=model.nbpml) rec_term = rec.interpolate(expr=u, offset=model.nbpml) op = Operator([stencil] + src_term + rec_term, subs=model.spacing_map) # Run the operator for `(nt-2)` time steps: op(time=nt - 2, dt=model.critical_dt) ######################################################################################################### #NBVAL_IGNORE_OUTPUT from devito import ConditionalDimension nsnaps = 100 # desired number of equally spaced snaps factor = round(nt / nsnaps) # subsequent calculated factor
u0_man = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=4, save=nt) receivers = [] for i in range(9): src_true = RickerSource(name='src', grid=model.grid, time_range=time_axis, coordinates=source_locations[i, :], npoint=1, f0=f0) src_term = src_true.inject(field=u.forward, expr=src_true * model.grid.stepping_dim.spacing**2 / model.m) # receiver receiver = Receiver(name='rec', grid=model.grid, time_range=time_axis, coordinates=rec_coordinates, npoint=nreceivers) rec_term = receiver.interpolate(expr=u) receivers.append(receiver) # operator op_fwd = Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward')
def tilted_shot(model, time_range, f0, tilt, qc=False, toggle_normals=False): """ Produce a shot for the same setup, but tilted with immersed free surface """ src = RickerSource(name='src', grid=model.grid, f0=f0, npoint=1, time_range=time_range) # First, position source, then set depth src.coordinates.data[0, 0] = 500. - 100. * np.sin(np.radians(tilt)) src.coordinates.data[0, 1] = 500. # Remember that 0, 0, 0 is top left corner # Depth is 100m from free-surface boundary src.coordinates.data[0, 2] = 500. + 100. * np.cos(np.radians(tilt)) # Create symbol for 101 receivers rec = Receiver(name='rec', grid=model.grid, npoint=101, time_range=time_range) # Prescribe even spacing for receivers along the x-axis rec_center_x = 500. - 150. * np.sin(np.radians(tilt)) rec_center_z = 500. + 150. * np.cos(np.radians(tilt)) rec_top_x = rec_center_x - 500. * np.cos(np.radians(tilt)) rec_bottom_x = rec_center_x + 500. * np.cos(np.radians(tilt)) rec_top_z = rec_center_z - 500. * np.sin(np.radians(tilt)) rec_bottom_z = rec_center_z + 500. * np.sin(np.radians(tilt)) rec.coordinates.data[:, 0] = np.linspace(rec_top_x, rec_bottom_x, num=101) rec.coordinates.data[:, 1] = 500. # Centered on y axis rec.coordinates.data[:, 2] = np.linspace(rec_top_z, rec_bottom_z, num=101) # Define the wavefield with the size of the model and the time dimension u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=4, coefficients='symbolic') infile = 'tests/trial_surfaces/angled_surface_' + str(tilt) + '.ply' # Zero even derivatives on the boundary spec = {2 * i: 0 for i in range(u.space_order)} bcs_u = BoundaryConditions(spec, u.space_order) functions = pd.DataFrame({ 'function': [u], 'bcs': [bcs_u] }, columns=['function', 'bcs']) # Create the immersed boundary surface surface = ImmersedBoundary('topography', infile, functions, interior_point=tuple(src.coordinates.data[0]), qc=qc, toggle_normals=toggle_normals) # Configure derivative needed derivs = pd.DataFrame( { 'function': [u], 'derivative': [2], 'eval_offset': [(0., 0., 0.)] }, columns=['function', 'derivative', 'eval_offset']) coeffs = surface.subs(derivs) # We can now write the PDE pde = model.m * u.dt2 - u.laplace + model.damp * u.dt stencil = Eq(u.forward, solve(pde, u.forward), coefficients=coeffs) # Finally we define the source injection and receiver read function src_term = src.inject(field=u.forward, expr=src * model.critical_dt**2 / model.m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u.forward) op = Operator([stencil] + src_term + rec_term) op(time=time_range.num - 1, dt=model.critical_dt) return rec.data
src.coordinates.data[:, -1] = 13 # Depth is 20m #src.coordinates.data[0, :] = np.array(model.domain_size) * .5 #src.coordinates.data[0, -1] = 20 # Depth is 20m #src.coordinates.data[1, :] = np.array(model.domain_size) * .5 #src.coordinates.data[1, -1] = 20 # Depth is 20m #src.coordinates.data[2, :] = np.array(model.domain_size) * .5 #src.coordinates.data[2, -1] = 20 # Depth is 20m #src.show() #pause(1) # f : perform source injection on an empty grid f = TimeFunction(name="f", grid=model.grid, space_order=so, time_order=2) src_f = src.inject(field=f.forward, expr=src) # op_f = Operator([src_f], opt=('advanced', {'openmp': True})) op_f = Operator([src_f]) op_f.apply(time=time_range.num-1) normf = norm(f) print("==========") print(normf) print("===========") # uref : reference solution uref = TimeFunction(name="uref", grid=model.grid, space_order=so, time_order=2) src_term_ref = src.inject(field=uref.forward, expr=src) pde_ref = model.m * uref.dt2 - uref.laplace + model.damp * uref.dt stencil_ref = Eq(uref.forward, solve(pde_ref, uref.forward)) #Get the nonzero indices
t0 = time.time() ####################################################################################### # Source # Source is at the middle of the domain at 10m depth tstart, tn = 0., 16000. time_range = TimeAxis(start=tstart, stop=tn, step=dt_cfl) f0 = 0.010 r = np.pi * f0 * (time_range.time_values - 1. / f0) wavelet = (1 - 2. * r**2) * np.exp(-r**2) src_coords = np.array([17500., 20000., 10.]) src = RickerSource(name='src', grid=grid, f0=0.010, time_range=time_range) src.coordinates.data[0, :] = src_coords src_P = src.inject(field=tau.forward[0, 0], expr=s * src) src_P += src.inject(field=tau.forward[1, 1], expr=s * src) src_P += src.inject(field=tau.forward[2, 2], expr=s * src) from scipy.signal import butter, sosfilt def butter_lowpass(cutoff, nyq_freq, order=5): normal_cutoff = float(cutoff) / nyq_freq sos = butter(order, normal_cutoff, analog=False, btype='lowpass', output='sos') return sos