def Gzz_shifted_2d(field, costheta, sintheta, space_order): """ 2D rotated second order derivative in the direction z as an average of two non-centered rotated second order derivative in the direction z :param field: symbolic data whose derivative we are computing :param costheta: cosine of the tilt :param sintheta: sine of the tilt :param space_order: discretization order :return: rotated second order derivative wrt z """ x, y = field.space_dimensions[:2] Gz1r = (sintheta * field.dxr + costheta * field.dy) Gzz1 = (first_derivative(Gz1r * sintheta, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gz1r * costheta, dim=y, side=centered, order=space_order, matvec=transpose)) Gz2r = (sintheta * field.dx + costheta * field.dyr) Gzz2 = (first_derivative(Gz2r * sintheta, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gz2r * costheta, dim=y, side=right, order=space_order, matvec=transpose)) return -.5 * (Gzz1 + Gzz2)
def Gyy_shifted(field, cosphi, sinphi, space_order): """ 3D rotated second order derivative in the direction y as an average of two non-centered rotated second order derivative in the direction y :param field: symbolic data whose derivative we are computing :param cosphi: cosine of the azymuth angle :param sinphi: sine of the azymuth angle :param space_order: discretization order :return: rotated second order derivative wrt y """ x, y = field.space_dimensions[:2] Gyp = (sinphi * field.dx - cosphi * field.dyr) Gyy = (first_derivative(Gyp * sinphi, dim=x, side=centered, order=space_order, matvec=transpose) - first_derivative(Gyp * cosphi, dim=y, side=right, order=space_order, matvec=transpose)) Gyp2 = (sinphi * field.dxr - cosphi * field.dy) Gyy2 = (first_derivative( Gyp2 * sinphi, dim=x, side=right, order=space_order, matvec=transpose) - first_derivative(Gyp2 * cosphi, dim=y, side=centered, order=space_order, matvec=transpose)) return -.5 * (Gyy + Gyy2)
def Gxx_shifted_2d(field, costheta, sintheta, space_order): """ 2D rotated second order derivative in the direction x as an average of two non-centered rotated second order derivative in the direction x :param field: symbolic data whose derivative we are computing :param costheta: cosine of the tilt angle :param sintheta: sine of the tilt angle :param space_order: discretization order :return: rotated second order derivative wrt x """ x, y = field.space_dimensions[:2] Gx1 = (costheta * field.dxr - sintheta * field.dy) Gxx1 = (first_derivative( Gx1 * costheta, dim=x, side=right, order=space_order, matvec=transpose) - first_derivative(Gx1 * sintheta, dim=y, side=centered, order=space_order, matvec=transpose)) Gx2p = (costheta * field.dx - sintheta * field.dyr) Gxx2 = (first_derivative(Gx2p * costheta, dim=x, side=centered, order=space_order, matvec=transpose) - first_derivative(Gx2p * sintheta, dim=y, side=right, order=space_order, matvec=transpose)) return -.5 * (Gxx1 + Gxx2)
def Gzz_centered_2d(field, costheta, sintheta, space_order): """ 2D rotated second order derivative in the direction z :param field: symbolic data whose derivative we are computing :param costheta: cosine of the tilt angle :param sintheta: sine of the tilt angle :param space_order: discretization order :return: rotated second order derivative wrt z """ order1 = space_order / 2 Gz = -( sintheta * first_derivative(field, dim=x, side=centered, order=order1) + costheta * first_derivative(field, dim=y, side=centered, order=order1)) Gzz = (first_derivative( Gz * sintheta, dim=x, side=centered, order=order1, matvec=transpose ) + first_derivative( Gz * costheta, dim=y, side=centered, order=order1, matvec=transpose)) return Gzz
def Gxx_shifted(field, costheta, sintheta, cosphi, sinphi, space_order): """ 3D rotated second order derivative in the direction x as an average of two non-centered rotated second order derivative in the direction x :param field: symbolic data whose derivative we are computing :param costheta: cosine of the tilt angle :param sintheta: sine of the tilt angle :param cosphi: cosine of the azymuth angle :param sinphi: sine of the azymuth angle :param space_order: discretization order :return: rotated second order derivative wrt x """ x, y, z = field.space_dimensions Gx1 = (costheta * cosphi * field.dx + costheta * sinphi * field.dyr - sintheta * field.dzr) Gxx1 = (first_derivative(Gx1 * costheta * cosphi, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gx1 * costheta * sinphi, dim=y, side=right, order=space_order, matvec=transpose) - first_derivative(Gx1 * sintheta, dim=z, side=right, order=space_order, matvec=transpose)) Gx2 = (costheta * cosphi * field.dxr + costheta * sinphi * field.dy - sintheta * field.dz) Gxx2 = (first_derivative(Gx2 * costheta * cosphi, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gx2 * costheta * sinphi, dim=y, side=centered, order=space_order, matvec=transpose) - first_derivative(Gx2 * sintheta, dim=z, side=centered, order=space_order, matvec=transpose)) return -.5 * (Gxx1 + Gxx2)
def Gzz_shited(field, costheta, sintheta, cosphi, sinphi, space_order): """ 3D rotated second order derivative in the direction z as an average of two non-centered rotated second order derivative in the direction z :param field: symbolic data whose derivative we are computing :param costheta: cosine of the tilt angle :param sintheta: sine of the tilt angle :param cosphi: cosine of the azymuth angle :param sinphi: sine of the azymuth angle :param space_order: discretization order :return: rotated second order derivative wrt z """ x, y, z = field.space_dimensions Gzr = (sintheta * cosphi * field.dx + sintheta * sinphi * field.dyr + costheta * field.dzr) Gzz = (first_derivative(Gzr * sintheta * cosphi, dim=x, side=centered, order=space_order, matvec=transpose) + first_derivative(Gzr * sintheta * sinphi, dim=y, side=right, order=space_order, matvec=transpose) + first_derivative(Gzr * costheta, dim=z, side=right, order=space_order, matvec=transpose)) Gzr2 = (sintheta * cosphi * field.dxr + sintheta * sinphi * field.dy + costheta * field.dz) Gzz2 = (first_derivative(Gzr2 * sintheta * cosphi, dim=x, side=right, order=space_order, matvec=transpose) + first_derivative(Gzr2 * sintheta * sinphi, dim=y, side=centered, order=space_order, matvec=transpose) + first_derivative(Gzr2 * costheta, dim=z, side=centered, order=space_order, matvec=transpose)) return -.5 * (Gzz + Gzz2)
def dzr(self): """Symbol for the derivative wrt to z with a right stencil""" return first_derivative(self, order=self.space_order, dim=z, side=right)
def dyl(self): """Symbol for the derivative wrt to y with a left stencil""" return first_derivative(self, order=self.space_order, dim=y, side=left)
def dz(self): """Symbol for the first derivative wrt the z dimension""" return first_derivative(self, order=self.space_order, dim=z, side=centered)
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 __init__(self, model, src, damp, data, time_order=2, spc_order=4, save=False, **kwargs): nrec, nt = data.shape dt = model.get_critical_dt() u = TimeData(name="u", shape=model.get_shape_comp(), time_dim=nt, time_order=time_order, space_order=spc_order, save=save, dtype=damp.dtype) v = TimeData(name="v", shape=model.get_shape_comp(), time_dim=nt, time_order=time_order, space_order=spc_order, save=save, dtype=damp.dtype) m = DenseData(name="m", shape=model.get_shape_comp(), dtype=damp.dtype) m.data[:] = model.padm() if model.epsilon is not None: epsilon = DenseData(name="epsilon", shape=model.get_shape_comp(), dtype=damp.dtype) epsilon.data[:] = model.pad(model.epsilon) else: epsilon = 1.0 if model.delta is not None: delta = DenseData(name="delta", shape=model.get_shape_comp(), dtype=damp.dtype) delta.data[:] = model.pad(model.delta) else: delta = 1.0 if model.theta is not None: theta = DenseData(name="theta", shape=model.get_shape_comp(), dtype=damp.dtype) theta.data[:] = model.pad(model.theta) else: theta = 0 if len(model.get_shape_comp()) == 3: if model.phi is not None: phi = DenseData(name="phi", shape=model.get_shape_comp(), dtype=damp.dtype) phi.data[:] = model.pad(model.phi) else: phi = 0 u.pad_time = save v.pad_time = save rec = SourceLike(name="rec", npoint=nrec, nt=nt, dt=dt, h=model.get_spacing(), coordinates=data.receiver_coords, ndim=len(damp.shape), dtype=damp.dtype, nbpml=model.nbpml) def Bhaskarasin(angle): if angle == 0: return 0 else: return (16.0 * angle * (3.1416 - abs(angle)) / (49.3483 - 4.0 * abs(angle) * (3.1416 - abs(angle)))) def Bhaskaracos(angle): if angle == 0: return 1.0 else: return Bhaskarasin(angle + 1.5708) Hp, Hzr = symbols('Hp Hzr') if len(m.shape) == 3: ang0 = Function('ang0')(x, y, z) ang1 = Function('ang1')(x, y, z) ang2 = Function('ang2')(x, y, z) ang3 = Function('ang3')(x, y, z) else: ang0 = Function('ang0')(x, y) ang1 = Function('ang1')(x, y) s, h = symbols('s h') ang0 = Bhaskaracos(theta) ang1 = Bhaskarasin(theta) spc_brd = spc_order / 2 # Derive stencil from symbolic equation if len(m.shape) == 3: ang2 = Bhaskaracos(phi) ang3 = Bhaskarasin(phi) Gy1p = (ang3 * u.dxl - ang2 * u.dyl) Gyy1 = (first_derivative(Gy1p, ang3, dim=x, side=right, order=spc_brd) - first_derivative(Gy1p, ang2, dim=y, side=right, order=spc_brd)) Gy2p = (ang3 * u.dxr - ang2 * u.dyr) Gyy2 = (first_derivative(Gy2p, ang3, dim=x, side=left, order=spc_brd) - first_derivative(Gy2p, ang2, dim=y, side=left, order=spc_brd)) Gx1p = (ang0 * ang2 * u.dxl + ang0 * ang3 * u.dyl - ang1 * u.dzl) Gz1r = (ang1 * ang2 * v.dxl + ang1 * ang3 * v.dyl + ang0 * v.dzl) Gxx1 = (first_derivative(Gx1p, ang0, ang2, dim=x, side=right, order=spc_brd) + first_derivative(Gx1p, ang0, ang3, dim=y, side=right, order=spc_brd) - first_derivative(Gx1p, ang1, dim=z, side=right, order=spc_brd)) Gzz1 = (first_derivative(Gz1r, ang1, ang2, dim=x, side=right, order=spc_brd) + first_derivative(Gz1r, ang1, ang3, dim=y, side=right, order=spc_brd) + first_derivative(Gz1r, ang0, dim=z, side=right, order=spc_brd)) Gx2p = (ang0 * ang2 * u.dxr + ang0 * ang3 * u.dyr - ang1 * u.dzr) Gz2r = (ang1 * ang2 * v.dxr + ang1 * ang3 * v.dyr + ang0 * v.dzr) Gxx2 = (first_derivative(Gx2p, ang0, ang2, dim=x, side=left, order=spc_brd) + first_derivative(Gx2p, ang0, ang3, dim=y, side=left, order=spc_brd) - first_derivative(Gx2p, ang1, dim=z, side=left, order=spc_brd)) Gzz2 = (first_derivative(Gz2r, ang1, ang2, dim=x, side=left, order=spc_brd) + first_derivative(Gz2r, ang1, ang3, dim=y, side=left, order=spc_brd) + first_derivative(Gz2r, ang0, dim=z, side=left, order=spc_brd)) parm = [m, damp, epsilon, delta, theta, phi, u, v] else: Gyy2 = 0 Gyy1 = 0 parm = [m, damp, epsilon, delta, theta, u, v] Gx1p = (ang0 * u.dxr - ang1 * u.dy) Gz1r = (ang1 * v.dxr + ang0 * v.dy) Gxx1 = (first_derivative(Gx1p * ang0, dim=x, side=left, order=spc_brd) - first_derivative(Gx1p * ang1, dim=y, side=centered, order=spc_brd)) Gzz1 = (first_derivative(Gz1r * ang1, dim=x, side=left, order=spc_brd) + first_derivative(Gz1r * ang0, dim=y, side=centered, order=spc_brd)) Gx2p = (ang0 * u.dx - ang1 * u.dyr) Gz2r = (ang1 * v.dx + ang0 * v.dyr) Gxx2 = (first_derivative(Gx2p * ang0, dim=x, side=centered, order=spc_brd) - first_derivative(Gx2p * ang1, dim=y, side=left, order=spc_brd)) Gzz2 = (first_derivative(Gz2r * ang1, dim=x, side=centered, order=spc_brd) + first_derivative(Gz2r * ang0, dim=y, side=left, order=spc_brd)) 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)) Hp_val = -(.5 * Gxx1 + .5 * Gxx2 + .5 * Gyy1 + .5 * Gyy2) Hzr_val = -(.5 * Gzz1 + .5 * Gzz2) factorized = {Hp: Hp_val, Hzr: Hzr_val} # Add substitutions for spacing (temporal and spatial) subs = [{s: src.dt, h: src.h}, {s: src.dt, h: src.h}] first_stencil = Eq(u.forward, stencilp.xreplace(factorized)) second_stencil = Eq(v.forward, stencilr.xreplace(factorized)) stencils = [first_stencil, second_stencil] super(ForwardOperator, self).__init__(src.nt, m.shape, stencils=stencils, subs=subs, spc_border=spc_order/2 + 2, time_order=time_order, forward=True, dtype=m.dtype, input_params=parm, **kwargs) # Insert source and receiver terms post-hoc self.input_params += [src, src.coordinates, rec, rec.coordinates] self.output_params += [v, rec] self.propagator.time_loop_stencils_a = (src.add(m, u) + src.add(m, v) + rec.read2(u, v)) self.propagator.add_devito_param(src) self.propagator.add_devito_param(src.coordinates) self.propagator.add_devito_param(rec) self.propagator.add_devito_param(rec.coordinates)