Propagation of Sound Near the Sea Surface

Propagation of Sound Near the Sea Surface#

It’s time to start to bring it all together and discuss how what we have talked about in the previous sections, impacts propagation in the ocean. We will begin by considering the simple case of a sound source and receiver near the sea surface to see how the interference of the non-reflected and reflected sound impacts what is measured at the receiver. After that, in the following section, we will bring in the seafloor and consider a case where sound is propagating through a shallow ocean and consider how the ocean boundaries affect the received signal in time.

Direct and reflected paths#

To see the role interference plays in the propagation of sound in the ocean, we start by considering a source at depth, \(D_s\), below the sea surface. We will pretend that the seafloor is very deep and doesn’t have a significant effect on the propagation. We will also assume that the speed of sound is the same everywhere throughout the water column. In this case, there will be two paths that the sound will follow to a receiver at some range, \(r\), and depth, \(D_r\): the path that connects the source and receiver without interacting with the surface, known as the direct path, and the path that reflects from the surface. Depending on the application, the direct path can be very important. It tends to be strong since it doesn’t suffer any loss from the reflection at the boundaries and any information in the transmitted signal tends to be preserved. Depending on the environment, this path may not exist. For example a sound speed profile with a strong gradient might refract all the transmitted sound to the seafloor such that any path to the receiver will be reflected.

We will assume that the sea surface is flat and the only impact of reflection from the sea surface will be to multiple the incident sound by -1. The script below calculates the intensity due to point source continuously transmitting a single frequency tone as a function of range and depth throughout the water column.

Hide code cell source

# Import packages
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal.windows import tukey
import ipywidgets as widgets

# Set inline
%matplotlib inline

Hide code cell source

def CW_pulse_propagation(p, t, tv, frequency, tau, win):
    """
    Function to compute continous wave pulse using Tukey window.
    """
    # Compute the full pulse with the phase factor:
    CW_pulse = p * np.exp(-1j * (2*np.pi*frequency*t - np.pi/2))
    
    # Identify indices where the pulse is active: (t - tv) in [0, tau]
    ind = (t - tv >= 0) & (t - tv <= tau)
    
    # Zero out values outside the active pulse window
    CW_pulse[(t - tv) < 0] = 0
    CW_pulse[(t - tv) > tau] = 0
    
    if np.any(ind):
        # Apply the Tukey window
        window = tukey(np.sum(ind), win)
        CW_pulse[ind] *= window
    
    return CW_pulse

Hide code cell source

def lloyd_acoustic_field(plot_type, frequency, source_depth):
    """
    Lloyd's mirror acoustic field visualization.
    """
    # Sound speed
    c = 1500

    # Source level
    SL = 0

    # Convert SL (dB) to pressure amplitude (µPa)
    A_SL = 10**(SL/20)

    # Horizontal extent (m)
    Lx = 50

    # Vertical extent (m)
    Ly = 20

    # Number of horizontal points
    Nx = 150

    # Number of vertical points
    Ny = Nx

    # Create domain
    x = np.linspace(0, Lx, Nx)
    y = np.linspace(0, Ly, Ny)
    X, Y = np.meshgrid(x, y)
    
    # Compute ranges to the real and virtual sources
    r1 = np.sqrt(X**2 + (Y - source_depth)**2)
    r2 = np.sqrt(X**2 + (Y + source_depth)**2)
    
    # Calculate pressures from the two sources
    eps = 1e-6
    p1 = A_SL * np.exp(1j * 2*np.pi*frequency*r1/c) / r1
    p2 = -A_SL * np.exp(1j * 2*np.pi*frequency*r2/c) / r2
    p = p1 + p2 + eps

    # Plot pressure, intensity, or phase
    fig, ax = plt.subplots(figsize=(8, 6))
    if plot_type == "Pressure":
        data = np.real(p) * np.sqrt(2)
        label = 'Pressure (µPa)'
    elif plot_type == "Intensity":
        data = 20 * np.log10(np.abs(p))
        label = 'Intensity (dB re 1 µPa)'
    elif plot_type == "Phase":
        data = np.angle(p)
        label = 'Phase (radians)'
    c = plt.pcolormesh(x, y, data, shading='auto', cmap='viridis')
    if plot_type == "Intensity":
        c.set_clim(-50, 10)
    elif plot_type == "Pressure":
        c.set_clim(-1,1)
    cbar = fig.colorbar(c, ax=ax)
    cbar.set_label(label)
    ax.set_title("Acoustic Field")
    ax.set_xlabel('Range (m)')
    ax.set_ylabel('Depth (m)')
    ax.set_ylim(1, 20)
    ax.invert_yaxis()

    # Show plot
    plt.tight_layout()
    plt.show()

# Create the interactive widgets
layout = widgets.Layout(width='500px')
_ = widgets.interact(lloyd_acoustic_field,
    plot_type=widgets.Dropdown(
        options=["Pressure", "Intensity", "Phase"],
        value="Intensity",
        description="Plot Type",
        style={'description_width': 'initial'}, 
        layout=layout,
    ),
    frequency=widgets.IntSlider(
        min=100,
        max=1000,
        step=5,
        value=500,
        description='Frequency (Hz)',
        style={'description_width': 'initial'}, 
        layout=layout,
    ),
    source_depth=widgets.FloatSlider(
        min=1,
        max=19.9,
        step=0.1,
        value=10,
        description='Source Depth',
        style={'description_width': 'initial'}, 
        layout=layout,
    ),
)

Pulse propagation near the sea surface#

