def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, nb=40, isic=False, dt=None, free_surface=False): clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, dm, damp = model.m, model.rho, model.dm, model.damp # Create the forward and linearized wavefield u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=space_order) du = TimeFunction(name="du", grid=model.grid, time_order=2, space_order=space_order) if len(model.shape) == 2: x,y = u.space_dimensions else: x,y,z = u.space_dimensions # Set up PDEs and rearrange ulaplace, rho = acoustic_laplacian(u, rho) dulaplace, _ = acoustic_laplacian(du, rho) if isic: # Sum ((u.dx * d, / rho).dx for x in dimensions) # space_order//2 so that u.dx.dx has the same radius as u.laplace du_aux = sum([first_derivative(first_derivative(u, dim=d, fd_order=space_order//2) * dm / rho, fd_order=space_order//2, dim=d) for d in u.space_dimensions]) lin_source = dm /rho * u.dt2 * m - du_aux else: lin_source = dm / rho * u.dt2 stencil_u = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace) stencil_du = damp * (2.0 * du - damp * du.backward + dt**2 * rho / m * (dulaplace - lin_source)) expression_u = [Eq(u.forward, stencil_u)] expression_du = [Eq(du.forward, stencil_du)] # Define source symbol with wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, expr=src * rho * dt**2 / m) # Define receiver symbol rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=du) expression = expression_u + expression_du + src_term + rec_term # Free surface if free_surface is True: expression += freesurface(u, space_order//2, model.nbpml) expression += freesurface(du, space_order//2, model.nbpml) # Create operator and run set_log_level('ERROR') subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced') op() return rec.data
def __init__(self, model, data, source, nbpml=40, t_order=2, s_order=8, tsave=4.0): set_log_level('ERROR') self.model = model self.t_order = t_order self.s_order = s_order self.data = data self.source = source self.dtype = np.float32 # Time step can be \sqrt{3}=1.73 bigger with 4th order self.dt = self.model.critical_dt self.tsave = tsave if len(self.model.shape ) == 2 and self.source.receiver_coords.shape[1] == 3: self.source.receiver_coords = np.delete( self.source.receiver_coords, 1, 1) if len(self.model.shape ) == 2 and self.data.receiver_coords.shape[1] == 3: self.data.receiver_coords = np.delete(self.data.receiver_coords, 1, 1)
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) # Input data is wavefield full_q = 0 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 full_q = wf_rec stencil = damp * (2.0 * v - damp * v.forward + dt**2 * rho / m * (vlaplace + full_q)) expression = [Eq(v.backward, stencil)] # Free surface if free_surface is True: expression += freesurface(v, space_order//2, model.nbpml, forward=False) # 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, 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) 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') op() if src_coords is None: return v else: return src.data
def forward_freq_modeling(model, src_coords, wavelet, rec_coords, freq, space_order=8, nb=40, dt=None, factor=None): # Forward modeling with on-the-fly DFT of forward wavefields clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp freq_dim = Dimension(name='freq_dim') time = model.grid.time_dim if factor is None: factor = int(1 / (dt*4*np.max(freq))) tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) if factor==1: tsave = time else: tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) print("DFT subsampling factor: ", factor) # Create wavefields nfreq = freq.shape[0] u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) f = Function(name='f', dimensions=(freq_dim,), shape=(nfreq,)) f.data[:] = freq[:] ufr = Function(name='ufr', dimensions=(freq_dim,) + u.indices[1:], shape=(nfreq,) + model.shape_domain) ufi = Function(name='ufi', dimensions=(freq_dim,) + u.indices[1:], shape=(nfreq,) + model.shape_domain) ulaplace, rho = acoustic_laplacian(u, rho) # Set up PDE and rearrange stencil = damp * (2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace) expression = [Eq(u.forward, stencil)] expression += [Inc(ufr, factor*u*cos(2*np.pi*f*tsave*factor*dt))] expression += [Inc(ufi, -factor*u*sin(2*np.pi*f*tsave*factor*dt))] # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, expr=src * dt**2 / m) # Data is sampled at receiver locations rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u) # Create operator and run set_log_level('ERROR') expression += src_term + rec_term subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Forward%s" % randint(1e5)) op() return rec.data, ufr, ufi
def test_timesteps_per_at_run(): """ Check that each autotuning run (ie with a given block shape) takes ``autotuning.options['at_squeezer'] - data.time_order`` timesteps. in an operator performing an increment such as ``a[t + timeorder, ...] = f(a[t, ...], ...)``. """ buffer = StringIO() temporary_handler = logging.StreamHandler(buffer) logger.addHandler(temporary_handler) set_log_level('DEBUG') shape = (30, 30, 30) grid = Grid(shape=shape) x, y, z = grid.dimensions t = grid.stepping_dim # Function infield = Function(name='infield', grid=grid) infield.data[:] = np.arange(reduce(mul, shape), dtype=np.int32).reshape(shape) outfield = Function(name='outfield', grid=grid) stencil = Eq(outfield.indexify(), outfield.indexify() + infield.indexify() * 3.0) op = Operator(stencil, dle=('blocking', {'blockalways': True})) op(infield=infield, outfield=outfield, autotune=True) out = [i for i in buffer.getvalue().split('\n') if 'AutoTuner:' in i] assert len(out) == 4 assert all('in 1 time steps' in i for i in out) buffer.truncate(0) # TimeFunction with increasing time order for to in [1, 2, 4]: infield = TimeFunction(name='infield', grid=grid, time_order=to) infield.data[:] = np.arange(reduce(mul, infield.shape), dtype=np.int32).reshape(infield.shape) outfield = TimeFunction(name='outfield', grid=grid, time_order=to) stencil = Eq(outfield.indexed[t + to, x, y, z], outfield.indexify() + infield.indexify() * 3.0) op = Operator(stencil, dle=('blocking', {'blockalways': True})) op(infield=infield, outfield=outfield, autotune=True) out = [i for i in buffer.getvalue().split('\n') if 'AutoTuner:' in i] expected = options['at_squeezer'] - to assert len(out) == 4 assert all('in %d time steps' % expected in i for i in out) buffer.truncate(0) logger.removeHandler(temporary_handler) temporary_handler.flush() temporary_handler.close() buffer.flush() buffer.close() set_log_level('INFO')
def adjoint_modeling(model, src_coords, rec_coords, rec_data, space_order=8, nb=40, dt=None): clear_cache() # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp # Create the adjoint wavefield v = TimeFunction(name="v", grid=model.grid, time_order=2, space_order=space_order) # Set up PDE and rearrange eqn = m * v.dt2 - v.laplace - damp * v.dt stencil = solve(eqn, v.backward)[0] expression = [Eq(v.backward, stencil)] # Adjoint source is injected at receiver locations 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 * dt**2 / m) # Data is sampled at source locations src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) adj_rec = src.interpolate(expr=v, offset=model.nbpml) # Create operator and run set_log_level('ERROR') expression += adj_src + adj_rec op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Backward%s" % randint(1e5)) op(dt=dt) return src.data
def test_at_is_actually_working(shape, expected): """ Check that autotuning is actually running when switched on, in both 2D and 3D operators. """ grid = Grid(shape=shape) buffer = StringIO() temporary_handler = logging.StreamHandler(buffer) logger.addHandler(temporary_handler) set_log_level('DEBUG') infield = Function(name='infield', grid=grid) infield.data[:] = np.arange(reduce(mul, shape), dtype=np.int32).reshape(shape) outfield = Function(name='outfield', grid=grid) stencil = Eq(outfield.indexify(), outfield.indexify() + infield.indexify() * 3.0) op = Operator(stencil, dle=('blocking', { 'blockinner': True, 'blockalways': True })) # Expected 3 AT attempts for the given shape op(infield=infield, outfield=outfield, autotune=True) out = [i for i in buffer.getvalue().split('\n') if 'AutoTuner:' in i] assert len(out) == 4 # Now try the same with aggressive autotuning, which tries 9 more cases configuration.core['autotuning'] = 'aggressive' op(infield=infield, outfield=outfield, autotune=True) out = [i for i in buffer.getvalue().split('\n') if 'AutoTuner:' in i] assert len(out) == expected configuration.core['autotuning'] = configuration.core._defaults[ 'autotuning'] logger.removeHandler(temporary_handler) temporary_handler.flush() temporary_handler.close() buffer.flush() buffer.close() set_log_level('INFO')
def forward_modeling(model, src_coords, wavelet, rec_coords, save=False, space_order=8, nb=40, free_surface=False, op_return=False, u_return=False, dt=None, tsub_factor=1): clear_cache() # If wavelet is file, read it if isinstance(wavelet, str): wavelet = np.load(wavelet) # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp # Create the forward wavefield if save is False and rec_coords is not None: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) eqsave = [] elif save is True and tsub_factor > 1: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) time_subsampled = ConditionalDimension(name='t_sub', parent=u.grid.time_dim, factor=tsub_factor) nsave = (nt-1)//tsub_factor + 2 usave = TimeFunction(name='us', grid=model.grid, time_order=2, space_order=space_order, time_dim=time_subsampled, save=nsave) eqsave = [Eq(usave.forward, u.forward)] else: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order, save=nt) eqsave = [] # Set up PDE ulaplace, rho = acoustic_laplacian(u, rho) stencil = damp * ( 2.0 * u - damp * u.backward + dt**2 * rho / m * ulaplace) # Input source is wavefield if isinstance(wavelet, TimeFunction): wf_src = TimeFunction(name='wf_src', grid=model.grid, time_order=2, space_order=space_order, save=nt) wf_src._data = wavelet._data stencil -= wf_src # Rearrange expression expression = [Eq(u.forward, stencil)] # Data is sampled at receiver locations if rec_coords is not None: rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u) expression += rec_term # Create operator and run if save: expression += eqsave # Free surface kwargs = dict() if free_surface is True: expression += freesurface(u, space_order//2, model.nbpml) # Source symbol with input wavelet if src_coords is not None: src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, expr=src * rho * dt**2 / m) expression += src_term # Create operator and run set_log_level('ERROR') subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced') # Return data and wavefields if op_return is False: op() if save is True and tsub_factor > 1: if rec_coords is None: return usave else: return rec.data, usave else: if rec_coords is None: return u else: return rec.data, u # For optimal checkpointing, return operator only else: return op
def adjoint_freq_born(model, rec_coords, rec_data, freq, ufr, ufi, space_order=8, nb=40, dt=None, isic=False, factor=None): clear_cache() # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp nfreq = ufr.shape[0] time = model.grid.time_dim if factor is None: factor = int(1 / (dt * 4 * np.max(freq))) tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) if factor == 1: tsave = time else: tsave = ConditionalDimension(name='tsave', parent=model.grid.time_dim, factor=factor) dtf = factor * dt ntf = factor / nt print("DFT subsampling factor: ", factor) # Create the forward and adjoint wavefield v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order) f = Function(name='f', dimensions=(ufr.indices[0], ), shape=(nfreq, )) f.data[:] = freq[:] gradient = Function(name="gradient", grid=model.grid) # Set up PDE and rearrange eqn = m * v.dt2 - v.laplace - damp * v.dt stencil = solve(eqn, v.backward, simplify=False, rational=False)[0] expression = [Eq(v.backward, stencil)] # Data at receiver locations as adjoint source 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 * dt**2 / m) # Gradient update if isic is True: if len(model.shape) == 2: gradient_update = [ Eq( gradient, gradient + (2 * np.pi * f)**2 * ntf * (ufr * cos(2 * np.pi * f * tsave * dtf) - ufi * sin(2 * np.pi * f * tsave * dtf)) * v * model.m - (ufr.dx * cos(2 * np.pi * f * tsave * dtf) - ufi.dx * sin(2 * np.pi * f * tsave * dtf)) * v.dx * ntf - (ufr.dy * cos(2 * np.pi * f * tsave * dtf) - ufi.dy * sin(2 * np.pi * f * tsave * dtf)) * v.dy * ntf) ] else: gradient_update = [ Eq( gradient, gradient + (2 * np.pi * f)**2 * ntf * (ufr * cos(2 * np.pi * f * tsave * dtf) - ufi * sin(2 * np.pi * f * tsave * dtf)) * v * model.m - (ufr.dx * cos(2 * np.pi * f * tsave * dtf) - ufi.dx * sin(2 * np.pi * f * tsave * dtf)) * v.dx * ntf - (ufr.dy * cos(2 * np.pi * f * tsave * dtf) - ufi.dy * sin(2 * np.pi * f * tsave * dtf)) * v.dy * ntf - (ufr.dz * cos(2 * np.pi * f * tsave * dtf) - ufi.dz * sin(2 * np.pi * f * tsave * dtf)) * v.dz * ntf) ] else: gradient_update = [ Eq( gradient, gradient + (2 * np.pi * f)**2 / nt * (ufr * cos(2 * np.pi * f * tsave * dtf) - ufi * sin(2 * np.pi * f * tsave * dtf)) * v) ] # Create operator and run set_log_level('ERROR') expression += adj_src + gradient_update subs = model.spacing_map subs[v.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Gradient%s" % randint(1e5)) op() clear_cache() return gradient.data
def adjoint_born(model, rec_coords, rec_data, u=None, op_forward=None, is_residual=False, space_order=8, nb=40, isic=False, dt=None, n_checkpoints=None, maxmem=None): clear_cache() # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, rho, damp = model.m, model.rho, model.damp # Create adjoint wavefield and gradient v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order) gradient = Function(name='gradient', grid=model.grid) # Set up PDE and rearrange vlaplace, rho = acoustic_laplacian(v, rho) H = symbols('H') eqn = m / rho * v.dt2 - H - damp * v.dt stencil = solve(eqn, v.backward, simplify=False, rational=False)[0] expression = [Eq(v.backward, stencil.subs({H: vlaplace}))] # Data at receiver locations as adjoint source rec_g = Receiver(name='rec_g', grid=model.grid, ntime=nt, coordinates=rec_coords) if op_forward is None: rec_g.data[:] = rec_data[:] adj_src = rec_g.inject(field=v.backward, offset=model.nbpml, expr=rec_g * rho * dt**2 / m) # Gradient update if u is None: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) if isic is not True: gradient_update = [Eq(gradient, gradient - dt * u.dt2 / rho * v)] else: # sum u.dx * v.dx fo x in dimensions. # space_order//2 diff_u_v = sum([ first_derivative(u, dim=d, order=space_order // 2) * first_derivative(v, dim=d, order=space_order // 2) for d in u.space_dimensions ]) gradient_update = [ Eq(gradient, gradient - dt * (u * v.dt2 * m + diff_u_v) / rho) ] # Create operator and run set_log_level('ERROR') expression += adj_src + gradient_update subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Gradient%s" % randint(1e5)) # Optimal checkpointing if op_forward is not None: rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) cp = DevitoCheckpoint([u]) if maxmem is not None: n_checkpoints = int( np.floor(maxmem * 10**6 / (cp.size * u.data.itemsize))) wrap_fw = CheckpointOperator(op_forward, u=u, m=model.m, rec=rec) wrap_rev = CheckpointOperator(op, u=u, v=v, m=model.m, rec_g=rec_g) # Run forward wrp = Revolver(cp, wrap_fw, wrap_rev, n_checkpoints, nt - 2) wrp.apply_forward() # Residual and gradient if is_residual is True: # input data is already the residual rec_g.data[:] = rec_data[:] else: rec_g.data[:] = rec.data[:] - rec_data[:] # input is observed data fval = .5 * np.dot(rec_g.data[:].flatten(), rec_g.data[:].flatten()) * dt wrp.apply_reverse() else: op() clear_cache() if op_forward is not None and is_residual is not True: return fval, gradient.data else: return gradient.data
def adjoint_freq_born(model, rec_coords, rec_data, freq, ufr, ufi, space_order=8, nb=40, dt=None): clear_cache() # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp nfreq = ufr.shape[0] time = model.grid.time_dim # Create the forward and adjoint wavefield v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order) f = Function(name='f', dimensions=(ufr.indices[0], ), shape=(nfreq, )) f.data[:] = freq[:] gradient = Function(name="gradient", grid=model.grid) # Set up PDE and rearrange eqn = m * v.dt2 - v.laplace - damp * v.dt stencil = solve(eqn, v.backward)[0] expression = [Eq(v.backward, stencil)] # Data at receiver locations as adjoint source 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 * dt**2 / m) # Gradient update gradient_update = [ Eq( gradient, gradient + (2 * np.pi * f)**2 / nt * (ufr * cos(2 * np.pi * f * time * dt) - ufi * sin(2 * np.pi * f * time * dt)) * v) ] # Create operator and run set_log_level('ERROR') expression += adj_src + gradient_update op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Gradient%s" % randint(1e5)) op(dt=dt) clear_cache() return gradient.data
def forward_freq_modeling(model, src_coords, wavelet, rec_coords, freq, space_order=8, nb=40, dt=None): # Forward modeling with on-the-fly DFT of forward wavefields clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp freq_dim = Dimension(name='freq_dim') time = model.grid.time_dim # Create wavefields nfreq = freq.shape[0] u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) f = Function(name='f', dimensions=(freq_dim, ), shape=(nfreq, )) f.data[:] = freq[:] ufr = Function(name='ufr', dimensions=(freq_dim, ) + u.indices[1:], shape=(nfreq, ) + model.shape_domain) ufi = Function(name='ufi', dimensions=(freq_dim, ) + u.indices[1:], shape=(nfreq, ) + model.shape_domain) # Set up PDE and rearrange eqn = m * u.dt2 - u.laplace + damp * u.dt stencil = solve(eqn, u.forward)[0] expression = [Eq(u.forward, stencil)] expression += [Eq(ufr, ufr + u * cos(2 * np.pi * f * time * dt))] expression += [Eq(ufi, ufi - u * sin(2 * np.pi * f * time * dt))] # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, offset=model.nbpml, expr=src * dt**2 / m) # Data is sampled at receiver locations rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u, offset=model.nbpml) # Create operator and run set_log_level('ERROR') expression += src_term + rec_term op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Forward%s" % randint(1e5)) op(dt=dt) return rec.data, ufr, ufi
def adjoint_born(model, rec_coords, rec_data, u=None, op_forward=None, is_residual=False, space_order=8, nb=40, isic=False, dt=None): clear_cache() # Parameters nt = rec_data.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp # Create adjoint wavefield and gradient v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=space_order) gradient = Function(name='gradient', grid=model.grid) # Set up PDE and rearrange eqn = m * v.dt2 - v.laplace - damp * v.dt stencil = solve(eqn, v.backward)[0] expression = [Eq(v.backward, stencil)] # Data at receiver locations as adjoint source rec_g = Receiver(name='rec_g', grid=model.grid, ntime=nt, coordinates=rec_coords) if op_forward is None: rec_g.data[:] = rec_data[:] adj_src = rec_g.inject(field=v.backward, offset=model.nbpml, expr=rec_g * dt**2 / m) # Gradient update if u is None: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) if isic is not True: gradient_update = [Eq(gradient, gradient - u * v.dt2) ] # zero-lag cross-correlation imaging condition else: # linearized inverse scattering imaging condition (Op't Root et al. 2010; Whitmore and Crawley 2012) if len(model.shape) == 2: gradient_update = [ Eq(gradient, gradient - (u * v.dt2 * m + u.dx * v.dx + u.dy * v.dy)) ] else: gradient_update = [ Eq( gradient, gradient - (u * v.dt2 * m + u.dx * v.dx + u.dy * v.dy + u.dz * v.dz)) ] # Create operator and run set_log_level('ERROR') expression += adj_src + gradient_update op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Gradient%s" % randint(1e5)) # Optimal checkpointing if op_forward is not None: rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) cp = DevitoCheckpoint([u]) n_checkpoints = None wrap_fw = CheckpointOperator(op_forward, u=u, m=model.m.data, rec=rec, dt=dt) wrap_rev = CheckpointOperator(op, u=u, v=v, m=model.m.data, rec_g=rec_g, dt=dt) # Run forward wrp = Revolver(cp, wrap_fw, wrap_rev, n_checkpoints, nt - 2) wrp.apply_forward() # Residual and gradient if is_residual is True: # input data is already the residual rec_g.data[:] = rec_data[:] else: rec_g.data[:] = rec.data[:] - rec_data[:] # input is observed data fval = .5 * np.linalg.norm(rec_g.data[:])**2 wrp.apply_reverse() else: op(dt=dt) clear_cache() if op_forward is not None and is_residual is not True: return fval, gradient.data else: return gradient.data
def forward_modeling(model, src_coords, wavelet, rec_coords, save=False, space_order=8, nb=40, op_return=False, dt=None): clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, damp = model.m, model.damp # Create the forward wavefield if save is False: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order) else: u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=space_order, save=nt) # Set up PDE and rearrange eqn = m * u.dt2 - u.laplace + damp * u.dt stencil = solve(eqn, u.forward)[0] expression = [Eq(u.forward, stencil)] # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, offset=model.nbpml, expr=src * dt**2 / m) # Data is sampled at receiver locations rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=u, offset=model.nbpml) # Create operator and run set_log_level('ERROR') expression += src_term + rec_term op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Forward%s" % randint(1e5)) if op_return is False: op(dt=dt) return rec.data, u else: return op
def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, nb=40, isic=False, dt=None): clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, dm, damp = model.m, model.dm, model.damp # Create the forward and linearized wavefield u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=space_order) du = TimeFunction(name="du", grid=model.grid, time_order=2, space_order=space_order) if len(model.shape) == 2: x, y = u.space_dimensions else: x, y, z = u.space_dimensions # Set up PDEs and rearrange eqn = m * u.dt2 - u.laplace + damp * u.dt stencil1 = solve(eqn, u.forward)[0] if isic is not True: eqn_lin = m * du.dt2 - du.laplace + damp * du.dt + dm * u.dt2 # born modeling else: du_aux = sum([ first_derivative( first_derivative(u, dim=d, order=space_order // 2) * dm, order=space_order // 2, dim=d) for d in u.space_dimensions ]) eqn_lin = m * du.dt2 - du.laplace + damp * du.dt + (dm * u.dt2 * m - du_aux) if isic is not True: stencil2 = solve(eqn_lin, du.forward)[0] else: stencil2 = solve(eqn_lin, du.forward, simplify=False, rational=False)[0] expression_u = [Eq(u.forward, stencil1)] expression_du = [Eq(du.forward, stencil2)] # Define source symbol with wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, offset=model.nbpml, expr=src * dt**2 / m) # Define receiver symbol rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=du, offset=model.nbpml) # Create operator and run set_log_level('ERROR') expression = expression_u + src_term + expression_du + rec_term op = Operator(expression, subs=model.spacing_map, dse='advanced', dle='advanced', name="Born%s" % randint(1e5)) op(dt=dt) return rec.data
def 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
def forward_born(model, src_coords, wavelet, rec_coords, space_order=8, nb=40, isic=False, dt=None): clear_cache() # Parameters nt = wavelet.shape[0] if dt is None: dt = model.critical_dt m, rho, dm, damp = model.m, model.rho, model.dm, model.damp # Create the forward and linearized wavefield u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=space_order) du = TimeFunction(name="du", grid=model.grid, time_order=2, space_order=space_order) if len(model.shape) == 2: x, y = u.space_dimensions else: x, y, z = u.space_dimensions # Set up PDEs and rearrange ulaplace, rho = acoustic_laplacian(u, rho) dulaplace, _ = acoustic_laplacian(du, rho) H = symbols('H') S = symbols('S') eqn = m / rho * u.dt2 - H + damp * u.dt stencil1 = solve(eqn, u.forward, simplify=False, rational=False)[0] eqn_lin = m / rho * du.dt2 - H + damp * du.dt + S if isic: # Sum ((u.dx * d, / rho).dx for x in dimensions) # space_order//2 so that u.dx.dx has the same radius as u.laplace du_aux = sum([ first_derivative( first_derivative(u, dim=d, order=space_order // 2) * dm / rho, order=space_order // 2, dim=d) for d in u.space_dimensions ]) lin_source = dm / rho * u.dt2 * m - du_aux else: lin_source = dm / rho * u.dt2 stencil2 = solve(eqn_lin, du.forward, simplify=False, rational=False)[0] expression_u = [Eq(u.forward, stencil1.subs({H: ulaplace}))] expression_du = [ Eq(du.forward, stencil2.subs({ H: dulaplace, S: lin_source })) ] # Define source symbol with wavelet src = PointSource(name='src', grid=model.grid, ntime=nt, coordinates=src_coords) src.data[:] = wavelet[:] src_term = src.inject(field=u.forward, offset=model.nbpml, expr=src * rho * dt**2 / m) # Define receiver symbol rec = Receiver(name='rec', grid=model.grid, ntime=nt, coordinates=rec_coords) rec_term = rec.interpolate(expr=du, offset=model.nbpml) # Create operator and run set_log_level('ERROR') expression = expression_u + src_term + expression_du + rec_term subs = model.spacing_map subs[u.grid.time_dim.spacing] = dt op = Operator(expression, subs=subs, dse='advanced', dle='advanced', name="Born%s" % randint(1e5)) op() return rec.data
configuration.add('platform', 'cpu64', list(platform_registry), callback=lambda i: platform_registry[i]()) configuration.add('compiler', 'custom', list(compiler_registry), callback=lambda i: compiler_registry[i]()) configuration.add('backend', 'core', list(backends_registry), callback=init_backend) # Should Devito run a first-touch Operator upon data allocation? configuration.add('first-touch', 0, [0, 1], lambda i: bool(i), False) # Should Devito ignore any unknown runtime arguments supplied to Operator.apply(), # or rather raise an exception (the default behaviour)? configuration.add('ignore-unknowns', 0, [0, 1], lambda i: bool(i), False) # Setup log level configuration.add('log-level', 'INFO', list(logger_registry), lambda i: set_log_level(i), False) # Escape hatch for custom kernels. The typical use case is as follows: one lets # Devito generate code for an Operator; then, once the session is over, the # generated file is manually modified (e.g., for debugging or for performance # experimentation); finally, when re-running the same program, Devito won't # overwrite the user-modified files (thus entirely bypassing code generation), # and will instead use the custom kernel configuration.add('jit-backdoor', 0, [0, 1], lambda i: bool(i), False) # Execution mode setup def _reinit_compiler(val): # noqa # Force re-build the compiler configuration['compiler'].__init__(suffix=configuration['compiler'].suffix, mpi=configuration['mpi']) return bool(val) if isinstance(val, int) else val
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
import os import sys if not "DEVITO_OPENMP" in os.environ or os.environ["DEVITO_OPENMP"] != "1": print( "*** WARNING: Devito OpenMP environment variable has not been set ***", file=sys.stderr) import numpy as np from sympy import Matrix, Eq, solve import progressbar from devito import TimeData, Operator, t, x, y, z, logger as devito_logger, parameters as devito_parameters from . import sim devito_logger.set_log_level('WARNING') def vector_laplacian(u): return Matrix([ u[0].dx2 + u[0].dy2 + u[0].dz2, u[1].dx2 + u[1].dy2 + u[1].dz2, u[2].dx2 + u[2].dy2 + u[2].dz2 ]) def vector_gradient(u): return u[0].dx**2 + u[0].dy**2 + u[0].dz**2 + u[1].dx**2 + u[1].dy**2 + u[ 1].dz**2 + u[2].dx**2 + u[2].dy**2 + u[2].dz**2 def curl(u):
callback=lambda i: compiler_registry[i]()) configuration.add('backend', 'core', list(backends_registry), callback=init_backend) # Should Devito run a first-touch Operator upon data allocation? configuration.add('first-touch', 0, [0, 1], lambda i: bool(i), False) # Should Devito ignore any unknown runtime arguments supplied to Operator.apply(), # or rather raise an exception (the default behaviour)? configuration.add('ignore-unknowns', 0, [0, 1], lambda i: bool(i), False) # Setup log level configuration.add('log-level', 'INFO', list(logger_registry), lambda i: set_log_level(i), False) # Escape hatch for custom kernels. The typical use case is as follows: one lets # Devito generate code for an Operator; then, once the session is over, the # generated file is manually modified (e.g., for debugging or for performance # experimentation); finally, when re-running the same program, Devito won't # overwrite the user-modified files (thus entirely bypassing code generation), # and will instead use the custom kernel configuration.add('jit-backdoor', 0, [0, 1], lambda i: bool(i), False) # Enable/disable automatic padding for allocated data configuration.add('autopadding', False, [False, True]) # Execution mode setup def _reinit_compiler(val): # noqa
raise NotImplementedError("Devito doesn't support configuration via file.") # Parameters casting and checking for k, v in list(configuration.items()): try: val = int(v) except (TypeError, ValueError): val = v if val not in accepted[k]: raise ValueError("Illegal configuration parameter (%s, %s). " "Accepted: %s" % (k, val, str(accepted[k]))) configuration[k] = val # Global setup # - Logger configuration.set_update_function('log_level', lambda i: set_log_level(i)) # - Compilation toolchain configuration['compiler'] = set_compiler(configuration['compiler'], configuration['openmp']) configuration['openmp'] = bool(configuration['openmp']) configuration.initialize() def print_defaults(): """Print the environment variables accepted by Devito, their default value, as well as all of the accepted values.""" for k, v in env_vars_mapper.items(): debug('%s: %s. Default: %s' % (k, accepted[v], defaults[v]))