This page was generated from doc/examples/animations-pulsating-sphere.ipynb. Interactive online version: Binder badge

Animations of a Pulsating Sphere

[1]:
import sfs
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML

In this example, the sound field of a pulsating sphere is visualized. Different acoustic variables, such as sound pressure, particle velocity, and particle displacement, are simulated. The first two quantities are computed with

while the last one can be obtained by using

which converts the particle velocity into displacement.

A couple of additional functions are implemented in

in order to help creating animating pictures, which is fun!

[2]:
import animations_pulsating_sphere as animation
[3]:
# Pulsating sphere
center = [0, 0, 0]
radius = 0.25
amplitude = 0.05
f = 1000  # frequency
omega = 2 * np.pi * f  # angular frequency

# Axis limits
figsize = (6, 6)
xmin, xmax = -1, 1
ymin, ymax = -1, 1

# Animations
frames = 20  # frames per period

Particle Displacement

[4]:
grid = sfs.util.xyz_grid([xmin, xmax], [ymin, ymax], 0, spacing=0.025)
ani = animation.particle_displacement(
        omega, center, radius, amplitude, grid, frames, figsize, c='Gray')
plt.close()
HTML(ani.to_jshtml())
[4]:

Click the arrow button to start the animation. to_jshtml() allows you to play with the animation, e.g. speed up/down the animation (+/- button). Try to reverse the playback by clicking the left arrow. You’ll see a sound sink.

You can also show the animation by using to_html5_video(). See the documentation for more detail.

Of course, different types of grid can be chosen. Below is the particle animation using the same parameters but with a hexagonal grid.

[5]:
def hex_grid(xlim, ylim, hex_edge, align='horizontal'):
    if align is 'vertical':
        umin, umax = ylim
        vmin, vmax = xlim
    else:
        umin, umax = xlim
        vmin, vmax = ylim
    du = np.sqrt(3) * hex_edge
    dv = 1.5 * hex_edge
    num_u = int((umax - umin) / du)
    num_v = int((vmax - vmin) / dv)
    u, v = np.meshgrid(np.linspace(umin, umax, num_u),
                       np.linspace(vmin, vmax, num_v))
    u[::2] += 0.5 * du

    if align is 'vertical':
        grid = v, u, 0
    elif align is 'horizontal':
        grid = u, v, 0
    return  grid
<>:2: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
<>:16: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
<>:18: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
<>:2: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
<>:16: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
<>:18: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
/tmp/ipykernel_1294/2319301824.py:2: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
  if align is 'vertical':
/tmp/ipykernel_1294/2319301824.py:16: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
  if align is 'vertical':
/tmp/ipykernel_1294/2319301824.py:18: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
  elif align is 'horizontal':
[6]:
grid = sfs.util.as_xyz_components(hex_grid([xmin, xmax],
                                           [ymin, ymax],
                                           0.0125,
                                           'vertical'))
ani = animation.particle_displacement(
        omega, center, radius, amplitude, grid, frames, figsize, c='Gray')
plt.close()
HTML(ani.to_jshtml())
[6]:

Another one using a random grid.

[7]:
grid = sfs.util.as_xyz_components([np.random.uniform(xmin, xmax, 4000),
                                   np.random.uniform(ymin, ymax, 4000),
                                   0])
ani = animation.particle_displacement(
        omega, center, radius, amplitude, grid, frames, figsize, c='Gray')
plt.close()
HTML(ani.to_jshtml())
[7]: