def kernel_staggered_2d(model, u, v, space_order, **kwargs): """ TTI finite difference. The equation solved is: vx.dt = - u.dx vz.dt = - v.dx m * v.dt = - sqrt(1 + 2 delta) vx.dx - vz.dz + Fh m * u.dt = - (1 + 2 epsilon) vx.dx - sqrt(1 + 2 delta) vz.dz + Fv """ # Forward or backward forward = kwargs.get('forward', True) dampl = 1 - model.damp m, epsilon, delta = model.m, model.epsilon, model.delta costheta, sintheta = trig_func(model) epsilon = 1 + 2 * epsilon delta = sqrt(1 + 2 * delta) s = model.grid.stepping_dim.spacing x, z = model.grid.dimensions # Get source qu = kwargs.get('qu', 0) qv = kwargs.get('qv', 0) # Staggered setup vx, vz, _ = particle_velocity_fields(model, space_order) if forward: # Stencils phdx = costheta * u.dx - sintheta * u.dy u_vx = Eq(vx.forward, dampl * vx - dampl * s * phdx) pvdz = sintheta * v.dx + costheta * v.dy u_vz = Eq(vz.forward, dampl * vz - dampl * s * pvdz) dvx = costheta * vx.forward.dx - sintheta * vx.forward.dy dvz = sintheta * vz.forward.dx + costheta * vz.forward.dy # u and v equations pv_eq = Eq(v.forward, dampl * (v - s / m * (delta * dvx + dvz)) + s / m * qv) ph_eq = Eq(u.forward, dampl * (u - s / m * (epsilon * dvx + delta * dvz)) + s / m * qu) else: # Stencils phdx = ((costheta*epsilon*u).dx - (sintheta*epsilon*u).dy + (costheta*delta*v).dx - (sintheta*delta*v).dy) u_vx = Eq(vx.backward, dampl * vx + dampl * s * phdx) pvdz = ((sintheta*delta*u).dx + (costheta*delta*u).dy + (sintheta*v).dx + (costheta*v).dy) u_vz = Eq(vz.backward, dampl * vz + dampl * s * pvdz) dvx = (costheta * vx.backward).dx - (sintheta * vx.backward).dy dvz = (sintheta * vz.backward).dx + (costheta * vz.backward).dy # u and v equations pv_eq = Eq(v.backward, dampl * (v + s / m * dvz)) ph_eq = Eq(u.backward, dampl * (u + s / m * dvx)) return [u_vx, u_vz] + [pv_eq, ph_eq]
def kernel_centered_3d(model, u, v, space_order, **kwargs): """ TTI finite difference kernel. The equation solved is: u.dt2 = H0 v.dt2 = Hz where H0 and Hz are defined as: H0 = (1+2 *epsilon) (Gxx(u)+Gyy(u)) + sqrt(1+ 2*delta) Gzz(v) Hz = sqrt(1+ 2*delta) (Gxx(u)+Gyy(u)) + Gzz(v) and H0 = (Gxx+Gyy)((1+2 *epsilon)*u + sqrt(1+ 2*delta)*v) Hz = Gzz(sqrt(1+ 2*delta)*u + v) for the forward and adjoint cases, respectively. Epsilon and delta are the Thomsen parameters. This function computes H0 and Hz. References: * Zhang, Yu, Houzhu Zhang, and Guanquan Zhang. "A stable TTI reverse time migration and its implementation." Geophysics 76.3 (2011): WA3-WA11. * Louboutin, Mathias, Philipp Witte, and Felix J. Herrmann. "Effects of wrong adjoints for RTM in TTI media." SEG Technical Program Expanded Abstracts 2018. Society of Exploration Geophysicists, 2018. 331-335. Parameters ---------- u : TimeFunction First TTI field. v : TimeFunction Second TTI field. space_order : int Space discretization order. Returns ------- u and v component of the rotated Laplacian in 3D. """ # Forward or backward forward = kwargs.get('forward', True) costheta, sintheta, cosphi, sinphi = trig_func(model) delta, epsilon = model.delta, model.epsilon epsilon = 1 + 2*epsilon delta = sqrt(1 + 2*delta) # Get source qu = kwargs.get('qu', 0) qv = kwargs.get('qv', 0) if forward: Gxx = Gxxyy_centered(model, u, costheta, sintheta, cosphi, sinphi, space_order) Gzz = Gzz_centered(model, v, costheta, sintheta, cosphi, sinphi, space_order) H0 = epsilon*Gxx + delta*Gzz Hz = delta*Gxx + Gzz return second_order_stencil(model, u, v, H0, Hz, qu, qv) else: H0 = Gxxyy_centered(model, (epsilon*u + delta*v), costheta, sintheta, cosphi, sinphi, space_order) Hz = Gzz_centered(model, (delta*u + v), costheta, sintheta, cosphi, sinphi, space_order) return second_order_stencil(model, u, v, H0, Hz, qu, qv, forward=forward)