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 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 update_devito(self, velIndex=1): tn, vp = velLoader(velIndex=velIndex, datapath=self.data_path) self.model.vp = vp 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.coordinates.data[0, :] = np.array([xsrc * self.spacing[0], 2 * \ self.spacing[1]]).astype(np.float32) 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.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.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.u_HF.data.fill(0.) self.u_LF.data.fill(0.)
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 tti_operator(dse=False, space_order=4): nrec = 101 t0 = 0.0 tn = 250. nbpml = 10 shape = (50, 50, 50) spacing = (20., 20., 20.) # Two layer model for true velocity model = demo_model('layers-tti', ratio=3, nbpml=nbpml, space_order=space_order, shape=shape, spacing=spacing) # Derive timestepping from model spacing # 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 = GaborSource(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] = model.origin[-1] + 2 * spacing[-1] # Define receiver geometry (spread across x, lust below surface) 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:] return AnisotropicWaveSolver(model, source=src, receiver=rec, space_order=space_order, dse=dse)
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 rec(self): nrec = 130 # Number of receivers t0, tn, dt = self.time_params time_range = TimeAxis(start=t0, stop=tn, step=dt) rec = Receiver(name='rec', grid=self.model.grid, time_range=time_range, npoint=nrec, dtype=self.dtype) rec.coordinates.data[:, 0] = np.linspace(0., self.model.domain_size[0], num=nrec) rec.coordinates.data[:, 1:] = self.src.coordinates.data[0, 1:] return rec
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 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_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 _setup_model_and_acquisition(self, space_order, shape, spacing, nbpml, tn): nrec = shape[0] model = demo_model('layers-isotropic', space_order=space_order, shape=shape, spacing=spacing, nbpml=nbpml) self.model = model t0 = 0.0 time_range = TimeAxis(start=t0, stop=tn, step=self.dt) self.nt = time_range.num # 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] = 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', grid=model.grid, time_range=time_range, 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, time_range=time_range, npoint=nrec, coordinates=rec_t.coordinates.data) # Receiver for Gradient self.rec_g = Receiver(name="rec", coordinates=self.rec.coordinates.data, grid=model.grid, time_range=time_range) # Gradient symbol self.grad = Function(name="grad", grid=model.grid)
def test_receiver(): grid = Grid(shape=(3,)) time_range = TimeAxis(start=0., stop=1000., step=0.1) nreceivers = 3 rec = Receiver(name='rec', grid=grid, time_range=time_range, npoint=nreceivers, coordinates=[(0.,), (1.,), (2.,)]) rec.data[:] = 1. pkl_rec = pickle.dumps(rec) new_rec = pickle.loads(pkl_rec) assert np.all(new_rec.data == 1) assert np.all(new_rec.coordinates.data == [[0.], [1.], [2.]])
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 overthrust_setup(filename, kernel='OT2', tn=4000, space_order=2, nbpml=40, dtype=np.float32, **kwargs): model = from_hdf5(filename, space_order=space_order, nbpml=nbpml, datakey='m0', dtype=dtype) shape = model.vp.shape spacing = model.spacing nrec = shape[0] # 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) src_coordinates = np.empty((1, len(spacing))) src_coordinates[0, :] = np.array(model.domain_size) * .5 if len(shape) > 1: src_coordinates[0, -1] = model.origin[-1] + 2 * spacing[-1] rec_coordinates = np.empty((nrec, len(spacing))) rec_coordinates[:, 0] = np.linspace(0., model.domain_size[0], num=nrec) if len(shape) > 1: rec_coordinates[:, 1] = np.array(model.domain_size)[1] * .5 rec_coordinates[:, -1] = model.origin[-1] + 2 * spacing[-1] # Create solver object to provide relevant operator geometry = AcquisitionGeometry(model, rec_coordinates, src_coordinates, t0=0.0, tn=tn, src_type='Ricker', f0=0.010) solver = AcousticWaveSolver(model, geometry, kernel=kernel, space_order=space_order, **kwargs) return solver
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 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 resample(rec, num): start, stop = rec._time_range.start, rec._time_range.stop dt0 = rec._time_range.step new_time_range = TimeAxis(start=start, stop=stop, num=num) dt = new_time_range.step to_interp = np.asarray(rec.data) data = np.zeros((num, to_interp.shape[1])) for i in range(to_interp.shape[1]): tck = interpolate.splrep(rec._time_range.time_values, to_interp[:, i], k=3) data[:, i] = interpolate.splev(new_time_range.time_values, tck) coords_loc = np.asarray(rec.coordinates.data) # Return new object return data, coords_loc
def test_tilted_boundary(self, spec): """ Check that gathers for a tilted boundary match those generated with a conventional horizontal free surface and the same geometry. """ tilt, toggle_normals = spec max_thres = 0.09 avg_thres = 0.006 # Define a physical size shape = (101, 101, 101) # Number of grid point (nx, ny, nz) spacing = (10., 10., 10. ) # Grid spacing in m. The domain size is 1x1x1km origin = (0., 0., 0.) v = 1.5 model = Model(vp=v, origin=origin, shape=shape, spacing=spacing, space_order=4, nbl=10, bcs="damp") t0 = 0. # Simulation starts a t=0 tn = 500. # Simulation last 0.5 seconds (500 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) ref = reference_shot(model, time_range, f0) tilted = tilted_shot(model, time_range, f0, tilt, toggle_normals=toggle_normals) assert np.amax(np.absolute(ref - tilted)) < max_thres assert np.mean(np.absolute(ref - tilted)) < avg_thres
def main(tilt, toggle_normals): """For troubleshooting the sectioning""" # Define a physical size shape = (101, 101, 101) # Number of grid point (nx, ny, nz) spacing = (10., 10., 10.) # Grid spacing in m. The domain size is 1x1x1km origin = (0., 0., 0.) v = 1.5 model = Model(vp=v, origin=origin, shape=shape, spacing=spacing, space_order=4, nbl=10, bcs="damp") t0 = 0. # Simulation starts a t=0 tn = 500. # Simulation last 0.5 seconds (500 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) ref = reference_shot(model, time_range, f0) tilted = tilted_shot(model, time_range, f0, tilt, qc=True, toggle_normals=toggle_normals) plt.imshow(ref) plt.show() plt.imshow(tilted) plt.show() plt.imshow(ref - tilted) plt.show()
def ib_ref(): """Generate a high-accuracy immersed-boundary reference""" # Number of grid point (nx, ny, nz) shape = (201, 201, 201) # Grid spacing in m. The domain size is 1x1x1km spacing = (5., 5., 5.) # Needs to account for damping layers origin = (100., 100., 0.) v = 1.5 model = Model(vp=v, origin=origin, shape=shape, spacing=spacing, space_order=8, nbl=10, bcs="damp") t0 = 0. # Simulation starts at t=0 tn = 450. # Simulation last 0.45 seconds (450 ms) dt = 0.6038 # Hardcoded timestep to keep stable time_range = TimeAxis(start=t0, stop=tn, step=dt) f0 = 0.015 # Source peak frequency is 15Hz (0.015 kHz) src, rec = setup_srcrec(model, time_range, f0) # 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=8, coefficients='symbolic') shot, wavefield = ib_shot(model, u, time_range, dt, src, rec) return shot, wavefield
def tti_setup(shape=(50, 50, 50), spacing=(20.0, 20.0, 20.0), tn=250.0, space_order=4, nbpml=10, preset='layers-tti', **kwargs): nrec = 101 # Two layer model for true velocity model = demo_model(preset, shape=shape, spacing=spacing, nbpml=nbpml) # Derive timestepping from model spacing dt = model.critical_dt 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.015, time_range=time_range) 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, 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:] return AnisotropicWaveSolver(model, source=src, receiver=rec, space_order=space_order, **kwargs)
def default_setup_iso(npad, shape, dtype, sigma=0, qmin=0.1, qmax=100.0, tmin=0.0, tmax=2000.0, bvalue=1.0 / 1000.0, vvalue=1.5, space_order=8): """ For isotropic propagator build default model with 10m spacing, and 1.5 m/msec velocity Return: dictionary of velocity, buoyancy, and wOverQ TimeAxis defining temporal sampling Source locations: one located at center of model, z = 1dz Receiver locations, one per interior grid intersection, z = 2dz 2D: 1D grid of receivers center z covering interior of model 3D: 2D grid of receivers center z covering interior of model """ d = 10.0 origin = tuple([0.0 - d * npad for s in shape]) extent = tuple([d * (s - 1) for s in shape]) # Define dimensions if len(shape) == 2: x = SpaceDimension(name='x', spacing=Constant(name='h_x', value=d)) z = SpaceDimension(name='z', spacing=Constant(name='h_z', value=d)) grid = Grid(extent=extent, shape=shape, origin=origin, dimensions=(x, z), dtype=dtype) else: x = SpaceDimension(name='x', spacing=Constant(name='h_x', value=d)) y = SpaceDimension(name='y', spacing=Constant(name='h_y', value=d)) z = SpaceDimension(name='z', spacing=Constant(name='h_z', value=d)) grid = Grid(extent=extent, shape=shape, origin=origin, dimensions=(x, y, z), dtype=dtype) b = Function(name='b', grid=grid, space_order=space_order) v = Function(name='v', grid=grid, space_order=space_order) b.data[:] = bvalue v.data[:] = vvalue dt = dtype("%.6f" % (0.8 * compute_critical_dt(v))) time_axis = TimeAxis(start=tmin, stop=tmax, step=dt) # Define coordinates in 2D and 3D if len(shape) == 2: nr = shape[0] - 2 * npad src_coords = np.empty((1, len(shape)), dtype=dtype) rec_coords = np.empty((nr, len(shape)), dtype=dtype) src_coords[:, 0] = origin[0] + extent[0] / 2 src_coords[:, 1] = 1 * d rec_coords[:, 0] = np.linspace(0.0, d * (nr - 1), nr) rec_coords[:, 1] = 2 * d else: # using numpy outer product here for array iteration speed xx, yy = np.ogrid[:shape[0] - 2 * npad, :shape[1] - 2 * npad] x1 = np.ones((shape[0] - 2 * npad, 1)) y1 = np.ones((1, shape[1] - 2 * npad)) xcoord = (xx * y1).reshape(-1) ycoord = (x1 * yy).reshape(-1) nr = len(xcoord) src_coords = np.empty((1, len(shape)), dtype=dtype) rec_coords = np.empty((nr, len(shape)), dtype=dtype) src_coords[:, 0] = origin[0] + extent[0] / 2 src_coords[:, 1] = origin[1] + extent[1] / 2 src_coords[:, 2] = 1 * d rec_coords[:, 0] = d * xcoord rec_coords[:, 1] = d * ycoord rec_coords[:, 2] = 2 * d return b, v, time_axis, src_coords, rec_coords
#============================================================================== vhomo = np.empty(shape,dtype=np.float32) vhomo[:,:] = vmodelmin model0 = Model(vp=vhomo,origin=origin,shape=shape,spacing=spacing,space_order=sou,nbl=nbl,bcs="damp") rec_homo = np.zeros((number_xfontpos,ntmax+1,nrec)) #============================================================================== if(verbosity>0): rplot.graph2dvel(model0.vp.data,teste,0,-1) #============================================================================== # 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
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
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))
def forward_modeling_single_shot(record, table, par_files): "Serial modeling function" worker = get_worker() # The worker on which this task is running strng = '{} : {} =>'.format(worker.address, str(record).zfill(5)) filename = 'logfile_{}.txt'.format(str(record).zfill(5)) g = open(filename, 'w') g.write("This will show up in the worker logs") # Read velocity model f = segyio.open(par_files[-1], iline=segyio.tracefield.TraceField.FieldRecord, xline=segyio.tracefield.TraceField.CDP) xl, il, t = f.xlines, f.ilines, f.samples dz = t[1] - t[0] dx = f.header[1][segyio.TraceField.SourceX]-f.header[0][segyio.TraceField.SourceX] if len(il) != 1: dims = (len(xl), len(il), len(f.samples)) else: dims = (len(xl), len(f.samples)) vp = f.trace.raw[:].reshape(dims) vp *= 1./1000 # convert to km/sec epsilon = np.empty(dims) delta = np.empty(dims) theta = np.empty(dims) params = [epsilon, delta, theta] # Read Thomsem parameters for segyfile, par in zip(par_files, params): f = segyio.open(segyfile, iline=segyio.tracefield.TraceField.FieldRecord, xline=segyio.tracefield.TraceField.CDP) par[:] = f.trace.raw[:].reshape(dims) theta *= (np.pi/180.) # use radians g.write('{} Parameter model dims: {}\n'.format(strng, vp.shape)) origin = (0., 0.) shape = vp.shape spacing = (dz, dz) # Get a single shot as a numpy array filename = table[record]['filename'] position = table[record]['Trace_Position'] traces_in_shot = table[record]['Num_Traces'] src_coord = np.array(table[record]['Source']).reshape((1, len(dims))) rec_coord = np.array(table[record]['Receivers']) start = time.time() f = segyio.open(filename, ignore_geometry=True) num_samples = len(f.samples) samp_int = f.bin[segyio.BinField.Interval]/1000 retrieved_shot = np.zeros((traces_in_shot, num_samples)) shot_traces = f.trace[position:position+traces_in_shot] for i, trace in enumerate(shot_traces): retrieved_shot[i] = trace g.write('{} Shot loaded in: {} seconds\n'.format(strng, time.time()-start)) # Only keep receivers within the model' xmin = origin[0] idx_xrec = np.where(rec_coord[:, 0] < xmin)[0] is_empty = idx_xrec.size == 0 if not is_empty: g.write('{} in {}\n'.format(strng, rec_coord.shape)) idx_tr = np.where(rec_coord[:, 0] >= xmin)[0] rec_coord = np.delete(rec_coord, idx_xrec, axis=0) # For 3D shot records, scan also y-receivers if len(origin) == 3: ymin = origin[1] idx_yrec = np.where(rec_coord[:, 1] < ymin)[0] is_empty = idx_yrec.size == 0 if not is_empty: rec_coord = np.delete(rec_coord, idx_yrec, axis=0) if rec_coord.size == 0: g.write('all receivers outside of model\n') return np.zeros(vp.shape) space_order = 8 g.write('{} before: {} {} {}\n'.format(strng, params[0].shape, rec_coord.shape, src_coord.shape)) model = limit_model_to_receiver_area(rec_coord, src_coord, origin, spacing, shape, vp, params, space_order=space_order, nbl=80) g.write('{} shape_vp: {}\n'.format(strng, model.vp.shape)) model.smooth(('epsilon', 'delta', 'theta')) # Geometry for current shot geometry = AcquisitionGeometry(model, rec_coord, src_coord, 0, (num_samples-1)*samp_int, f0=0.018, src_type='Ricker') g.write("{} Number of samples modelled data & dt: {} & {}\n".format(strng, geometry.nt, model.critical_dt)) g.write("{} Samples & dt: {} & {}\n".format(strng, num_samples, samp_int)) # Set up solver. solver_tti = AnisotropicWaveSolver(model, geometry, space_order=space_order) # Create image symbol and instantiate the previously defined imaging operator image = Function(name='image', grid=model.grid) itemsize = np.dtype(np.float32).itemsize full_fld_mem = model.vp.size*itemsize*geometry.nt*2. checkpointing = True if checkpointing: op_imaging = ImagingOperator(geometry, image, space_order, save=False) n_checkpoints = 150 ckp_fld_mem = model.vp.size*itemsize*n_checkpoints*2. g.write('Mem full fld: {} == {} use ckp instead\n'.format(full_fld_mem, humanbytes(full_fld_mem))) g.write('Number of checkpoints/timesteps: {}/{}\n'.format(n_checkpoints, geometry.nt)) g.write('Memory saving: {}\n'.format(humanbytes(full_fld_mem-ckp_fld_mem))) u = TimeFunction(name='u', grid=model.grid, staggered=None, time_order=2, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, staggered=None, time_order=2, space_order=space_order) vv = TimeFunction(name='vv', grid=model.grid, staggered=None, time_order=2, space_order=space_order) uu = TimeFunction(name='uu', grid=model.grid, staggered=None, time_order=2, space_order=space_order) cp = DevitoCheckpoint([u, v]) op_fwd = solver_tti.op_fwd(save=False) op_fwd.cfunction op_imaging.cfunction wrap_fw = CheckpointOperator(op_fwd, src=geometry.src, u=u, v=v, vp=model.vp, epsilon=model.epsilon, delta=model.delta, theta=model.theta, dt=model.critical_dt) time_range = TimeAxis(start=0, stop=(num_samples-1)*samp_int, step=samp_int) dobs = Receiver(name='dobs', grid=model.grid, time_range=time_range, coordinates=geometry.rec_positions) if not is_empty: dobs.data[:] = retrieved_shot[idx_tr, :].T else: dobs.data[:] = retrieved_shot[:].T dobs_resam = dobs.resample(num=geometry.nt) g.write('Shape of residual: {}\n'.format(dobs_resam.data.shape)) wrap_rev = CheckpointOperator(op_imaging, u=u, v=v, vv=vv, uu=uu, vp=model.vp, epsilon=model.epsilon, delta=model.delta, theta=model.theta, dt=model.critical_dt, residual=dobs_resam.data) # Run forward wrp = Revolver(cp, wrap_fw, wrap_rev, n_checkpoints, dobs_resam.shape[0]-2) g.write('Revolver storage: {}\n'.format(humanbytes(cp.size*n_checkpoints*itemsize))) wrp.apply_forward() g.write('{} run finished\n'.format(strng)) summary = wrp.apply_reverse() form = 'image_{}.bin'.format(str(record).zfill(5)) h = open(form, 'wb') g.write('{}\n'.format(str(image.data.shape))) np.transpose(image.data).astype('float32').tofile(h) else: # For illustrative purposes, assuming that there is enough memory g.write('enough memory to save full fld: {} == {}\n'.format(full_fld_mem, humanbytes(full_fld_mem))) op_imaging = ImagingOperator(geometry, image, space_order) vv = TimeFunction(name='vv', grid=model.grid, staggered=None, time_order=2, space_order=space_order) uu = TimeFunction(name='uu', grid=model.grid, staggered=None, time_order=2, space_order=space_order) time_range = TimeAxis(start=0, stop=(num_samples-1)*samp_int, step=samp_int) dobs = Receiver(name='dobs', grid=model.grid, time_range=time_range, coordinates=geometry.rec_positions) if not is_empty: dobs.data[:] = retrieved_shot[idx_tr, :].T else: dobs.data[:] = retrieved_shot[:].T dobs_resam = dobs.resample(num=geometry.nt) u, v = solver_tti.forward(vp=model.vp, epsilon=model.epsilon, delta=model.delta, theta=model.theta, dt=model.critical_dt, save=True)[1:-1] op_imaging(u=u, v=v, vv=vv, uu=uu, epsilon=model.epsilon, delta=model.delta, theta=model0.theta, vp=model.vp, dt=model.critical_dt, residual=dobs_resam) full_image = extend_image(origin, vp, model, image) return full_image
def test_tti(shape, space_order, kernel): """ This first test compare the solution of the acoustic wave-equation and the TTI wave-eqatuon with all anisotropy parametrs to 0. The two solutions should be the same. """ if kernel == 'shifted': space_order *= 2 to = 2 so = space_order // 2 if kernel == 'shifted' else space_order nbpml = 10 origin = [0. for _ in shape] spacing = [10. for _ in shape] vp = 1.5 * np.ones(shape) # Constant model for true velocity model = Model(origin=origin, shape=shape, vp=vp, spacing=spacing, nbpml=nbpml, space_order=space_order, epsilon=np.zeros(shape), delta=np.zeros(shape), theta=np.zeros(shape), phi=np.zeros(shape)) # Define seismic data and parameters f0 = .010 dt = model.critical_dt t0 = 0.0 tn = 350.0 time_range = TimeAxis(start=t0, stop=tn, step=dt) nt = time_range.num last = (nt - 2) % 3 indlast = [(last + 1) % 3, last % 3, (last - 1) % 3] # 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) acoustic = AcousticWaveSolver(model, source=source, receiver=receiver, time_order=2, space_order=so) rec, u1, _ = acoustic.forward(save=False) source.data.fill(0.) # Solvers acoustic = AcousticWaveSolver(model, source=source, receiver=receiver, time_order=2, space_order=so) solver_tti = AnisotropicWaveSolver(model, source=source, receiver=receiver, time_order=2, space_order=space_order) # Create new wavefield object restart forward computation u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=so) u.data[0:3, :] = u1.data[indlast, :] acoustic.forward(save=False, u=u, time_M=10, src=source) utti = TimeFunction(name='u', grid=model.grid, time_order=to, space_order=so) vtti = TimeFunction(name='v', grid=model.grid, time_order=to, space_order=so) utti.data[0:to + 1, :] = u1.data[indlast[:to + 1], :] vtti.data[0:to + 1, :] = u1.data[indlast[:to + 1], :] solver_tti.forward(u=utti, v=vtti, kernel=kernel, time_M=10, src=source) normal_u = u.data[:] normal_utti = .5 * utti.data[:] normal_vtti = .5 * vtti.data[:] res = linalg.norm((normal_u - normal_utti - normal_vtti).reshape(-1))**2 res /= np.linalg.norm(normal_u.reshape(-1))**2 log("Difference between acoustic and TTI with all coefficients to 0 %2.4e" % res) assert np.isclose(res, 0.0, atol=1e-4)
spacing=spacing, nbpml=40) model0 = demo_model('circle-isotropic', vp=2.5, vp_background=2.5, origin=origin, shape=shape, spacing=spacing, nbpml=40, grid=model.grid) # time t0 = 0. tn = 1000. f0 = 0.010 time_axis = TimeAxis(start=t0, stop=tn, step=model.critical_dt) nt = time_axis.num # source nshots = 9 src_coordinates = np.empty((1, 2)) source_locations = np.empty((nshots, 2), dtype=np.float32) source_locations[:, 0] = 30. source_locations[:, 1] = np.linspace(0., 1000, num=nshots) # receiver nreceivers = 101 rec_coordinates = np.empty((nreceivers, 2)) rec_coordinates[:, 1] = np.linspace(0, model.domain_size[0], num=nreceivers) rec_coordinates[:, 0] = 980.
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)