11from devito import (Eq , Operator , Function , TimeFunction , NODE , Inc , solve ,
2- cos , sin , sqrt , div , grad )
2+ cos , sin , sqrt )
33from examples .seismic .acoustic .operators import freesurface
44
55
6+ def _subs (func , d , d0 ):
7+ try :
8+ return func ._subs (d , d0 )
9+ except AttributeError :
10+ return func
11+
12+
613def second_order_stencil (model , u , v , H0 , Hz , qu , qv , forward = True ):
714 """
815 Creates the stencil corresponding to the second order TTI wave equation
@@ -78,17 +85,17 @@ def Gzz_centered(model, field):
7885 x , y , z = field .grid .dimensions
7986 dx , dy , dz = x .spacing / 2 , y .spacing / 2 , z .spacing / 2
8087
81- Gz = (sintheta * cosphi * field .dx (fd_order = order1 , x0 = x + dx ) +
82- sintheta * sinphi * field .dy (fd_order = order1 , x0 = y + dy ) +
83- costheta * field .dz (fd_order = order1 , x0 = z + dz ))
88+ Gz = (_subs ( b , x , x + dx ) * sintheta * cosphi * field .dx (fd_order = order1 , x0 = x + dx ) +
89+ _subs ( b , y , y + dy ) * sintheta * sinphi * field .dy (fd_order = order1 , x0 = y + dy ) +
90+ _subs ( b , z , z + dz ) * costheta * field .dz (fd_order = order1 , x0 = z + dz ))
8491
85- Gzz = (b * Gz * costheta ).dz (fd_order = order1 , x0 = z - dz )
92+ Gzz = (Gz * costheta ).dz (fd_order = order1 , x0 = z - dz )
8693 # Add rotated derivative if angles are not zero. If angles are
8794 # zeros then `0*Gz = 0` and doesn't have any `.dy` ....
8895 if sintheta != 0 :
89- Gzz += (b * Gz * sintheta * cosphi ).dx (fd_order = order1 , x0 = x - dx )
96+ Gzz += (Gz * sintheta * cosphi ).dx (fd_order = order1 , x0 = x - dx )
9097 if sinphi != 0 :
91- Gzz += (b * Gz * sintheta * sinphi ).dy (fd_order = order1 , x0 = y - dy )
98+ Gzz += (Gz * sintheta * sinphi ).dy (fd_order = order1 , x0 = y - dy )
9299
93100 return Gzz
94101
@@ -115,14 +122,14 @@ def Gzz_centered_2d(model, field):
115122 x , y = field .grid .dimensions
116123 dx , dy = x .spacing / 2 , y .spacing / 2
117124
118- Gz = (sintheta * field .dx (fd_order = order1 , x0 = x + dx ) +
119- costheta * field .dy (fd_order = order1 , x0 = y + dy ))
120- Gzz = (b * Gz * costheta ).dy (fd_order = order1 , x0 = y - dy )
125+ Gz = (_subs ( b , x , x + dx ) * sintheta * field .dx (fd_order = order1 , x0 = x + dx ) +
126+ _subs ( b , y , y + dy ) * costheta * field .dy (fd_order = order1 , x0 = y + dy ))
127+ Gzz = (Gz * costheta ).dy (fd_order = order1 , x0 = y - dy )
121128
122129 # Add rotated derivative if angles are not zero. If angles are
123130 # zeros then `0*Gz = 0` and doesn't have any `.dy` ....
124131 if sintheta != 0 :
125- Gzz += (b * Gz * sintheta ).dx (fd_order = order1 , x0 = x - dx )
132+ Gzz += (Gz * sintheta ).dx (fd_order = order1 , x0 = x - dx )
126133 return Gzz
127134
128135
@@ -151,8 +158,14 @@ def Gh_centered(model, field):
151158 Gzz = Gzz_centered_2d (model , field )
152159 b = getattr (model , 'b' , None )
153160 if b is not None :
161+ _diff = lambda f , d : getattr (f , f'd{ d .name } ' )
154162 so = field .space_order // 2
155- lap = div (b * grad (field , shift = .5 , order = so ), shift = - .5 , order = so )
163+ lap = 0
164+ for d in field .space_dimensions :
165+ x0 = d + d .spacing / 2
166+ x0m = d - d .spacing / 2
167+ lap += _diff (_subs (b , d , x0 ) * _diff (field , d )(x0 = x0 , order = so ),
168+ d )(x0 = x0m , order = so )
156169 else :
157170 lap = field .laplace
158171 return lap - Gzz
0 commit comments