Skip to content

Commit

Permalink
Sound field of a pulsating sphere
Browse files Browse the repository at this point in the history
  • Loading branch information
narahahn committed Mar 11, 2019
1 parent ce48b42 commit 44a2c5e
Show file tree
Hide file tree
Showing 6 changed files with 595 additions and 4 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ addons:
apt:
packages:
- pandoc
- ffmpeg
install:
- pip install .
- pip install -r tests/requirements.txt
Expand Down
1 change: 1 addition & 0 deletions doc/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ Examples

examples/modal-room-acoustics
examples/mirror-image-source-model
examples/animations-pulsating-sphere
example-python-scripts
366 changes: 366 additions & 0 deletions doc/examples/animations-pulsating-sphere.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,366 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Animations of a Pulsating Sphere"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sfs\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import HTML"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example, the sound field of a pulsating sphere is visualized.\n",
"Different acoustic variables, such as sound pressure,\n",
"particle velocity, and particle displacement, are simulated.\n",
"The first two quantities are computed with\n",
"\n",
"- [sfs.mono.source.pulsating_sphere()](../sfs.mono.source.rst#sfs.mono.source.pulsating_sphere) and \n",
"- [sfs.mono.source.pulsating_sphere_velocity()](../sfs.mono.source.rst#sfs.mono.source.pulsating_sphere_velocity)\n",
"\n",
"while the last one can be obtained by using\n",
"\n",
"- [sfs.util.displacement()](../sfs.util.rst#sfs.util.displacement)\n",
"\n",
"which converts the particle velocity into displacement.\n",
"\n",
"A couple of additional functions are implemented in\n",
"\n",
"- [animations_pulsating_sphere.py](animations_pulsating_sphere.py)\n",
"\n",
"in order to help creating animating pictures, which is fun!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import animations_pulsating_sphere as animation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Pulsating sphere\n",
"center = [0, 0, 0]\n",
"radius = 0.25\n",
"amplitude = 0.05\n",
"f = 1000 # frequency\n",
"omega = 2 * np.pi * f # angular frequency\n",
"\n",
"# Axis limits\n",
"figsize = (6, 6)\n",
"xmin, xmax = -1, 1\n",
"ymin, ymax = -1, 1\n",
"\n",
"# Animations\n",
"frames = 20 # frames per period"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Particle Displacement"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid = sfs.util.xyz_grid([xmin, xmax], [ymin, ymax], 0, spacing=0.025)\n",
"ani = animation.particle_displacement(\n",
" omega, center, radius, amplitude, grid, frames, figsize, c='Gray')\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can play with the animation more interactively by using `.to_jshtml`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"HTML(ani.to_jshtml())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Of course, different types of grid can be chosen.\n",
"Below is the particle animation using the same parameters\n",
"but with a [hexagonal grid](https://www.redblobgames.com/grids/hexagons/)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hex_grid(xlim, ylim, hex_edge, align='horizontal'):\n",
" if align is 'vertical':\n",
" umin, umax = ylim\n",
" vmin, vmax = xlim\n",
" else:\n",
" umin, umax = xlim\n",
" vmin, vmax = ylim\n",
" du = np.sqrt(3) * hex_edge\n",
" dv = 1.5 * hex_edge\n",
" num_u = int((umax - umin) / du)\n",
" num_v = int((vmax - vmin) / dv)\n",
" u, v = np.meshgrid(np.linspace(umin, umax, num_u),\n",
" np.linspace(vmin, vmax, num_v))\n",
" u[::2] += 0.5 * du\n",
"\n",
" if align is 'vertical':\n",
" grid = v, u, 0\n",
" elif align is 'horizontal':\n",
" grid = u, v, 0\n",
" return grid"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid = hex_grid([xmin, xmax], [ymin, ymax], 0.0125, 'vertical')\n",
"ani = animation.particle_displacement(\n",
" omega, center, radius, amplitude, grid, frames, figsize, c='Gray')\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another one using a random grid."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid = [np.random.uniform(xmin, xmax, 4000),\n",
" np.random.uniform(ymin, ymax, 4000), 0]\n",
"ani = animation.particle_displacement(\n",
" omega, center, radius, amplitude, grid, frames, figsize, c='Gray')\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each grid has its strengths and weaknesses. Please refer to the\n",
"[on-line discussion](https://github.com/sfstoolbox/sfs-python/pull/69#issuecomment-468405536)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Particle Velocity"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"amplitude = 1e-3\n",
"grid = sfs.util.xyz_grid([xmin, xmax], [ymin, ymax], 0, spacing=0.04)\n",
"ani = animation.particle_velocity(\n",
" omega, center, radius, amplitude, grid, frames, figsize)\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Please notice that the amplitude of the pulsating motion is adjusted\n",
"so that the arrows are neither too short nor too long.\n",
"This kind of compromise is inevitable since\n",
"\n",
"$$\n",
"\\text{(particle velocity)} = \\text{i} \\omega \\times (\\text{amplitude}),\n",
"$$\n",
"\n",
"thus the absolute value of particle velocity is usually\n",
"much larger than that of amplitude.\n",
"It should be also kept in mind that the hole in the middle\n",
"does not visualizes the exact motion of the pulsating sphere.\n",
"According to the above equation, the actual amplitude should be\n",
"much smaller than the arrow lengths.\n",
"The changing rate of its size is also two times higher than the original frequency."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sound Pressure"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"amplitude = 0.05\n",
"impedance_pw = sfs.default.rho0 * sfs.default.c\n",
"max_pressure = omega * impedance_pw * amplitude\n",
"\n",
"grid = sfs.util.xyz_grid([xmin, xmax], [ymin, ymax], 0, spacing=0.005)\n",
"ani = animation.sound_pressure(\n",
" omega, center, radius, amplitude, grid, frames, pulsate=True,\n",
" figsize=figsize, vmin=-max_pressure, vmax=max_pressure)\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that the sound pressure exceeds\n",
"the atmospheric pressure ($\\approx 10^5$ Pa), which of course makes no sense.\n",
"This is due to the large amplitude (50 mm) of the pulsating motion.\n",
"It was chosen to better visualize the particle movements\n",
"in the earlier animations.\n",
"\n",
"For 1 kHz, the amplitude corresponding to a moderate sound pressure,\n",
"let say 1 Pa, is in the order of micrometer.\n",
"As it is very small compared to the corresponding wavelength (0.343 m),\n",
"the movement of the particles and the spatial structure of the sound field\n",
"cannot be observed simultaneously.\n",
"Furthermore, at high frequencies, the sound pressure\n",
"for a given particle displacement scales with the frequency.\n",
"The smaller wavelength (higher frequency) we choose,\n",
"it is more likely to end up with a prohibitively high sound pressure.\n",
"\n",
"In the following examples, the amplitude is set to a realistic value 1 $\\mu$m.\n",
"Notice that the pulsating motion of the sphere is no more visible."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"amplitude = 1e-6\n",
"impedance_pw = sfs.default.rho0 * sfs.default.c\n",
"max_pressure = omega * impedance_pw * amplitude\n",
"\n",
"grid = sfs.util.xyz_grid([xmin, xmax], [ymin, ymax], 0, spacing=0.005)\n",
"ani = animation.sound_pressure(\n",
" omega, center, radius, amplitude, grid, frames, pulsate=True,\n",
" figsize=figsize, vmin=-max_pressure, vmax=max_pressure)\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's zoom in closer to the boundary of the sphere."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L = 10 * amplitude\n",
"xmin_zoom, xmax_zoom = radius - L, radius + L\n",
"ymin_zoom, ymax_zoom = -L, L"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid = sfs.util.xyz_grid([xmin_zoom, xmax_zoom], [ymin_zoom, ymax_zoom], 0, spacing=L / 100)\n",
"ani = animation.sound_pressure(\n",
" omega, center, radius, amplitude, grid, frames, pulsate=True,\n",
" figsize=figsize, vmin=-max_pressure, vmax=max_pressure)\n",
"plt.close()\n",
"HTML(ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This shows how the vibrating motion of the sphere (left half)\n",
"changes the sound pressure of the surrounding air (right half).\n",
"Notice that the sound pressure increases/decreases (more red/blue)\n",
"when the surface accelerates/decelerates."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit 44a2c5e

Please sign in to comment.