def test_position(shape): t0 = 0.0 # Start time tn = 500. # Final time nrec = 130 # Number of receivers # Create model from preset model = demo_model('constant-isotropic', spacing=[15. for _ in shape], shape=shape, nbpml=10) # Derive timestepping from model spacing dt = model.critical_dt nt = int(1 + (tn - t0) / dt) # Number of timesteps time_values = np.linspace(t0, tn, nt) # Discretized time axis # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time=time_values) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 30. # Define receiver geometry (same as source, but spread across x) rec = Receiver(name='nrec', grid=model.grid, ntime=nt, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, time_order=2, space_order=4) rec, u, _ = solver.forward(save=False) # Define source geometry (center of domain, just below surface) with 100. origin src = RickerSource(name='src', grid=model.grid, f0=0.01, time=time_values) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 + 100. src.coordinates.data[0, -1] = 130. # Define receiver geometry (same as source, but spread across x) rec2 = Receiver(name='rec2', grid=model.grid, ntime=nt, npoint=nrec) rec2.coordinates.data[:, 0] = np.linspace(100., 100. + model.domain_size[0], num=nrec) rec2.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] rec1, u1, _ = solver.forward(save=False, src=src, rec=rec2, o_x=100., o_y=100., o_z=100.) assert (np.allclose(rec.data, rec1.data, atol=1e-5))
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)
def run_acoustic_forward(dse=None): shape = (50, 50, 50) spacing = (10., 10., 10.) nbpml = 10 nrec = 101 t0 = 0.0 tn = 250.0 # Create two-layer model from preset model = demo_model(preset='layers-isotropic', vp_top=3., vp_bottom=4.5, spacing=spacing, shape=shape, nbpml=nbpml) # Derive timestepping from model spacing dt = model.critical_dt time_range = TimeAxis(start=t0, stop=tn, step=dt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 20. # Define receiver geometry (same as source, but spread across x) rec = Receiver(name='nrec', grid=model.grid, time_range=time_range, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] solver = AcousticWaveSolver(model, source=src, receiver=rec, dse=dse, dle='basic') rec, u, _ = solver.forward(save=False) return u, rec
def _setup_model_and_acquisition(self, shape, spacing, nbpml, tn): nrec = shape[0] model = demo_model('layers-isotropic', shape=shape, spacing=spacing, nbpml=nbpml) self.model = model t0 = 0.0 self.nt = int(1 + (tn-t0) / self.dt) # Number of timesteps time = np.linspace(t0, tn, self.nt) # Discretized time axis # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time=time) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = model.origin[-1] + 2 * spacing[-1] self.src = src # Define receiver geometry (spread across x, just below surface) # We need two receiver fields - one for the true (verification) run rec_t = Receiver(name='rec_t', grid=model.grid, ntime=self.nt, npoint=nrec) rec_t.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec_t.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] self.rec_t = rec_t # and the other for the smoothed run self.rec = Receiver(name='rec', grid=model.grid, ntime=self.nt, npoint=nrec, coordinates=rec_t.coordinates.data) # Receiver for Gradient self.rec_g = Receiver(name="rec_g", coordinates=self.rec.coordinates.data, grid=model.grid, dt=self.dt, ntime=self.nt) # Gradient symbol self.grad = Function(name="grad", grid=model.grid)
def src(self, model, time_params): time_values = np.linspace(*time_params) # Discretized time axis # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', ndim=model.dim, f0=0.01, time=time_values) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 30. return src
def acoustic_setup(shape=(50, 50, 50), spacing=(15.0, 15.0, 15.0), tn=500., kernel='OT2', space_order=4, nbpml=10, constant=False, **kwargs): nrec = shape[0] preset = 'constant-isotropic' if constant else 'layers-isotropic' model = demo_model(preset, space_order=space_order, shape=shape, nbpml=nbpml, dtype=kwargs.pop('dtype', np.float32), spacing=spacing) # Derive timestepping from model spacing dt = model.critical_dt * (1.73 if kernel == 'OT4' else 1.0) t0 = 0.0 time_range = TimeAxis(start=t0, stop=tn, step=dt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 if len(shape) > 1: src.coordinates.data[0, -1] = model.origin[-1] + 2 * spacing[-1] # Define receiver geometry (spread across x, just below surface) rec = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) if len(shape) > 1: rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, kernel=kernel, space_order=space_order, **kwargs) return solver
def setup_srcrec(model, time_range, f0): """Return a ricker source and receivers""" 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] = 600. src.coordinates.data[0, 1] = 600. # Remember that 0, 0, 0 is top left corner # Depth is 100m from free-surface boundary src.coordinates.data[0, 2] = 900. # 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(100, 1100, num=101) rec.coordinates.data[:, 1] = 600. # Centered on y axis # Receivers track the surface at 20m depth rec.coordinates.data[:, 2] = 480 + 480 * (np.sin( np.pi * np.linspace(100, 1100, num=101) / 1200)) - 20 return src, rec
def acoustic_setup(shape=(50, 50, 50), spacing=(15.0, 15.0, 15.0), tn=500., time_order=2, space_order=4, nbpml=10, constant=False, **kwargs): nrec = shape[0] preset = 'constant-isotropic' if constant else 'layers-isotropic' model = demo_model(preset, shape=shape, spacing=spacing, nbpml=nbpml) # Derive timestepping from model spacing dt = model.critical_dt * (1.73 if time_order == 4 else 1.0) t0 = 0.0 nt = int(1 + (tn-t0) / dt) # Number of timesteps time = np.linspace(t0, tn, nt) # Discretized time axis # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time=time) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = model.origin[-1] + 2 * spacing[-1] # Define receiver geometry (spread across x, just below surface) rec = Receiver(name='nrec', grid=model.grid, ntime=nt, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, time_order=time_order, space_order=space_order, **kwargs) return solver
def tti_setup(shape=(50, 50, 50), spacing=(20.0, 20.0, 20.0), tn=250.0, time_order=2, space_order=4, nbpml=10, **kwargs): nrec = 101 # Two layer model for true velocity model = demo_model('layers-tti', shape=shape, spacing=spacing, nbpml=nbpml) # Derive timestepping from model spacing dt = model.critical_dt t0 = 0.0 nt = int(1 + (tn - t0) / dt) time = np.linspace(t0, tn, nt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.015, time=time) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = model.origin[-1] + 2 * spacing[-1] # Define receiver geometry (spread across x, lust below surface) rec = Receiver(name='nrec', grid=model.grid, ntime=nt, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] return AnisotropicWaveSolver(model, source=src, receiver=rec, time_order=time_order, space_order=space_order, **kwargs)
def get_data(param): """ Returns source and receiver data for a single shot labeled 'shot_id'. """ true_model = get_true_model() dt = true_model.critical_dt # Time step from model grid spacing # Set up source data and geometry. nt = int(1 + (param['tn']-param['t0']) / dt) # Discrete time axis length src = RickerSource(name='src', grid=true_model.grid, f0=param['f0'], time=np.linspace(param['t0'], param['tn'], nt)) src.coordinates.data[0, :] = [30, param['shot_id']*1000./(param['nshots']-1)] # Set up receiver data and geometry. nreceivers = 101 # Number of receiver locations per shot rec = Receiver(name='rec', grid=true_model.grid, npoint=nreceivers, ntime=nt) rec.coordinates.data[:, 1] = np.linspace(0, true_model.domain_size[0], num=nreceivers) rec.coordinates.data[:, 0] = 980. # 20m from the right end # Set up solver - using model_in so that we have the same dt, # otherwise we should use pandas to resample the time series data. solver = AcousticWaveSolver(true_model, src, rec, space_order=4) # Generate synthetic receiver data from true model true_d, _, _ = solver.forward(src=src, m=true_model.m) return src, true_d, nt, solver
def test_acoustic(mkey, shape, kernel, space_order, nbpml): t0 = 0.0 # Start time tn = 500. # Final time nrec = 130 # Number of receivers # Create model from preset model = demo_model(spacing=[15. for _ in shape], dtype=np.float64, space_order=space_order, shape=shape, nbpml=nbpml, **(presets[mkey])) # Derive timestepping from model spacing dt = model.critical_dt * (1.73 if kernel == 'OT4' else 1.0) time_range = TimeAxis(start=t0, stop=tn, step=dt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 30. # Define receiver geometry (same as source, but spread across x) rec = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, kernel=kernel, space_order=space_order) # Create adjoint receiver symbol srca = Receiver(name='srca', grid=model.grid, time_range=solver.source.time_range, coordinates=solver.source.coordinates.data) # Run forward and adjoint operators rec, _, _ = solver.forward(save=False) solver.adjoint(rec=rec, srca=srca) # Adjoint test: Verify <Ax,y> matches <x, A^Ty> closely term1 = np.dot(srca.data.reshape(-1), solver.source.data) term2 = linalg.norm(rec.data)**2 info('<Ax,y>: %f, <x, A^Ty>: %f, difference: %12.12f, ratio: %f' % (term1, term2, (term1 - term2) / term1, term1 / term2)) assert np.isclose((term1 - term2) / term1, 0., rtol=1.e-10)
def src(self): t0, tn, dt = self.time_params time_range = TimeAxis(start=t0, stop=tn, step=dt) # Discretized time axis # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=self.model.grid, f0=0.01, time_range=time_range, dtype=self.dtype) src.coordinates.data[0, :] = np.array(self.model.domain_size) * .5 src.coordinates.data[0, -1] = 30. return src
def test_resample(): shape = (50, 50, 50) spacing = (10., 10., 10.) nbpml = 10 f0 = 0.01 t0 = 0.0 tn = 500 # Create two-layer model from preset model = demo_model(preset='layers-isotropic', vp_top=1., vp_bottom=2., spacing=spacing, shape=shape, nbpml=nbpml) time_range = TimeAxis(start=t0, stop=tn, step=model.critical_dt) src_a = RickerSource(name='src_a', grid=model.grid, f0=f0, time_range=time_range) time_range_f = TimeAxis(start=t0, step=time_range.step/(10*np.sqrt(2)), stop=time_range.stop) src_b = RickerSource(name='src_b', grid=model.grid, f0=f0, time_range=time_range_f) # Test resampling specifying dt. src_c = src_b.resample(dt=src_a._time_range.step) end = min(src_a.data.shape[0], src_c.data.shape[0]) assert np.allclose(src_a.data[:end], src_c.data[:end]) assert np.allclose(src_a.data[:end], src_c.data[:end]) # Text resampling based on num src_d = RickerSource(name='src_d', grid=model.grid, f0=f0, time_range=TimeAxis(start=time_range_f.start, stop=time_range_f.stop, num=src_a._time_range.num)) src_e = src_b.resample(num=src_d._time_range.num) assert np.isclose(src_d._time_range.step, src_e._time_range.step) assert np.isclose(src_d._time_range.stop, src_e._time_range.stop) assert src_d._time_range.num == src_e._time_range.num assert np.allclose(src_d.data, src_e.data) assert np.allclose(src_d.data, src_e.data)
def test_acousticJ(shape, space_order): t0 = 0.0 # Start time tn = 500. # Final time nrec = shape[0] # Number of receivers nbpml = 10 + space_order / 2 spacing = [15. for _ in shape] # Create two-layer "true" model from preset with a fault 1/3 way down model = demo_model('layers-isotropic', ratio=3, vp_top=1.5, vp_bottom=2.5, spacing=spacing, space_order=space_order, shape=shape, nbpml=nbpml, dtype=np.float64) # Derive timestepping from model spacing dt = model.critical_dt time_range = TimeAxis(start=t0, stop=tn, step=dt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 src.coordinates.data[0, -1] = 30. # Define receiver geometry (same as source, but spread across x) rec = Receiver(name='nrec', grid=model.grid, time_range=time_range, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, kernel='OT2', space_order=space_order) # Create initial model (m0) with a constant velocity throughout model0 = demo_model('layers-isotropic', ratio=3, vp_top=1.5, vp_bottom=1.5, spacing=spacing, space_order=space_order, shape=shape, nbpml=nbpml, dtype=np.float64) # Compute the full wavefield u0 _, u0, _ = solver.forward(save=True, m=model0.m) # Compute initial born perturbation from m - m0 dm = model.m.data - model0.m.data du, _, _, _ = solver.born(dm, m=model0.m) # Compute gradientfrom initial perturbation im, _ = solver.gradient(du, u0, m=model0.m) # Adjoint test: Verify <Ax,y> matches <x, A^Ty> closely term1 = np.dot(im.data.reshape(-1), dm.reshape(-1)) term2 = linalg.norm(du.data)**2 info('<Ax,y>: %f, <x, A^Ty>: %f, difference: %12.12f, ratio: %f' % (term1, term2, term1 - term2, term1 / term2)) assert np.isclose(term1 / term2, 1.0, atol=0.001)
def test_tti_staggered(shape): spacing = [10. for _ in shape] # Model model = demo_model('constant-tti', shape=shape, spacing=spacing) # Define seismic data and parameters f0 = .010 dt = model.critical_dt t0 = 0.0 tn = 250.0 time_range = TimeAxis(start=t0, stop=tn, step=dt) nt = time_range.num last = (nt - 1) % 2 # Generate a wavefield as initial condition source = RickerSource(name='src', grid=model.grid, f0=f0, time_range=time_range) source.coordinates.data[0, :] = np.array(model.domain_size) * .5 receiver = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=1) # Solvers solver_tti = AnisotropicWaveSolver(model, source=source, receiver=receiver, time_order=2, space_order=8) solver_tti2 = AnisotropicWaveSolver(model, source=source, receiver=receiver, time_order=2, space_order=8) # Solve configuration['dse'] = 'aggressive' configuration['dle'] = 'advanced' rec1, u1, v1, _ = solver_tti.forward(kernel='staggered') configuration['dle'] = 'basic' rec2, u2, v2, _ = solver_tti2.forward(kernel='staggered') u_staggered1 = u1.data[last, :] + v1.data[last, :] u_staggered2 = u2.data[last, :] + v2.data[last, :] res = np.linalg.norm(u_staggered1.reshape(-1) - u_staggered2.reshape(-1)) log("DSE/DLE introduces error %2.4e in %d dimensions" % (res, len(shape))) assert np.isclose(res, 0.0, atol=1e-8)
def test_resample(): shape = (50, 50, 50) spacing = (10., 10., 10.) nbl = 10 f0 = 0.01 t0 = 0.0 tn = 500 # Create two-layer model from preset model = demo_model(preset='layers-isotropic', vp_top=1., vp_bottom=2., spacing=spacing, shape=shape, nbl=nbl) time_range = TimeAxis(start=t0, stop=tn, step=model.critical_dt) src_a = RickerSource(name='src_a', grid=model.grid, f0=f0, time_range=time_range) time_range_f = TimeAxis(start=t0, step=time_range.step / (10 * np.sqrt(2)), stop=time_range.stop) src_b = RickerSource(name='src_b', grid=model.grid, f0=f0, time_range=time_range_f) # Test resampling specifying dt. src_c = src_b.resample(dt=src_a._time_range.step) end = min(src_a.data.shape[0], src_c.data.shape[0]) assert np.allclose(src_a.data[:end], src_c.data[:end]) assert np.allclose(src_a.data[:end], src_c.data[:end]) # Text resampling based on num src_d = RickerSource(name='src_d', grid=model.grid, f0=f0, time_range=TimeAxis(start=time_range_f.start, stop=time_range_f.stop, num=src_a._time_range.num)) src_e = src_b.resample(num=src_d._time_range.num) assert np.isclose(src_d._time_range.step, src_e._time_range.step) assert np.isclose(src_d._time_range.stop, src_e._time_range.stop) assert src_d._time_range.num == src_e._time_range.num assert np.allclose(src_d.data, src_e.data) assert np.allclose(src_d.data, src_e.data)
def test_position(shape): t0 = 0.0 # Start time tn = 500. # Final time nrec = 130 # Number of receivers # Create model from preset model = demo_model('constant-isotropic', spacing=[15. for _ in shape], shape=shape, nbl=10) # Derive timestepping from model spacing dt = model.critical_dt time_range = TimeAxis(start=t0, stop=tn, step=dt) # Source and receiver geometries src_coordinates = np.empty((1, len(shape))) src_coordinates[0, :] = np.array(model.domain_size) * .5 src_coordinates[0, -1] = 30. rec_coordinates = np.empty((nrec, len(shape))) rec_coordinates[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) rec_coordinates[:, 1:] = src_coordinates[0, 1:] geometry = AcquisitionGeometry(model, rec_coordinates, src_coordinates, t0=t0, tn=tn, src_type='Ricker', f0=0.010) # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, geometry, time_order=2, space_order=4) rec, u, _ = solver.forward(save=False) # Define source geometry (center of domain, just below surface) with 100. origin src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 + 100. src.coordinates.data[0, -1] = 130. # Define receiver geometry (same as source, but spread across x) rec2 = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=nrec) rec2.coordinates.data[:, 0] = np.linspace(100., 100. + model.domain_size[0], num=nrec) rec2.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] ox_g, oy_g, oz_g = tuple(o.dtype(o.data+100.) for o in model.grid.origin) rec1, u1, _ = solver.forward(save=False, src=src, rec=rec2, o_x=ox_g, o_y=oy_g, o_z=oz_g) assert(np.allclose(rec.data, rec1.data, atol=1e-5))
def overthrust_setup(filename, kernel='OT2', space_order=2, nbpml=40, **kwargs): model = from_hdf5(filename, space_order=space_order, nbpml=nbpml, datakey='m0', dtype=np.float64) spacing = model.spacing shape = model.vp.shape nrec = shape[0] tn = round(2 * max(model.domain_size) / np.min(model.vp)) # Derive timestepping from model spacing dt = model.critical_dt * (1.73 if kernel == 'OT4' else 1.0) t0 = 0.0 time_range = TimeAxis(start=t0, stop=tn, step=dt) # Define source geometry (center of domain, just below surface) src = RickerSource(name='src', grid=model.grid, f0=0.01, time_range=time_range) src.coordinates.data[0, :] = np.array(model.domain_size) * .5 if len(shape) > 1: src.coordinates.data[0, -1] = model.origin[-1] + 2 * spacing[-1] # Define receiver geometry (spread across x, just below surface) rec = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=nrec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) if len(shape) > 1: rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] # Create solver object to provide relevant operators solver = AcousticWaveSolver(model, source=src, receiver=rec, kernel=kernel, space_order=space_order, **kwargs) return solver
def analytic_response(): """ Computes analytic solution of 2D acoustic wave-equation with Ricker wavelet peak frequency fpeak, temporal padding 20x per the accuracy notebook: examples/seismic/acoustic/accuracy.ipynb u(r,t) = 1/(2 pi) sum[ -i pi H_0^2(k,r) q(w) e^{i w t} dw where: r = sqrt{(x_s - x_r)^2 + (z_s - z_r)^2} w = 2 pi f q(w) = Fourier transform of Ricker source wavelet H_0^2(k,r) Hankel function of the second kind k = w/v (wavenumber) """ sx, sz = src_coords[0, :] rx, rz = rec_coords[0, :] ntpad = 20 * (nt - 1) + 1 tmaxpad = dt * (ntpad - 1) time_axis_pad = TimeAxis(start=tmin, stop=tmaxpad, step=dt) srcpad = RickerSource(name='srcpad', grid=model.grid, f0=fpeak, npoint=1, time_range=time_axis_pad, t0w=t0w) nf = int(ntpad / 2 + 1) df = 1.0 / tmaxpad faxis = df * np.arange(nf) # Take the Fourier transform of the source time-function R = np.fft.fft(srcpad.wavelet[:]) R = R[0:nf] nf = len(R) # Compute the Hankel function and multiply by the source spectrum U_a = np.zeros((nf), dtype=complex) for a in range(1, nf - 1): w = 2 * np.pi * faxis[a] r = np.sqrt((rx - sx)**2 + (rz - sz)**2) U_a[a] = -1j * np.pi * hankel2(0.0, w * r / v0) * R[a] # Do inverse fft on 0:dt:T and you have analytical solution U_t = 1.0 / (2.0 * np.pi) * np.real(np.fft.ifft(U_a[:], ntpad)) # Note that the analytic solution is scaled by dx^2 to convert to pressure return (np.real(U_t) * (dx**2)), srcpad
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,:,:]
nbpml=10) from examples.seismic import TimeAxis t0 = 0. # Simulation starts a t=0 tn = 2000. # Simulation last 1 second (1000 ms) dt = model.critical_dt # Time step from model grid spacing time_range = TimeAxis(start=t0, stop=tn, step=dt) from examples.seismic import RickerSource f0 = 0.010 # Source peak frequency is 10Hz (0.010 kHz) 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 src.coordinates.data[0, -1] = 20. # Depth is 20m from examples.seismic import Receiver # 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] = 20. # Depth is 20m
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
npad = 20 qmin = 0.1 qmax = 1000.0 tmax = 500.0 fpeak = 0.010 omega = 2.0 * np.pi * fpeak b, v, time_axis, src_coords, rec_coords = default_setup_iso(npad, shape, dtype, tmax=tmax) solver = SsaIsoAcousticWaveSolver(npad, qmin, qmax, omega, b, v, src_coords, rec_coords, time_axis, space_order=8) src = RickerSource(name='src', grid=v.grid, f0=fpeak, npoint=1, time_range=time_axis) src.coordinates.data[:] = src_coords[:] rec, _, _ = solver.forward(src)
shape=shape, spacing=spacing, space_order=so, nbl=10, bcs="damp") # plt.imshow(model.vp.data[10, :, :]) ; pause(1) t0 = 0 # Simulation starts a t=0 tn = args.tn # Simulation last 1 second (1000 ms) dt = model.critical_dt # Time step from model grid spacing time_range = TimeAxis(start=t0, stop=tn, step=dt) f0 = 0.010 # Source peak frequency is 10Hz (0.010 kHz) src = RickerSource(name='src', grid=model.grid, f0=f0, npoint=9, time_range=time_range) # 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
file_trainA = h5py.File(strTrainA, 'w-') datasetA = file_trainA.create_dataset( dataset_train, (datasize, shape[0] + 2 * nbpml, shape[1] + 2 * nbpml)) file_trainB = h5py.File(strTrainB, 'w-') datasetB = file_trainB.create_dataset( dataset_train, (datasize, shape[0] + 2 * nbpml, shape[1] + 2 * nbpml)) num_rec = 601 rec_samp = np.linspace(0., model.domain_size[0], num=num_rec) rec_samp = rec_samp[1] - rec_samp[0] time_range = TimeAxis(start=t0, stop=tn, step=dt) src = RickerSource(name='src', grid=model.grid, f0=0.025, time_range=time_range, space_order=1, npoint=1) src.coordinates.data[0, :] = np.array([1 * spacing[0], 2 * spacing[1]]).astype(np.float32) rec = Receiver(name='rec', grid=model.grid, time_range=time_range, npoint=num_rec) rec.coordinates.data[:, 0] = np.linspace(0., model.domain_size[0], num=num_rec) rec.coordinates.data[:, 1:] = src.coordinates.data[0, 1:] solverbad = AcousticWaveSolver(model, source=src, receiver=rec,
def _setup_devito(self, velIndex=0): origin = (0.0, 0.0) self.spacing = (7.5, 7.5) self.nbpml = 40 self.num_rec = 401 self.shape = [ self.image_size0 - 2 * self.nbpml, self.image_size1 - 2 * self.nbpml ] tn, vp = velLoader(velIndex=velIndex, datapath=self.data_path) self.model = Model(origin, self.spacing, self.shape, 2, vp, nbpml=self.nbpml) dt = self.model.critical_dt t0 = 0.0 nt = int(1 + (tn - t0) / dt) self.virt_timestep = int(nt // self.correction_num) rec_samp = np.linspace(0., self.model.domain_size[0], num=self.num_rec) rec_samp = rec_samp[1] - rec_samp[0] xsrc = 100 time_range = TimeAxis(start=t0, stop=tn, step=dt) self.src = RickerSource(name='src', grid=self.model.grid, f0=0.025, time_range=time_range, space_order=1, npoint=1) self.src.coordinates.data[0, :] = np.array([xsrc * self.spacing[0], 2 * \ self.spacing[1]]).astype(np.float32) self.src_zero = RickerSource(name='src_zero', grid=self.model.grid, f0=0.025, time_range=time_range, space_order=1, npoint=1) self.src_zero.data.fill(0.) self.src_zero.coordinates.data[0, :] = np.array([xsrc * self.spacing[0], 2 * \ self.spacing[1]]).astype(np.float32) self.rec = Receiver(name='rec', grid=self.model.grid, time_range=time_range, \ npoint=self.num_rec) self.rec.coordinates.data[:, 0] = np.linspace(0., self.model.domain_size[0], \ num=self.num_rec) self.rec.coordinates.data[:, 1:] = self.src.coordinates.data[0, 1:] self.rec_zero = Receiver(name='rec_zero', grid=self.model.grid, time_range=time_range, \ npoint=self.num_rec) self.rec_zero.coordinates.data[:, 0] = np.linspace(0., self.model.domain_size[0], \ num=self.num_rec) self.rec_zero.coordinates.data[:, 1:] = self.src_zero.coordinates.data[0, 1:] self.solverLF = AcousticWaveSolver(self.model, source=self.src, receiver=self.rec, \ kernel='OT2', space_order=2) self.solverHF = AcousticWaveSolver(self.model, source=self.src, receiver=self.rec, \ kernel='OT2', space_order=20) self.u_HF = TimeFunction(name="u", grid=self.model.grid, time_order=2, space_order=20) self.u_LF = TimeFunction(name="u", grid=self.model.grid, time_order=2, space_order=2)
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
#============================================================================== # Construção Parâmetros Temporais do Modelo Hohomogeneo #============================================================================== dt_ref0 = model0.critical_dt dt0 = np.float32((tn-t0)/(ntmax)) time_range0 = TimeAxis(start=t0,stop=tn,step=dt0) dt = dt0 time_range = time_range0 print("dt: ", dt0, " dt_ref: ", dt_ref0) #============================================================================== #============================================================================== # Construção Fonte de Ricker Modelo Homogeneo #============================================================================== src0 = RickerSource(name='src0',grid=model0.grid,f0=f0,npoint=nfonte,time_range=time_range0) src0.coordinates.data[:, 0] = nxfontposv[0] src0.coordinates.data[:, 1] = nzfontpos #============================================================================== #============================================================================== # 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 #==============================================================================
rec = Receiver(name='rec', npoint=nreceivers, ntime=nt, grid=model.grid, coordinates=rec_coords) # NOT FOR MANUSCRIPT from examples.seismic import RickerSource # At first, we want only a single shot. # Src is 5% across model, at depth of 500 m. z_locations = np.linspace(0, z_extent, num=nshots) src_coords = np.array([(z_extent / 50, z) for z in z_locations]) # NOT FOR MANUSCRIPT f0 = 0.010 # kHz, peak frequency. src = RickerSource(name='src', grid=model.grid, f0=f0, time=time, coordinates=src_coords[nshots // 2]) # NOT FOR MANUSCRIPT plt.plot(src.time, src.data) plt.xlabel("Time (ms)") plt.ylabel("Amplitude") plt.show() from examples.seismic import plot_velocity plot_velocity(model) plot_velocity(model0)
def test_full_model(): shape = (50, 50, 50) spacing = [10. for _ in shape] nbl = 10 # Create two-layer model from preset model = demo_model(preset='layers-isotropic', vp_top=1., vp_bottom=2., spacing=spacing, shape=shape, nbl=nbl) # Test Model pickling pkl_model = pickle.dumps(model) new_model = pickle.loads(pkl_model) assert np.isclose(np.linalg.norm(model.vp.data[:] - new_model.vp.data[:]), 0) f0 = .010 dt = model.critical_dt t0 = 0.0 tn = 350.0 time_range = TimeAxis(start=t0, stop=tn, step=dt) # Test TimeAxis pickling pkl_time_range = pickle.dumps(time_range) new_time_range = pickle.loads(pkl_time_range) assert np.isclose(np.linalg.norm(time_range.time_values), np.linalg.norm(new_time_range.time_values)) # Test Class Constant pickling pkl_origin = pickle.dumps(model.grid.origin) new_origin = pickle.loads(pkl_origin) for a, b in zip(model.grid.origin, new_origin): assert a.compare(b) == 0 # Test Class TimeDimension pickling time_dim = TimeDimension(name='time', spacing=Constant(name='dt', dtype=np.float32)) pkl_time_dim = pickle.dumps(time_dim) new_time_dim = pickle.loads(pkl_time_dim) assert time_dim.spacing._value == new_time_dim.spacing._value # Test Class SteppingDimension stepping_dim = SteppingDimension(name='t', parent=time_dim) pkl_stepping_dim = pickle.dumps(stepping_dim) new_stepping_dim = pickle.loads(pkl_stepping_dim) assert stepping_dim.is_Time == new_stepping_dim.is_Time # Test Grid pickling pkl_grid = pickle.dumps(model.grid) new_grid = pickle.loads(pkl_grid) assert model.grid.shape == new_grid.shape assert model.grid.extent == new_grid.extent assert model.grid.shape == new_grid.shape for a, b in zip(model.grid.dimensions, new_grid.dimensions): assert a.compare(b) == 0 ricker = RickerSource(name='src', grid=model.grid, f0=f0, time_range=time_range) pkl_ricker = pickle.dumps(ricker) new_ricker = pickle.loads(pkl_ricker) assert np.isclose(np.linalg.norm(ricker.data), np.linalg.norm(new_ricker.data))