def test_default_dimension(self): d = Dimension(name='d') dd0 = DefaultDimension(name='d') assert d is not dd0 dd1 = DefaultDimension(name='d') assert dd0 is not dd1
def otf_dft(u, freq, dt, factor=None): """ On the fly DFT wavefield (frequency slices) and expression Parameters ---------- u: TimeFunction or Tuple Forward wavefield freq: Array Array of frequencies for on-the-fly DFT factor: int Subsampling factor for DFT """ if freq is None: return [], None # init dft_modes = [] # Subsampled dft time axis time = as_tuple(u)[0].grid.time_dim tsave, factor = sub_time(time, factor, dt=dt, freq=freq) # Frequencies nfreq = np.shape(freq)[0] freq_dim = DefaultDimension(name='freq_dim', default_value=nfreq) f = Function(name='f', dimensions=(freq_dim, ), shape=(nfreq, )) f.data[:] = np.array(freq[:]) # Get fourier atoms to avoid shitty perf cf = TimeFunction(name="cf", dimensions=(as_tuple(u)[0].grid.stepping_dim, freq_dim), shape=(3, nfreq), time_order=2) sf = TimeFunction(name="sf", dimensions=(as_tuple(u)[0].grid.stepping_dim, freq_dim), shape=(3, nfreq), time_order=2) # Pulsation omega_t = 2 * np.pi * f * tsave * factor * dt dft = [Eq(cf, cos(omega_t)), Eq(sf, sin(omega_t))] for wf in as_tuple(u): ufr = Function(name='ufr%s' % wf.name, dimensions=(freq_dim, ) + wf.indices[1:], grid=wf.grid, shape=(nfreq, ) + wf.shape[1:]) ufi = Function(name='ufi%s' % wf.name, dimensions=(freq_dim, ) + wf.indices[1:], grid=wf.grid, shape=(nfreq, ) + wf.shape[1:]) dft += [Inc(ufr, factor * cf * wf)] dft += [Inc(ufi, -factor * sf * wf)] dft_modes += [(ufr, ufi)] return dft, dft_modes
def freesurface(field, stencil_s, npml, forward=True): """ Generate the stencil that mirrors the field as a free surface modeling for the acoustic wave equation """ fs = DefaultDimension(name="fs", default_value=stencil_s) field_m = field.forward if forward else field.backward lhs = field_m.subs({field.indices[-1]: npml - fs - 1}) rhs = -field_m.subs({field.indices[-1]: npml + fs + 1}) return [Eq(lhs, rhs)]
def test_lower_func_as_ind(self): grid = Grid((11, 11)) x, y = grid.dimensions t = grid.stepping_dim h = DefaultDimension("h", default_value=10) u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2) oh = Function(name="ou", dimensions=(h, ), shape=(10, ), dtype=int) eq = [Eq(u.forward, u._subs(x, x + oh))] lowered = LoweredEq( Eq(u[t + 1, x + 2, y + 2], u[t, x + oh[h] + 2, y + 2])) with timed_region('x'): leq = Operator._lower_exprs(eq) assert leq[0] == lowered
def otf_dft(u, freq, dt, factor=None): """ On the fly DFT wavefield (frequency slices) and expression Parameters ---------- u: TimeFunction or Tuple Forward wavefield freq: Array Array of frequencies for on-the-fly DFT factor: int Subsampling factor for DFT """ if freq is None: return [], None # init dft = [] dft_modes = [] # Subsampled dft time axis time = as_tuple(u)[0].grid.time_dim tsave, factor = sub_time(time, factor, dt=dt, freq=freq) # Frequencies nfreq = freq.shape[0] freq_dim = DefaultDimension(name='freq_dim', default_value=nfreq) f = Function(name='f', dimensions=(freq_dim, ), shape=(nfreq, )) f.data[:] = freq[:] # Pulsation omega_t = 2 * np.pi * f * tsave * factor * dt for wf in as_tuple(u): ufr = Function(name='ufr%s' % wf.name, dimensions=(freq_dim, ) + wf.indices[1:], grid=wf.grid, shape=(nfreq, ) + wf.shape[1:]) ufi = Function(name='ufi%s' % wf.name, dimensions=(freq_dim, ) + wf.indices[1:], grid=wf.grid, shape=(nfreq, ) + wf.shape[1:]) dft += [Inc(ufr, factor * cos(omega_t) * wf)] dft += [Inc(ufi, -factor * sin(omega_t) * wf)] dft_modes += [(ufr, ufi)] return dft, dft_modes
def test_default_dimension(self): """Test that different DefaultDimensions have different hash value.""" dd0 = DefaultDimension(name='dd') dd1 = DefaultDimension(name='dd') assert hash(dd0) != hash(dd1)
def forward_modeling(model, src_coords, wavelet, rec_coords, save=False, space_order=8, nb=40, free_surface=False, op_return=False, dt=None): clear_cache() # If wavelet is file, read it if isinstance(wavelet, str): wavelet = np.load(wavelet) # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp # Create the forward wavefield if save is False and rec_coords is not None: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) else: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order, save=nt) # Set up PDE and rearrange ulaplace, rho = acoustic_laplacian(u, rho) H = symbols('H') eqn = m / rho * u.dt2 - H + damp * u.dt # Input source is wavefield if isinstance(wavelet, TimeFunction): wf_src = TimeFunction(name='wf_src', grid=model.grid, time_order=2, space_order=space_order, save=nt) wf_src._data = wavelet._data eqn -= wf_src # Rearrange expression stencil = solve(eqn, u.forward, simplify=False, rational=False)[0] expression = [Eq(u.forward, stencil.subs({H: ulaplace}))] # Free surface if free_surface is True: fs = DefaultDimension(name="fs", default_value=int(space_order / 2)) expression += [ Eq(u.forward.subs({u.indices[-1]: model.nbpml - fs - 1}), -u.forward.subs({u.indices[-1]: model.nbpml + fs + 1})) ] # Source symbol with input wavelet if src_coords is not None: src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, offset=model.nbpml, expr=src * rho * dt**2 / m) expression += src_term # Data is sampled at receiver locations if rec_coords is not None: rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u, offset=model.nbpml) expression += rec_term # Create operator and run set_log_level('ERROR') subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Forward%s" % randint(1e5)) if op_return is False: op() if rec_coords is None: return u else: return rec.data, u else: return op
def adjoint_modeling(model, src_coords, rec_coords, rec_data, space_order=8, nb=40, free_surface=False, dt=None): clear_cache() # If wavelet is file, read it if isinstance(rec_data, str): rec_data = np.load(rec_data) # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp # Create the adjoint wavefield if src_coords is not None: v = TimeFunction(name="v", grid=model.grid, time_order=2, space_order=space_order) else: v = TimeFunction(name="v", grid=model.grid, time_order=2, space_order=space_order, save=nt) # Set up PDE and rearrange vlaplace, rho = acoustic_laplacian(v, rho) H = symbols('H') eqn = m / rho * v.dt2 - H - damp * v.dt # Input data is wavefield if isinstance(rec_data, TimeFunction): wf_rec = TimeFunction(name='wf_rec', grid=model.grid, time_order=2, space_order=space_order, save=nt) wf_rec._data = rec_data._data eqn -= wf_rec stencil = solve(eqn, v.backward, simplify=False, rational=False)[0] expression = [Eq(v.backward, stencil.subs({H: vlaplace}))] # Free surface if free_surface is True: fs = DefaultDimension(name="fs", default_value=int(space_order / 2)) expression += [ Eq(v.forward.subs({v.indices[-1]: model.nbpml - fs - 1}), -v.forward.subs({v.indices[-1]: model.nbpml + fs + 1})) ] # Adjoint source is injected at receiver locations if rec_coords is not None: rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec.data[:] = rec_data[:] adj_src = rec.inject(field=v.backward, offset=model.nbpml, expr=rec * rho * dt**2 / m) expression += adj_src # Data is sampled at source locations if src_coords is not None: src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) adj_rec = src.interpolate(expr=v, offset=model.nbpml) expression += adj_rec # Create operator and run set_log_level('ERROR') subs = model.spacing_map subs[v.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Backward%s" % randint(1e5)) op() if src_coords is None: return v else: return src.data