Monopoles, dipoles and quadrupole animations

Animations Waves Complex Numbers

In this post, we're going to produce a couple of animations related to typical sound sources encountered in the study of acoustics: monopole, dipole and quadrupole sources (using holoviews with the matplotlib backend).

We start by creating an $(x, y)$ grid of space.

In [1]:
import numpy as np
import holoviews as hv
hv.extension('matplotlib', logo=False)
In [2]:
x = np.linspace(-15, 15, num=100)
y = np.linspace(-15, 15, num=100)

X, Y = np.meshgrid(x, y)

Using this grid, we can build a phase map for a monopole source. By phase map, I mean the change in phase, at the selected frequency that a radial wave would incur by propagating from the origin to the point of the grid.

In [3]:
r = np.sqrt(X**2 + Y**2)
phase_map1= np.exp(1j * r)

hv.QuadMesh((X, Y, np.real(phase_map1)))

We can animate this phase map by adding a phase term that varies as a function of time. If we discretize a single period in a given number of frames and loop over the frames, we can generate an "infinite" animation. Let's try this!

In [4]:
N = 15
In [5]:
%%output holomap='scrubber'
hmap1 = hv.HoloMap({i: hv.QuadMesh((X, Y, np.real(phase_map1* np.exp(-1j * i / N * 2 * np.pi))), 
                                   label='monopole') for i in range(N)}).opts(colorbar=True)

Let's apply the same logic to a dipole, made out of two sources a fraction of a wavelength apart and out of phase.

In [6]:
delta = 2.5
r1 = np.sqrt((X-delta)**2 + Y**2)
r2 = np.sqrt((X+delta)**2 + Y**2)
phase_map2 = .5 * np.exp(1j * r1) - .5 * np.exp(1j * r2)
In [7]:
%%output holomap='scrubber' 
hmap2 = hv.HoloMap({i: hv.QuadMesh((X, Y, np.real(phase_map2 * np.exp(-1j * i / N * 2 * np.pi))), 
                                   label='dipole') for i in range(N)}).opts(colorbar=True)