def src_rec(v, tau, model, geometry): """ Source injection and receiver interpolation """ s = model.grid.time_dim.spacing # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec1 = Receiver(name='rec1', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) rec2 = Receiver(name='rec2', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # The source injection term src_xx = src.inject(field=tau[0, 0].forward, expr=src * s) src_zz = src.inject(field=tau[-1, -1].forward, expr=src * s) src_expr = src_xx + src_zz if model.grid.dim == 3: src_yy = src.inject(field=tau[1, 1].forward, expr=src * s) src_expr += src_yy # Create interpolation expression for receivers rec_term1 = rec1.interpolate(expr=tau[-1, -1]) rec_term2 = rec2.interpolate(expr=div(v)) return src_expr + rec_term1 + rec_term2
def src_rec(p, model, geometry, **kwargs): """ Forward case: Source injection and receiver interpolation Adjoint case: Receiver injection and source interpolation """ dt = model.grid.time_dim.spacing m = model.m # Source symbol with input wavelet src = PointSource(name="src", grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) forward = kwargs.get('forward', True) time_order = p.time_order if forward: # The source injection term if(time_order == 1): src_term = src.inject(field=p.forward, expr=src * dt) else: src_term = src.inject(field=p.forward, expr=src * dt**2 / m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=p) else: # Construct expression to inject receiver values if(time_order == 1): rec_term = rec.inject(field=p.backward, expr=rec * dt) else: rec_term = rec.inject(field=p.backward, expr=rec * dt**2 / m) # Create interpolation expression for the adjoint-source src_term = src.interpolate(expr=p) return src_term + rec_term
def src_rec(vx, vy, vz, txx, tyy, tzz, model, geometry): """ Source injection and receiver interpolation """ s = model.grid.time_dim.spacing # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec1 = Receiver(name='rec1', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) rec2 = Receiver(name='rec2', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # The source injection term src_xx = src.inject(field=txx.forward, expr=src * s) src_zz = src.inject(field=tzz.forward, expr=src * s) src_expr = src_xx + src_zz if model.grid.dim == 3: src_yy = src.inject(field=tyy.forward, expr=src * s) src_expr += src_yy # Create interpolation expression for receivers rec_term1 = rec1.interpolate(expr=tzz) if model.grid.dim == 2: rec_expr = vx.dx + vz.dy else: rec_expr = vx.dx + vy.dy + vz.dz rec_term2 = rec2.interpolate(expr=rec_expr) return src_expr + rec_term1 + rec_term2
def ForwardOperator(model, source, receiver, space_order=4, save=False, kernel='centered', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param src: None ot IShot() (not currently supported properly) :param data: IShot() object containing the acquisition geometry and field data :param: time_order: Time discretization order :param: spc_order: Space discretization order """ dt = model.grid.time_dim.spacing m = model.m time_order = 1 if kernel == 'staggered' else 2 # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, save=source.nt if save else None, time_order=time_order, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, save=source.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', grid=model.grid, time_range=source.time_range, npoint=source.npoint) rec = Receiver(name='rec', grid=model.grid, time_range=receiver.time_range, npoint=receiver.npoint) # FD kernels of the PDE FD_kernel = kernels[(kernel, len(model.shape))] stencils = FD_kernel(model, u, v, space_order) # Source and receivers stencils += src.inject(field=u.forward, expr=src * dt**2 / m, offset=model.nbpml) stencils += src.inject(field=v.forward, expr=src * dt**2 / m, offset=model.nbpml) stencils += rec.interpolate(expr=u + v, offset=model.nbpml) # Substitute spacing terms to reduce flops return Operator(stencils, subs=model.spacing_map, name='ForwardTTI', **kwargs)
def ForwardOperator(model, geometry, space_order=4, save=False, kernel='OT2', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param space_order: Space discretization order :param save: Saving flag, True saves all time steps, False only the three """ m, damp = model.m, model.damp # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, save=geometry.nt if save else None, time_order=2, space_order=space_order) src = PointSource(name='src', grid=geometry.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=geometry.grid, time_range=geometry.time_axis, npoint=geometry.nrec) s = model.grid.stepping_dim.spacing eqn = iso_stencil(u, m, s, damp, kernel) # Construct expression to inject source values src_term = src.inject(field=u.forward, expr=src * s**2 / m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u) # Substitute spacing terms to reduce flops return Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward', **kwargs)
def td_born_adjoint_op(model, geometry, time_order, space_order): nt = geometry.nt # Define the wavefields with the size of the model and the time dimension u = TimeFunction( name='u', grid=model.grid, time_order=time_order, space_order=space_order, save=nt ) # Define the wave equation pde = model.m * u.dt2 - u.laplace + model.damp * u.dt.T # Use `solve` to rearrange the equation into a stencil expression stencil = Eq(u.backward, solve(pde, u.backward), subdomain=model.grid.subdomains['physdomain']) # Inject at receivers born_data_rec = PointSource( name='born_data_rec', grid=model.grid, time_range=geometry.time_axis, coordinates=geometry.rec_positions ) dt = Constant(name='dt') rec_term = born_data_rec.inject(field=u.backward, expr=born_data_rec * (dt ** 2) / model.m) return Operator([stencil] + rec_term, subs=model.spacing_map)
def ImagingOperator(model, image): # Define the wavefield with the size of the model and the time dimension v = TimeFunction(name='v', grid=model.grid, time_order=2, space_order=4) u = TimeFunction(name='u', grid=model.grid, time_order=2, space_order=4, save=geometry.nt) # Define the wave equation, but with a negated damping term eqn = model.m * v.dt2 - v.laplace - model.damp * v.dt # Use `solve` to rearrange the equation into a stencil expression stencil = Eq(v.backward, solve(eqn, v.backward)) # Define residual injection at the location of the forward receivers dt = model.critical_dt residual = PointSource(name='residual', grid=model.grid, time_range=geometry.time_axis, coordinates=geometry.rec_positions) res_term = residual.inject(field=v, expr=residual * dt**2 / model.m) # Correlate u and v for the current time step and add it to the image image_update = Eq(image, image - u * v) return Operator([stencil] + res_term + [image_update], subs=model.spacing_map)
def ImagingOperator(geometry, image, space_order, save=True): stagg_u = stagg_v = None u = TimeFunction(name='u', grid=geometry.model.grid, staggered=stagg_u, save=geometry.nt if save else None, time_order=2, space_order=space_order) v = TimeFunction(name='v', grid=geometry.model.grid, staggered=stagg_v, save=geometry.nt if save else None, time_order=2, space_order=space_order) uu = TimeFunction(name='uu', grid=geometry.model.grid, staggered=stagg_u, save=None, time_order=2, space_order=space_order) vv = TimeFunction(name='vv', grid=geometry.model.grid, staggered=stagg_v, save=None, time_order=2, space_order=space_order) dt = geometry.dt residual = PointSource(name='residual', grid=geometry.model.grid, time_range=geometry.time_axis, coordinates=geometry.rec_positions) stencils = kernel_centered_2d(geometry.model, uu, vv, space_order, forward=False) stencils += residual.inject(field=uu.backward, expr=residual * dt**2 / geometry.model.m) stencils += residual.inject(field=vv.backward, expr=residual * dt**2 / geometry.model.m) # Correlate u and v for the current time step and add it to the image image_update = Eq(image, image - (u.dt2*uu + v.dt2*vv)) return Operator(stencils + [image_update], subs=geometry.model.spacing_map)
def ForwardOperator(model, source, receiver, space_order=4, save=False, kernel='OT2', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param space_order: Space discretization order :param save: Saving flag, True saves all time steps, False only the three """ m, damp = model.m, model.damp # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, save=source.nt if save else None, time_order=2, space_order=space_order) src = PointSource(name='src', grid=model.grid, time_range=source.time_range, npoint=source.npoint) rec = Receiver(name='rec', grid=model.grid, time_range=receiver.time_range, npoint=receiver.npoint) s = model.grid.stepping_dim.spacing eqn = iso_stencil(u, m, s, damp, kernel) # Construct expression to inject source values src_term = src.inject(field=u.forward, expr=src * s**2 / m, offset=model.nbpml) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u, offset=model.nbpml) # Substitute spacing terms to reduce flops return Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward', **kwargs)
def BornOperator(model, source, receiver, space_order=4, kernel='OT2', **kwargs): """ Constructor method for the Linearized Born operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param time_order: Time discretization order :param space_order: Space discretization order """ m, damp = model.m, model.damp # Create source and receiver symbols src = PointSource(name='src', grid=model.grid, time_range=source.time_range, npoint=source.npoint) rec = Receiver(name='rec', grid=model.grid, time_range=receiver.time_range, npoint=receiver.npoint) # Create wavefields and a dm field u = TimeFunction(name="u", grid=model.grid, save=None, time_order=2, space_order=space_order) U = TimeFunction(name="U", grid=model.grid, save=None, time_order=2, space_order=space_order) dm = Function(name="dm", grid=model.grid, space_order=0) s = model.grid.stepping_dim.spacing eqn1 = iso_stencil(u, m, s, damp, kernel) eqn2 = iso_stencil(U, m, s, damp, kernel, q=-dm * u.dt2) # Add source term expression for u source = src.inject(field=u.forward, expr=src * s**2 / m, offset=model.nbpml) # Create receiver interpolation expression from U receivers = rec.interpolate(expr=U, offset=model.nbpml) # Substitute spacing terms to reduce flops return Operator(eqn1 + source + eqn2 + receivers, subs=model.spacing_map, name='Born', **kwargs)
def ForwardOperator(model, geometry, space_order=4, save=False, kernel='OT2', **kwargs): """ Construct a forward modelling operator in an acoustic medium. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. space_order : int, optional Space discretization order. save : int or Buffer, optional Saving flag, True saves all time steps. False saves three timesteps. Defaults to False. kernel : str, optional Type of discretization, 'OT2' or 'OT4'. """ m = model.m # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, save=geometry.nt if save else None, time_order=2, space_order=space_order) src = PointSource(name='src', grid=geometry.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=geometry.grid, time_range=geometry.time_axis, npoint=geometry.nrec) s = model.grid.stepping_dim.spacing eqn = iso_stencil(u, model, kernel) # Construct expression to inject source values src_term = src.inject(field=u.forward, expr=src * s**2 / m) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u) # Substitute spacing terms to reduce flops return Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward', **kwargs)
def src_rec(vx, vy, vz, qx, qy, qz, txx, tyy, tzz, p, model, geometry): """ Source injection and receiver interpolation """ dt = model.grid.time_dim.spacing # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec1 = Receiver(name='rec1', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) rec2 = Receiver(name='rec2', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) M = model.M # The source injection term #src_xx = src.inject(field=txx.forward, expr=src * (1.0 - model.phi) * dt, offset=model.nbpml) #src_zz = src.inject(field=tzz.forward, expr=src * (1.0 - model.phi) * dt, offset=model.nbpml) #src_xx = src.inject(field=txx.forward, expr=src * dt) #src_zz = src.inject(field=tzz.forward, expr=src * dt) src_pp = src.inject(field=p.forward, expr=src * M) #src_expr = src_xx + src_zz + src_pp src_expr = src_pp if model.grid.dim == 3: src_yy = src.inject(field=tyy.forward, expr=src * (1.0 - model.phi) * dt, offset=model.nbpml) src_expr += src_yy # Create interpolation expression for receivers rec_term1 = rec1.interpolate(expr=p, offset=model.nbpml) if model.grid.dim == 2: rec_expr = vx.dx + vz.dy else: rec_expr = vx.dx + vy.dy + vz.dz rec_term2 = rec2.interpolate(expr=rec_expr, offset=model.nbpml) return src_expr + rec_term1 + rec_term2
def ForwardOperator(model, geometry, space_order=4, save=False, kernel='centered', **kwargs): """ Construct an forward modelling operator in an tti media. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. space_order : int, optional Space discretization order. save : int or Buffer, optional Saving flag, True saves all time steps. False saves three timesteps. Defaults to False. kernel : str, optional Type of discretization, centered or shifted """ dt = model.grid.time_dim.spacing m = model.m time_order = 1 if kernel == 'staggered' else 2 if kernel == 'staggered': stagg_u = stagg_v = NODE else: stagg_u = stagg_v = None # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, staggered=stagg_u, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, staggered=stagg_v, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # FD kernels of the PDE FD_kernel = kernels[(kernel, len(model.shape))] stencils = FD_kernel(model, u, v, space_order) # Source and receivers expr = src * dt / m if kernel == 'staggered' else src * dt**2 / m stencils += src.inject(field=u.forward, expr=expr) stencils += src.inject(field=v.forward, expr=expr) stencils += rec.interpolate(expr=u + v) # Substitute spacing terms to reduce flops return Operator(stencils, subs=model.spacing_map, name='ForwardTTI', **kwargs)
def ForwardOperator(model, geometry, space_order=4, save=False, kernel='centered', **kwargs): """ Construct an forward modelling operator in an acoustic media. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. data : ndarray IShot() object containing the acquisition geometry and field data. time_order : int Time discretization order. space_order : int Space discretization order. """ dt = model.grid.time_dim.spacing m = model.m time_order = 1 if kernel == 'staggered' else 2 if kernel == 'staggered': dims = model.space_dimensions stagg_u = (-dims[-1]) stagg_v = (-dims[0], -dims[1]) if model.grid.dim == 3 else (-dims[0]) else: stagg_u = stagg_v = None # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, staggered=stagg_u, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, staggered=stagg_v, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # FD kernels of the PDE FD_kernel = kernels[(kernel, len(model.shape))] stencils = FD_kernel(model, u, v, space_order) # Source and receivers stencils += src.inject(field=u.forward, expr=src * dt**2 / m) stencils += src.inject(field=v.forward, expr=src * dt**2 / m) stencils += rec.interpolate(expr=u + v) # Substitute spacing terms to reduce flops return Operator(stencils, subs=model.spacing_map, name='ForwardTTI', **kwargs)
def ForwardOperator(model, source, receiver, time_order=2, space_order=4, save=False, **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param time_order: Time discretization order :param space_order: Space discretization order :param save : Saving flag, True saves all time steps, False only the three """ m, damp = model.m, model.damp # Create symbols for forward wavefield, source and receivers u = TimeData(name='u', shape=model.shape_domain, time_dim=source.nt, time_order=time_order, space_order=space_order, save=save, dtype=model.dtype) src = PointSource(name='src', ntime=source.nt, ndim=source.ndim, npoint=source.npoint) rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim, npoint=receiver.npoint) if time_order == 2: biharmonic = 0 dt = model.critical_dt else: biharmonic = u.laplace2(1/m) dt = 1.73 * model.critical_dt # Derive both stencils from symbolic equation: # Create the stencil by hand instead of calling numpy solve for speed purposes # Simple linear solve of a u(t+dt) + b u(t) + c u(t-dt) = L for u(t+dt) stencil = 1 / (2 * m + s * damp) * ( 4 * m * u + (s * damp - 2 * m) * u.backward + 2 * s**2 * (u.laplace + s**2 / 12 * biharmonic)) eqn = [Eq(u.forward, stencil)] # Construct expression to inject source values # Note that src and field terms have differing time indices: # src[time, ...] - always accesses the "unrolled" time index # u[ti + 1, ...] - accesses the forward stencil value ti = u.indices[0] src_term = src.inject(field=u, u_t=ti + 1, offset=model.nbpml, expr=src * dt**2 / m, p_t=time) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u, u_t=ti, offset=model.nbpml) return Operator(eqn + src_term + rec_term, subs={s: dt, h: model.get_spacing()}, time_axis=Forward, name='Forward', **kwargs)
def ForwardOperator(model, geometry, space_order=4, save=False, kernel='centered', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param src: None ot IShot() (not currently supported properly) :param data: IShot() object containing the acquisition geometry and field data :param: time_order: Time discretization order :param: spc_order: Space discretization order """ dt = model.grid.time_dim.spacing m = model.m time_order = 1 if kernel == 'staggered' else 2 if kernel == 'staggered': dims = model.space_dimensions stagg_u = (-dims[-1]) stagg_v = (-dims[0], -dims[1]) if model.grid.dim == 3 else (-dims[0]) else: stagg_u = stagg_v = None # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, staggered=stagg_u, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, staggered=stagg_v, save=geometry.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # FD kernels of the PDE FD_kernel = kernels[(kernel, len(model.shape))] stencils = FD_kernel(model, u, v, space_order) # Source and receivers stencils += src.inject(field=u.forward, expr=src * dt**2 / m) stencils += src.inject(field=v.forward, expr=src * dt**2 / m) stencils += rec.interpolate(expr=u + v) # Substitute spacing terms to reduce flops return Operator(stencils, subs=model.spacing_map, name='ForwardTTI', **kwargs)
def BornOperator(model, source, receiver, time_order=2, space_order=4, **kwargs): """ Constructor method for the Linearized Born operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param time_order: Time discretization order :param space_order: Space discretization order """ m, damp = model.m, model.damp # Create source and receiver symbols src = PointSource(name='src', ntime=source.nt, ndim=source.ndim, npoint=source.npoint) rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim, npoint=receiver.npoint) # Create wavefields and a dm field u = TimeData(name="u", shape=model.shape_domain, save=False, time_order=time_order, space_order=space_order, dtype=model.dtype) U = TimeData(name="U", shape=model.shape_domain, save=False, time_order=time_order, space_order=space_order, dtype=model.dtype) dm = DenseData(name="dm", shape=model.shape_domain, dtype=model.dtype) if time_order == 2: biharmonicu = 0 biharmonicU = 0 dt = model.critical_dt else: biharmonicu = u.laplace2(1/m) biharmonicU = U.laplace2(1/m) dt = 1.73 * model.critical_dt # Derive both stencils from symbolic equation # first_eqn = m * u.dt2 - u.laplace + damp * u.dt # second_eqn = m * U.dt2 - U.laplace - dm* u.dt2 + damp * U.dt stencil1 = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * u + (s * damp - 2.0 * m) * u.backward + 2.0 * s ** 2 * (u.laplace + s**2 / 12 * biharmonicu)) stencil2 = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * U + (s * damp - 2.0 * m) * U.backward + 2.0 * s ** 2 * (U.laplace + s**2 / 12 * biharmonicU - dm * u.dt2)) eqn1 = Eq(u.forward, stencil1) eqn2 = Eq(U.forward, stencil2) # Add source term expression for u ti = u.indices[0] source = src.inject(field=u, u_t=ti + 1, offset=model.nbpml, expr=src * dt * dt / m, p_t=time) # Create receiver interpolation expression from U receivers = rec.interpolate(expr=U, u_t=ti, offset=model.nbpml) return Operator([eqn1] + source + [eqn2] + receivers, subs={s: dt, h: model.get_spacing()}, time_axis=Forward, name='Born', **kwargs)
def ForwardOperator(model, source, receiver, time_order=2, space_order=4, save=False, kernel='centered', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param src: None ot IShot() (not currently supported properly) :param data: IShot() object containing the acquisition geometry and field data :param: time_order: Time discretization order :param: spc_order: Space discretization order """ dt = model.critical_dt m, damp, epsilon, delta, theta, phi = (model.m, model.damp, model.epsilon, model.delta, model.theta, model.phi) # Create symbols for forward wavefield, source and receivers u = TimeData(name='u', shape=model.shape_domain, dtype=model.dtype, save=save, time_dim=source.nt if save else None, time_order=time_order, space_order=space_order) v = TimeData(name='v', shape=model.shape_domain, dtype=model.dtype, save=save, time_dim=source.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', ntime=source.nt, ndim=source.ndim, npoint=source.npoint) rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim, npoint=receiver.npoint) # Tilt and azymuth setup ang0 = cos(theta) ang1 = sin(theta) ang2 = 0 ang3 = 0 if len(model.shape) == 3: ang2 = cos(phi) ang3 = sin(phi) FD_kernel = kernels[(kernel, len(model.shape))] H0, Hz = FD_kernel(u, v, ang0, ang1, ang2, ang3, space_order) s = t.spacing # Stencils stencilp = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * u + (s * damp - 2.0 * m) * u.backward + 2.0 * s ** 2 * (epsilon * H0 + delta * Hz)) stencilr = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * v + (s * damp - 2.0 * m) * v.backward + 2.0 * s ** 2 * (delta * H0 + Hz)) first_stencil = Eq(u.forward, stencilp) second_stencil = Eq(v.forward, stencilr) stencils = [first_stencil, second_stencil] # Source and receivers stencils += src.inject(field=u.forward, expr=src * dt * dt / m, offset=model.nbpml) stencils += src.inject(field=v.forward, expr=src * dt * dt / m, offset=model.nbpml) stencils += rec.interpolate(expr=u + v, offset=model.nbpml) # Add substitutions for spacing (temporal and spatial) subs = dict([(t.spacing, dt)] + [(time.spacing, dt)] + [(i.spacing, model.get_spacing()[j]) for i, j in zip(u.indices[1:], range(len(model.shape)))]) # Operator return Operator(stencils, subs=subs, name='ForwardTTI', **kwargs)
def ForwardOperator(model, geometry, space_order=4, time_order = 1, save=False, **kwargs): """ Construct method for the forward modelling operator in an elastic media. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. space_order : int, optional Space discretization order. save : int or Buffer Saving flag, True saves all time steps, False saves three buffered indices (last three time steps). Defaults to False. """ v = VectorTimeFunction(name='v', grid=model.grid, space_order=space_order, time_order=time_order) tau = TensorTimeFunction(name='tau', grid=model.grid, space_order=space_order, time_order=time_order) ## Symbolic physical parameters used from the model irho = model.irho c11 = model.c11 c33 = model.c33 c44 = model.c44 c66 = model.c66 c13 = model.c13 # Model critical timestep computed from CFL condition for VTI media ts = model.grid.stepping_dim.spacing damp = model.damp.data # Particle Velocity for each direction u_vx = Eq(v[0].forward, damp*v[0] + damp*ts*irho*(tau[0,0].dx + tau[1,0].dy + tau[2,0].dz) ) u_vy = Eq(v[1].forward, damp*v[1] + damp*ts*irho*(tau[0,1].dx + tau[1,1].dy + tau[1,2].dz) ) u_vz = Eq(v[2].forward, damp*v[2] + damp*ts*irho*(tau[0,2].dx + tau[2,1].dy + tau[2,2].dz) ) # Stress for each direction in VTI Media: u_txx = Eq(tau[0,0].forward, damp*tau[0,0] + damp*ts*(c11*v[0].forward.dx + c11*v[1].forward.dy - 2*c66*v[1].forward.dy + c13*v[2].forward.dz) ) u_tyy = Eq(tau[1,1].forward, damp*tau[1,1] + damp*ts*(c11*v[0].forward.dx - 2*c66*v[0].forward.dx + c11*v[1].forward.dy + c13*v[2].forward.dz) ) u_tzz = Eq(tau[2,2].forward, damp*tau[2,2] + damp*ts*(c13*v[0].forward.dx + c13*v[1].forward.dy + c33*v[2].forward.dz) ) u_txz = Eq(tau[0,2].forward, damp*tau[0,2] + damp*ts*(c44*v[2].forward.dx + c44*v[0].forward.dz) ) u_tyz = Eq(tau[1,2].forward, damp*tau[1,2] + damp*ts*(c44*v[2].forward.dy + c44*v[1].forward.dz) ) u_txy = Eq(tau[0,1].forward, damp*tau[0,1] + damp*ts*(c66*v[1].forward.dx + c66*v[0].forward.dy) ) stencil = [u_vx, u_vy, u_vz, u_txx, u_tyy, u_tzz, u_txz, u_tyz, u_txy] #srcrec = src_rec(v, tau, model, geometry) src = PointSource(name='src', grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name='rec', grid=geometry.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # The source injection term src_xx = src.inject(field=tau[0, 0].forward, expr=src * ts) src_zz = src.inject(field=tau[-1, -1].forward, expr=src * ts) src_term = src_xx + src_zz if model.grid.dim == 3: src_yy = src.inject(field=tau[1, 1].forward, expr=src * ts) src_term += src_yy # Create interpolation expression for receivers rec_term = rec.interpolate(expr=v) srcrec = src_term + rec_term pde = stencil + srcrec # Substitute spacing terms to reduce flops op = Operator(pde, subs=model.spacing_map, name="ForwardElasticVTI", **kwargs) return op
# Recs are distributed across model, at depth of 20 m. z_extent, _ = model.domain_size z_locations = np.linspace(0, z_extent, num=nreceivers) rec_coords = np.array([(980, z) for z in z_locations]) # NOT FOR MANUSCRIPT from examples.seismic import PointSource residual = PointSource(name='residual', ntime=nt, grid=model.grid, coordinates=rec_coords) res_term = residual.inject(field=v.backward, expr=residual * dt**2 / model.m, offset=model.nbpml) # NOT FOR MANUSCRIPT 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)
def ForwardOperator(model, geometry, space_order=4, kernel='blanch_symes', save=False, **kwargs): """ Construct method for the forward modelling operator in a viscoacoustic media. Parameters ---------- model : Model Object containing the physical parameters. geometry : AcquisitionGeometry Geometry object that contains the source (SparseTimeFunction) and receivers (SparseTimeFunction) and their position. space_order : int, optional Space discretization order. kernel : selects a visco-acoustic equation from the options below: blanch_symes - Blanch and Symes (1995) / Dutta and Schuster (2014) viscoacoustic equation ren - Ren et al. (2014) viscoacoustic equation deng_mcmechan - Deng and McMechan (2007) viscoacoustic equation Defaults to blanch_symes. save : int or Buffer Saving flag, True saves all time steps, False saves three buffered indices (last three time steps). Defaults to False. """ s = model.grid.stepping_dim.spacing # Create symbols for forward wavefield, particle velocity, source and receivers # Velocity: v = VectorTimeFunction(name="v", grid=model.grid, save=geometry.nt if save else None, time_order=1, space_order=space_order) p = TimeFunction(name="p", grid=model.grid, staggered=NODE, save=geometry.nt if save else None, time_order=1, space_order=space_order) src = PointSource(name="src", grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nsrc) rec = Receiver(name="rec", grid=model.grid, time_range=geometry.time_axis, npoint=geometry.nrec) # Equations kernels eq_kernel = kernels[kernel] eqn = eq_kernel(model, geometry, v, p, save=save) # The source injection term src_term = src.inject(field=p.forward, expr=src * s) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=p) # Substitute spacing terms to reduce flops return Operator(eqn + src_term + rec_term, subs=model.spacing_map, name='Forward', **kwargs)
def ForwardOperator(model, source, receiver, space_order=4, save=False, kernel='centered', **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param src: None ot IShot() (not currently supported properly) :param data: IShot() object containing the acquisition geometry and field data :param: time_order: Time discretization order :param: spc_order: Space discretization order """ dt = model.grid.time_dim.spacing m, damp, epsilon, delta, theta, phi = (model.m, model.damp, model.epsilon, model.delta, model.theta, model.phi) # Create symbols for forward wavefield, source and receivers u = TimeFunction(name='u', grid=model.grid, save=save, time_dim=source.nt if save else None, time_order=2, space_order=space_order) v = TimeFunction(name='v', grid=model.grid, save=save, time_dim=source.nt if save else None, time_order=2, space_order=space_order) src = PointSource(name='src', grid=model.grid, ntime=source.nt, npoint=source.npoint) rec = Receiver(name='rec', grid=model.grid, ntime=receiver.nt, npoint=receiver.npoint) # Tilt and azymuth setup ang0 = cos(theta) ang1 = sin(theta) ang2 = 0 ang3 = 0 if len(model.shape) == 3: ang2 = cos(phi) ang3 = sin(phi) FD_kernel = kernels[(kernel, len(model.shape))] H0, Hz = FD_kernel(u, v, ang0, ang1, ang2, ang3, space_order) # Stencils s = model.grid.stepping_dim.spacing stencilp = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * u + (s * damp - 2.0 * m) * u.backward + 2.0 * s ** 2 * (epsilon * H0 + delta * Hz)) stencilr = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * v + (s * damp - 2.0 * m) * v.backward + 2.0 * s ** 2 * (delta * H0 + Hz)) first_stencil = Eq(u.forward, stencilp) second_stencil = Eq(v.forward, stencilr) stencils = [first_stencil, second_stencil] # Source and receivers stencils += src.inject(field=u.forward, expr=src * dt * dt / m, offset=model.nbpml) stencils += src.inject(field=v.forward, expr=src * dt * dt / m, offset=model.nbpml) stencils += rec.interpolate(expr=u + v, offset=model.nbpml) # Substitute spacing terms to reduce flops return Operator(stencils, subs=model.spacing_map, name='ForwardTTI', **kwargs)
def ForwardOperator(model, source, receiver, time_order=2, space_order=4, save=False, **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param src: None ot IShot() (not currently supported properly) :param data: IShot() object containing the acquisition geometry and field data :param: time_order: Time discretization order :param: spc_order: Space discretization order :param: u_ini : wavefield at the three first time step for non-zero initial condition """ dt = model.critical_dt m, damp, epsilon, delta, theta, phi = (model.m, model.damp, model.epsilon, model.delta, model.theta, model.phi) # Create symbols for forward wavefield, source and receivers u = TimeData(name='u', shape=model.shape_domain, time_dim=source.nt, time_order=time_order, space_order=space_order, save=save, dtype=model.dtype) v = TimeData(name='v', shape=model.shape_domain, time_dim=source.nt, time_order=time_order, space_order=space_order, save=save, dtype=model.dtype) src = PointSource(name='src', ntime=source.nt, ndim=source.ndim, npoint=source.npoint) rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim, npoint=receiver.npoint) ang0 = cos(theta) ang1 = sin(theta) if len(model.shape) == 3: ang2 = cos(phi) ang3 = sin(phi) # Derive stencil from symbolic equation Gyp = (ang3 * u.dx - ang2 * u.dyr) Gyy = (first_derivative(Gyp * ang3, dim=x, side=centered, order=space_order, matvec=transpose) - first_derivative(Gyp * ang2, dim=y, side=right, order=space_order, matvec=transpose)) Gyp2 = (ang3 * u.dxr - ang2 * u.dy) Gyy2 = (first_derivative(Gyp2 * ang3, dim=x, side=right, order=space_order, matvec=transpose) - first_derivative(Gyp2 * ang2, dim=y, side=centered, order=space_order, matvec=transpose)) Gxp = (ang0 * ang2 * u.dx + ang0 * ang3 * u.dyr - ang1 * u.dzr) Gzr = (ang1 * ang2 * v.dx + ang1 * ang3 * v.dyr + ang0 * v.dzr) Gxx = (first_derivative(Gxp * ang0 * ang2, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gxp * ang0 * ang3, dim=y, side=right, order=space_order, matvec=transpose) - first_derivative(Gxp * ang1, dim=z, side=right, order=space_order, matvec=transpose)) Gzz = (first_derivative(Gzr * ang1 * ang2, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gzr * ang1 * ang3, dim=y, side=right, order=space_order, matvec=transpose) + first_derivative(Gzr * ang0, dim=z, side=right, order=space_order, matvec=transpose)) Gxp2 = (ang0 * ang2 * u.dxr + ang0 * ang3 * u.dy - ang1 * u.dz) Gzr2 = (ang1 * ang2 * v.dxr + ang1 * ang3 * v.dy + ang0 * v.dz) Gxx2 = (first_derivative(Gxp2 * ang0 * ang2, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gxp2 * ang0 * ang3, dim=y, side=centered, order=space_order, matvec=transpose) - first_derivative(Gxp2 * ang1, dim=z, side=centered, order=space_order, matvec=transpose)) Gzz2 = (first_derivative(Gzr2 * ang1 * ang2, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gzr2 * ang1 * ang3, dim=y, side=centered, order=space_order, matvec=transpose) + first_derivative(Gzr2 * ang0, dim=z, side=centered, order=space_order, matvec=transpose)) Hp = -(.5 * Gxx + .5 * Gxx2 + .5 * Gyy + .5 * Gyy2) Hzr = -(.5 * Gzz + .5 * Gzz2) else: Gx1p = (ang0 * u.dxr - ang1 * u.dy) Gz1r = (ang1 * v.dxr + ang0 * v.dy) Gxx1 = (first_derivative(Gx1p * ang0, dim=x, side=right, order=space_order, matvec=transpose) - first_derivative(Gx1p * ang1, dim=y, side=centered, order=space_order, matvec=transpose)) Gzz1 = (first_derivative(Gz1r * ang1, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gz1r * ang0, dim=y, side=centered, order=space_order, matvec=transpose)) Gx2p = (ang0 * u.dx - ang1 * u.dyr) Gz2r = (ang1 * v.dx + ang0 * v.dyr) Gxx2 = (first_derivative(Gx2p * ang0, dim=x, side=centered, order=space_order, matvec=transpose) - first_derivative(Gx2p * ang1, dim=y, side=right, order=space_order, matvec=transpose)) Gzz2 = (first_derivative(Gz2r * ang1, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gz2r * ang0, dim=y, side=right, order=space_order, matvec=transpose)) Hp = -(.5 * Gxx1 + .5 * Gxx2) Hzr = -(.5 * Gzz1 + .5 * Gzz2) stencilp = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * u + (s * damp - 2.0 * m) * u.backward + 2.0 * s**2 * (epsilon * Hp + delta * Hzr)) stencilr = 1.0 / (2.0 * m + s * damp) * \ (4.0 * m * v + (s * damp - 2.0 * m) * v.backward + 2.0 * s**2 * (delta * Hp + Hzr)) # Add substitutions for spacing (temporal and spatial) subs = {s: dt, h: model.get_spacing()} first_stencil = Eq(u.forward, stencilp) second_stencil = Eq(v.forward, stencilr) stencils = [first_stencil, second_stencil] ti = u.indices[0] stencils += src.inject(field=u, u_t=ti + 1, expr=src * dt * dt / m, offset=model.nbpml) stencils += src.inject(field=v, u_t=ti + 1, expr=src * dt * dt / m, offset=model.nbpml) stencils += rec.interpolate(expr=u, u_t=ti, offset=model.nbpml) stencils += rec.interpolate(expr=v, u_t=ti, offset=model.nbpml) return Operator(stencils, subs=subs, name='ForwardTTI', **kwargs)
def ForwardOperator(model, source, receiver, space_order=4, save=False, **kwargs): """ Constructor method for the forward modelling operator in an elastic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param space_order: Space discretization order :param save: Saving flag, True saves all time steps, False only the three buffered indices (last three time steps) """ vp, vs, rho, damp = model.vp, model.vs, model.rho, model.damp s = model.grid.stepping_dim.spacing x, z = model.grid.dimensions cp2 = vp * vp cs2 = vs * vs ro = 1 / rho mu = cs2 * rho l = rho * (cp2 - 2 * cs2) # Create symbols for forward wavefield, source and receivers vx = TimeFunction(name='vx', grid=model.grid, staggered=(0, 1, 0), save=source.nt if save else None, time_order=2, space_order=space_order) vz = TimeFunction(name='vz', grid=model.grid, staggered=(0, 0, 1), save=source.nt if save else None, time_order=2, space_order=space_order) txx = TimeFunction(name='txx', grid=model.grid, save=source.nt if save else None, time_order=2, space_order=space_order) tzz = TimeFunction(name='tzz', grid=model.grid, save=source.nt if save else None, time_order=2, space_order=space_order) txz = TimeFunction(name='txz', grid=model.grid, staggered=(0, 1, 1), save=source.nt if save else None, time_order=2, space_order=space_order) # Source symbol with input wavelet src = PointSource(name='src', grid=model.grid, time_range=source.time_range, npoint=source.npoint) rec1 = Receiver(name='rec1', grid=model.grid, time_range=receiver.time_range, npoint=receiver.npoint) rec2 = Receiver(name='rec2', grid=model.grid, time_range=receiver.time_range, npoint=receiver.npoint) # Stencils fd_vx = (staggered_diff(txx, dim=x, order=space_order, stagger=left) + staggered_diff(txz, dim=z, order=space_order, stagger=right)) u_vx = Eq(vx.forward, damp * vx - damp * s * ro * fd_vx) fd_vz = (staggered_diff(txz, dim=x, order=space_order, stagger=right) + staggered_diff(tzz, dim=z, order=space_order, stagger=left)) u_vz = Eq(vz.forward, damp * vz - damp * ro * s * fd_vz) vxdx = staggered_diff(vx.forward, dim=x, order=space_order, stagger=right) vzdz = staggered_diff(vz.forward, dim=z, order=space_order, stagger=right) u_txx = Eq( txx.forward, damp * txx - damp * (l + 2 * mu) * s * vxdx - damp * l * s * vzdz) u_tzz = Eq( tzz.forward, damp * tzz - damp * (l + 2 * mu) * s * vzdz - damp * l * s * vxdx) vxdz = staggered_diff(vx.forward, dim=z, order=space_order, stagger=left) vzdx = staggered_diff(vz.forward, dim=x, order=space_order, stagger=left) u_txz = Eq(txz.forward, damp * txz - damp * mu * s * (vxdz + vzdx)) # The source injection term src_xx = src.inject(field=txx.forward, expr=src * s, offset=model.nbpml) src_zz = src.inject(field=tzz.forward, expr=src * s, offset=model.nbpml) # Create interpolation expression for receivers rec_term1 = rec1.interpolate(expr=txx, offset=model.nbpml) rec_term2 = rec2.interpolate(expr=tzz, offset=model.nbpml) # Substitute spacing terms to reduce flops return Operator([u_vx, u_vz, u_txx, u_tzz, u_txz] + src_xx + src_zz + rec_term1 + rec_term2, subs=model.spacing_map, name='Forward', **kwargs)
def ForwardOperator(model, source, receiver, time_order=2, space_order=4, save=False, **kwargs): """ Constructor method for the forward modelling operator in an acoustic media :param model: :class:`Model` object containing the physical parameters :param source: :class:`PointData` object containing the source geometry :param receiver: :class:`PointData` object containing the acquisition geometry :param time_order: Time discretization order :param space_order: Space discretization order :param save: Saving flag, True saves all time steps, False only the three """ m, damp = model.m, model.damp # Create symbols for forward wavefield, source and receivers u = TimeData(name='u', shape=model.shape_domain, dtype=model.dtype, save=save, time_dim=source.nt if save else None, time_order=time_order, space_order=space_order) src = PointSource(name='src', ntime=source.nt, ndim=source.ndim, npoint=source.npoint) rec = Receiver(name='rec', ntime=receiver.nt, ndim=receiver.ndim, npoint=receiver.npoint) if time_order == 2: biharmonic = 0 dt = model.critical_dt else: biharmonic = u.laplace2(1 / m) dt = 1.73 * model.critical_dt # Derive both stencils from symbolic equation: # Create the stencil by hand instead of calling numpy solve for speed purposes # Simple linear solve of a u(t+dt) + b u(t) + c u(t-dt) = L for u(t+dt) s = t.spacing stencil = 1.0 / (2.0 * m + s * damp) * ( 4.0 * m * u + (s * damp - 2.0 * m) * u.backward + 2.0 * s**2 * (u.laplace + s**2 / 12.0 * biharmonic)) eqn = [Eq(u.forward, stencil)] # Construct expression to inject source values src_term = src.inject(field=u.forward, expr=src * dt**2 / m, offset=model.nbpml) # Create interpolation expression for receivers rec_term = rec.interpolate(expr=u, offset=model.nbpml) subs = dict([(t.spacing, dt)] + [(time.spacing, dt)] + [(i.spacing, model.get_spacing()[j]) for i, j in zip(u.indices[1:], range(len(model.shape)))]) return Operator(eqn + src_term + rec_term, subs=subs, time_axis=Forward, name='Forward', **kwargs)