I am trying to compare my finite difference's solution of the scalar (or simple acoustic) wave equation with an analytic solution.
For that purpose I am using the following analytic solution presented in the old paper Accuracy of the finite-difference modeling of the acoustic wave equation - Geophysics 1974 - R. M. Alford et. al.
The solution, equation (9) in that paper, for a constant velocity medium is given in cylindrical coordinates by:
\begin{eqnarray} u_s(\rho, \phi, t) = \frac{1}{2\pi} \int_{-\infty}^{\infty} \{ -i \pi H_0^{(2)}\left(k | \sigma - \sigma_s| \right) F(\omega) e^{i\omega t} d\omega\} \end{eqnarray} (A)
$H_0^{(2)}$ is the Hankel function of the second kind with order zero.
$| \sigma - \sigma_s| $ is the distance from the source to the observation point.
Also $ k = \frac{\omega}{C_0}$ come from $C_0$ the medium velocity converted to the Fourier domain, defined in the original scalar wave equation as:
\begin{eqnarray} \left[ \nabla^2 - \frac{1}{C_0^2}\frac{\partial ^2}{\partial t^2}\right] u(\rho, \phi, t) = -4 \pi \frac{\delta(\rho-\rho_s)\delta(\phi-\phi_s)f(t)}{\rho} \end{eqnarray}
$ (\rho_s, \phi_s) $ defines the source location in the $\phi$ x $\rho$ plane.
$ F(\omega)$ comes from the source function $f(t)$
The problem:
- When implementing numerically A I'm not getting meaningful results. The velocity obtained using A is totally different from the $C_0$ used as input
My code example is bellow where I am evaluating A, using python.
I calculate the solution at zero solution0
and at a distance D=8000 solutionD
. Then I use the global maximum to calculate an approximation to velocity $C_0$
Probably it's a quite simple error that I am doing. If someone can point it out for me. The velocity I am getting shows that maybe the equation (9) is wrong or I am implementing it wrongly (what I believe to be the case).
from scipy.special import hankel2
import numpy as np
# a simple source function f(t) gauss derivative normalized
def gaussource(time, wlength, delay=None):
if delay == None: # enough delay time
delay = 3*wlength
t = time - delay
return ((2*np.sqrt(np.e)/(wlength))
*t*np.exp(-2*(t**2)/(wlength**2)))
# analytic solution equation (A) paper
def waves(source, distance, c):
n = len(source)
sourcew = np.fft.fft(source) # source in the frequency domain
hnk_factor = distance/c # distance to source divided by velocity
if not distance == 0.0:
hankelshift = np.complex(0,-np.pi)*np.array([hankel2(0,hnk_factor*omega) for omega in xrange(n)])
hankelshift[0] = 0. # i infinity in limit
return np.real(np.fft.ifft(hankelshift*sourcew))
return source
c = 4000.
fc = 5.0
dt = 0.01
t = np.arange(0., 2., dt) # 2 seconds to evaluate the solution
source = gaussource(t, 1./fc) # source
solution0 = waves(source, 0., c) # solution at zero source (source itself)
solutionD = waves(source, 8000., c) #solution at certain distance D=8000 metres e.g.
t0 = solution0.argmax(); # get max index time at zero
tD = solutionD.argmax(); # get max index time at distance
print "phase velocity aproximation ", 8000./((tD-t0)*dt)