The pattern created by the interference of the direct and surface-reflected paths shows striations of strong constructive and destructive interference. Directly above the source, \(x = 0\) m, the direct and surface-reflected sound is traveling in opposite directions. Along this line, the nulls occur at depths that are multiples of a half-wavelength, or \(d = \frac{c}{2f}\), where \(c = 1500\) m/s, regardless of source depth. Moving further out along the x-axis, the interference fringes dip down to form straight lines, radiating out from the origin.

In actual acoustic systems, an sound source is used to transmit a pulse instead of a continuous tone. To understand how to relate the pulse transmission to the continuous wave result shown above, the following script allows you to choose a receiver depth and range and the number of cycles to transmit in the pulse. The received signal is shown in two ways: the first is the pressure time series and the second is the intensity in dB.

Hide code cell source

def lloyd_pulse_propagation(pulse_width, recDepth, recRange):
    """
    Lloyd's mirror pulse propagation visualization.
    """
    # Frequency (Hz)
    frequency =  500

    # Source depth
    source_depth = 10

    # Sound speed (m/s)
    c = 1500

    # Source level (dB)
    SL = 0

    # Receiver depth (m)
#     recDepth = 15

    # Receiver range (m)
#     recRange = 3

    # Convert SL (dB) to pressure amplitude (µPa)
    A_SL = 10**(SL/20)
    
    # Calculate distances from receiver to real and virtual sources
    rec1R = np.sqrt(recRange**2 + (recDepth - source_depth)**2)
    rec2R = np.sqrt(recRange**2 + (recDepth + source_depth)**2)
    ts1 = rec1R / c
    ts2 = rec2R / c
    
    # Calculate pressures for direct and reflected paths
    pr1 = A_SL * np.exp(1j * 2*np.pi*frequency*rec1R/c) / rec1R
    pr2 = -A_SL * np.exp(1j * 2*np.pi*frequency*rec2R/c) / rec2R
    intensityCW = 20 * np.log10(np.abs(pr1 + pr2))
    
    # Create the time axis for simulation
    dt = (1/frequency)/20
    t1 = np.arange(0, ts2*3 + dt, dt)

    # Duration of transmitted pulse
    tau = pulse_width / frequency
    
    # Compute the transmitted pulses for both paths
    pulse1 = CW_pulse_propagation(pr1, t1, ts1, frequency, tau, 0.2)
    pulse2 = CW_pulse_propagation(pr2, t1, ts2, frequency, tau, 0.2)
    Output_pulse = pulse1 + pulse2 + 1e-6

    
    # Create subplots
    _, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(16, 4))

    # Create pressure plot
    ax1.plot(t1, np.real(Output_pulse) * np.sqrt(2) * 10**(SL/20))
    ax1.set_xlim(0, 0.05)
    ax1.set_ylim(-0.35, 0.35)
    ax1.set_xlabel('Time (s)')
    ax1.set_ylabel('Pressure (µPa)')
    ax1.set_title("Pressure Time Series")

    # Create intensity plot
    ax2.plot(t1, 20 * np.log10(np.abs(Output_pulse)) + SL, linewidth=2)
    ax2.plot([t1[0], t1[-1]], [intensityCW, intensityCW], 'k--', label='CW Intensity')
    ax2.set_xlim(0, 0.05)
    ax2.set_ylim(-45, -10)
    ax2.set_xlabel('Time (s)')
    ax2.set_ylabel('Intensity (dB)')
    ax2.set_title("Intensity Time Series")
    ax2.legend()

    ax3.plot([0, recRange/2],[source_depth, 0], 'k--', linewidth=2, label='Reflected Path')
    ax3.plot([recRange/2, recRange],[0, recDepth], 'k--',linewidth=2)
    ax3.plot([0, recRange],[source_depth, recDepth], 'k-', linewidth=2, label='Direct Path')
    ax3.set_xlim(0, 1.2 * recRange)
    if source_depth > recDepth:
        ax3.set_ylim(0, 1.2 * source_depth)
    else:
        ax3.set_ylim(0, 1.2 * recDepth)
    ax3.set_xlabel('Range (m)')
    ax3.set_ylabel('Depth (m)')
    ax3.invert_yaxis()
    ax3.set_title("Ray Paths")
    ax3.legend()
    

    # Show plot
    plt.tight_layout()
    plt.show()

# Create the interactive widget
layout = widgets.Layout(width='500px')
_ = widgets.interact(lloyd_pulse_propagation, 
    pulse_width=widgets.FloatSlider(
        min=1,
        max=15,
        step=0.1,
        value=3.0,
        description='Pulse Width',
        style={'description_width': 'initial'}, 
        layout=layout,
    ),
    recDepth=widgets.FloatSlider(
        min=1,
        max=20,
        step=0.1,
        value=10,
        description='Receiver Depth',
        style={'description_width': 'initial'}, 
        layout=layout,
    ),
    recRange=widgets.FloatSlider(
        min=1,
        max=50,
        step=0.1,
        value=40,
        description='Receiver Range',
        style={'description_width': 'initial'}, 
        layout=layout,
    )
)

In this scenario, the sound traveling along the direct path arrives first followed by the sound that is reflected from the surface. The reflected sound is always lower in amplitude since the pressure is proportional to the inverse of the distance traveled (1/\(r\)) and it has to travel further than the direct path. If the number of cycles transmitted is very short (< 5), the receiver is at short range (< 5 m), and both the source and receiver far from the sea surface (> 5 m), you can clearly see the two pulses arrive at separate times. As the number of cycles are increased and/or the receiver is moved further away, the two pulses will begin to overlap in time and interfere with one another. In the intensity plot, the red line shows the intensity that should be expected if a continuous tone was used. At the times when the pulses overlap, the interference of the two pulses produces an intensity that matches the continuous tone result.