# linear moveout # subroutine lmo( adj,add, slow, tau0, t0,dt, x0,dx, modl,nt,nx, data ) integer adj,add, nt,nx, it,ix,iu real t, x, tau, slow, tau0, t0,dt, x0,dx, modl(nt,nx), data(nt,nx) call adjnull( adj,add, modl,nt*nx, data,nt*nx) do ix= 1, nx { x= x0 + dx * (ix-1) do it= 1, nt { t= t0 + dt * (it-1) tau = t - x * slow iu = 1.5001 + (tau-tau0)/dt if( 0 < iu && iu <= nt) if( adj == 0 ) data(it,ix) = data(it,ix) + modl(iu,ix) else modl(iu,ix) = modl(iu,ix) + data(it,ix) }} return; end
Nearest neighbor rounding is crude but ordinarily very reliable.
I discovered a very rare numerical roundoff problem
peculiar to signal time-shifting, a problem
which arises in the linear moveout application
when the water velocity, about 1.48km/sec is approximated by 1.5=3/2.
The problem arises only where the amount of the time shift
is a numerical value (like 12.5000001 or 12.499999)
and the fractional part should be exactly 1/2 but
numerical rounding pushes it randomly in either direction.
We would not care if an entire signal was shifted
by either 12 units or by 13 units.
What is troublesome, however, is if some random portion
of the signal shifts 12 units while the rest of it shifts 13 units.
Then the output signal has places which are empty while
adjacent places contain the sum of two values.
Linear moveout is the only application
where I have ever encountered this difficulty.
A simple fix here was to modify the
lmo()
subroutine changing
the ``1.5'' to ``1.5001''.
The problem disappears if we use a more accurate sound velocity
or if we switch from nearest-neighbor interpolation
to linear interpolation.