Chapter 27
25 min read
Section 229 of 353

Standing Waves and Normal Modes

The Wave Equation

Learning Objectives

By the end of this section, you will be able to:

  1. Explain how standing waves arise from the superposition of two counter-propagating traveling waves
  2. Derive the normal modes of a vibrating string using separation of variables and boundary conditions
  3. Calculate the frequencies, wavelengths, and node positions of any normal mode
  4. Construct the general solution as a superposition of normal modes using Fourier sine series
  5. Analyze how initial conditions determine which modes are excited and their relative amplitudes
  6. Apply standing wave analysis to musical instruments, quantum mechanics, and structural engineering
  7. Connect normal mode decomposition to spectral methods in machine learning and signal processing

The Big Picture: Why Standing Waves Matter

"The universe is written in the language of mathematics, and its characters are triangles, circles, and other geometric figures." — Galileo Galilei

When you pluck a guitar string, the string does not send a single wave racing back and forth. Instead, the string vibrates in a pattern that appears to stand still — certain points remain motionless while others oscillate with maximum amplitude. This is a standing wave, and it is one of the most important phenomena in all of physics.

Standing waves emerge whenever a wave is confined to a finite region with boundaries. The boundary conditions — whether the endpoints are fixed, free, or something in between — select only certain special vibration patterns from the infinite family of possible wave shapes. These special patterns are the normal modes, and they form the fundamental building blocks of all possible vibrations in the system.

🎸 Music

Every musical instrument produces sound through standing waves. The harmonic series of normal modes is what gives each instrument its distinctive timbre.

⚛ Quantum Mechanics

Electron orbitals are standing waves of probability. The quantized energy levels of atoms come directly from the normal modes of the Schrödinger equation.

🛠 Engineering

Structural resonance can destroy bridges and buildings. Engineers must understand normal modes to prevent catastrophic failures like the Tacoma Narrows collapse.

💻 Computing

Spectral methods decompose data into frequency components (normal modes). This powers everything from audio compression (MP3) to neural network positional encodings.


Historical Context

The study of vibrating strings is one of the oldest problems in mathematical physics. Pythagoras (6th century BCE) discovered that musical harmony corresponds to simple ratios of string lengths. A string half as long produces a note one octave higher — the first mathematical law of nature.

In 1746, Jean le Rond d'Alembert derived the wave equation and found its general solution as two traveling waves. Shortly after, Daniel Bernoulli proposed that any vibration of a string could be expressed as a sum of sinusoidal standing waves — the first statement of the superposition principle. This sparked a famous debate with Leonhard Euler and d'Alembert about whether "arbitrary" functions could really be represented as infinite sums of sines. The resolution came a half-century later with Joseph Fourier's groundbreaking work on heat conduction, which established the Fourier series and vindicated Bernoulli's insight.

This story illustrates how standing waves sit at the crossroads of physics and pure mathematics. The idea that any function can be decomposed into simple oscillatory components is arguably the single most powerful idea in applied mathematics, underpinning signal processing, quantum mechanics, and modern machine learning.


From Traveling Waves to Standing Waves

Recall from Section 2 that d'Alembert's general solution to the wave equation is the sum of two traveling waves:

u(x,t)=f(xct)+g(x+ct)u(x,t) = f(x - ct) + g(x + ct)

where ff travels to the right and gg travels to the left at speed cc. Now consider what happens when both waves have the same sinusoidal shape but travel in opposite directions:

u(x,t)=Asin(kxωt)+Asin(kx+ωt)u(x,t) = A \sin(kx - \omega t) + A \sin(kx + \omega t)

Applying the trigonometric identity sinα+sinβ=2sin ⁣(α+β2)cos ⁣(αβ2)\sin \alpha + \sin \beta = 2 \sin\!\left(\frac{\alpha+\beta}{2}\right) \cos\!\left(\frac{\alpha-\beta}{2}\right), we get:

u(x,t)=2Asin(kx)cos(ωt)u(x,t) = 2A \sin(kx) \cos(\omega t)

The Key Result. The superposition of two identical traveling waves moving in opposite directions produces a standing wave: the spatial and temporal parts separate completely. The function sin(kx)\sin(kx) determines the shape of the vibration, while cos(ωt)\cos(\omega t) determines how that shape oscillates in time. Every point on the string oscillates in place — no net energy propagates in either direction.

This is profoundly different from a traveling wave, where the entire pattern moves through space. In a standing wave:

  • Nodes (where sin(kx)=0\sin(kx) = 0) remain permanently at rest.
  • Antinodes (where sin(kx)=1|\sin(kx)| = 1) oscillate with maximum amplitude 2A2A.
  • All points between a pair of nodes oscillate in phase with each other — they all reach their peak at the same time.
  • Points on opposite sides of a node oscillate 180° out of phase.
🎶Standing Wave Visualizer

Explore how standing waves form from the superposition of two counter-propagating traveling waves. Toggle between views to see the individual waves, the standing pattern, or the amplitude envelope.

n = 1 is fundamental, n > 1 are overtones

Nodes

Points that never move. Mode n has n+1 nodes (including endpoints).

Antinodes

Points of maximum oscillation, located midway between consecutive nodes.

Frequency

fₙ = nc/(2L). Mode n oscillates n times faster than the fundamental.


Separation of Variables for the Wave Equation

Let us now derive the standing wave solutions systematically. We seek solutions to the one-dimensional wave equation:

2ut2=c22ux2\frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2}

subject to fixed-end boundary conditions:

u(0,t)=0andu(L,t)=0for all tu(0, t) = 0 \quad \text{and} \quad u(L, t) = 0 \quad \text{for all } t

We assume the solution can be written as a product of a function of space alone and a function of time alone:

u(x,t)=X(x)T(t)u(x, t) = X(x) \cdot T(t)

Substituting into the wave equation:

X(x)T(t)=c2X(x)T(t)X(x) \cdot T''(t) = c^2 \, X''(x) \cdot T(t)

Dividing both sides by c2X(x)T(t)c^2 \, X(x) \, T(t):

T(t)c2T(t)=X(x)X(x)\frac{T''(t)}{c^2 \, T(t)} = \frac{X''(x)}{X(x)}

The left side depends only on tt and the right side depends only on xx. Since they are equal for all xx and tt, both sides must equal the same constant, which we call λ-\lambda:

X(x)X(x)=λX(x)+λX(x)=0\frac{X''(x)}{X(x)} = -\lambda \quad \Longrightarrow \quad X''(x) + \lambda \, X(x) = 0

T(t)c2T(t)=λT(t)+λc2T(t)=0\frac{T''(t)}{c^2 \, T(t)} = -\lambda \quad \Longrightarrow \quad T''(t) + \lambda \, c^2 \, T(t) = 0

Solving the Spatial Equation (Eigenvalue Problem)

The boundary conditions u(0,t)=0u(0,t) = 0 and u(L,t)=0u(L,t) = 0 translate to X(0)=0X(0) = 0 and X(L)=0X(L) = 0. For the ODE X+λX=0X'' + \lambda X = 0 with these conditions, the only nontrivial solutions occur when λ>0\lambda > 0. Writing λ=k2\lambda = k^2:

X(x)=Asin(kx)+Bcos(kx)X(x) = A \sin(kx) + B \cos(kx)

Applying X(0)=0X(0) = 0 gives B=0B = 0, so X(x)=Asin(kx)X(x) = A \sin(kx). Applying X(L)=0X(L) = 0:

Asin(kL)=0A \sin(kL) = 0

Since A0A \neq 0 (nontrivial), we need sin(kL)=0\sin(kL) = 0, which requires:

kL=nπkn=nπL,n=1,2,3,kL = n\pi \quad \Longrightarrow \quad k_n = \frac{n\pi}{L}, \quad n = 1, 2, 3, \ldots

These are the eigenvalues. The boundary conditions have quantized the allowed wave numbers to a discrete set kn=nπ/Lk_n = n\pi/L. Only specific wavelengths "fit" into the string. This quantization is the same mechanism that produces discrete energy levels in quantum mechanics.

The corresponding eigenfunctions (normal mode shapes) are:

Xn(x)=sin ⁣(nπxL),n=1,2,3,X_n(x) = \sin\!\left(\frac{n\pi x}{L}\right), \quad n = 1, 2, 3, \ldots

Solving the Temporal Equation

With λn=(nπ/L)2\lambda_n = (n\pi/L)^2, the time equation becomes:

T(t)+ωn2T(t)=0,where ωn=nπcLT''(t) + \omega_n^2 \, T(t) = 0, \quad \text{where } \omega_n = \frac{n\pi c}{L}

This is the simple harmonic oscillator equation with solution:

Tn(t)=ancos(ωnt)+bnsin(ωnt)T_n(t) = a_n \cos(\omega_n t) + b_n \sin(\omega_n t)

where ana_n and bnb_n are constants determined by initial conditions.


Normal Modes of a Vibrating String

Combining the spatial and temporal solutions, the nth normal mode of a vibrating string is:

un(x,t)=sin ⁣(nπxL)[ancos(ωnt)+bnsin(ωnt)]u_n(x, t) = \sin\!\left(\frac{n\pi x}{L}\right) \left[a_n \cos(\omega_n t) + b_n \sin(\omega_n t)\right]

Each normal mode has three defining characteristics:

  1. A fixed spatial shape: sin(nπx/L)\sin(n\pi x / L), which does not change over time. The mode has exactly n1n - 1 interior nodes (points of zero displacement within the string, excluding the endpoints).
  2. A single frequency: ωn=nπc/L\omega_n = n\pi c/L. The mode oscillates sinusoidally at this frequency and no other. This is what makes it "normal" — it is a natural frequency of the system.
  3. Independence: Each mode vibrates independently of all others. Energy does not transfer between modes in a linear system. This is the mathematical expression of the principle of superposition.
🎹Normal Modes Explorer

Each normal mode vibrates at its own frequency. The string's motion is the superposition of all active modes. Adjust individual amplitudes to see how they combine.

Presets:

Key Insight: Harmonic Series

For a string with fixed ends, the frequencies form a harmonic series: fₙ = n · f₁. The fundamental frequency f₁ = c/(2L) depends on the wave speed c = √(T/μ) and string length L. This is exactly why a guitar string produces a musical note with overtones — its vibration is a superposition of normal modes with harmonically related frequencies.


Frequencies and Harmonics

The frequencies of the normal modes form a harmonic series:

fn=n2LTμ=nf1,n=1,2,3,f_n = \frac{n}{2L} \sqrt{\frac{T}{\mu}} = n \cdot f_1, \quad n = 1, 2, 3, \ldots

where TT is the string tension, μ\mu is the linear mass density, and f1=c/(2L)f_1 = c / (2L) is the fundamental frequency. The wave speed is c=T/μc = \sqrt{T/\mu}.

Mode nNameFrequencyWavelengthInterior Nodes
1Fundamental (1st harmonic)f₁ = c/(2L)λ₁ = 2L0
22nd harmonic (1st overtone)f₂ = 2f₁λ₂ = L1
33rd harmonic (2nd overtone)f₃ = 3f₁λ₃ = 2L/32
44th harmonic (3rd overtone)f₄ = 4f₁λ₄ = L/23
nnth harmonicfₙ = nf₁λₙ = 2L/nn−1

Three physical parameters control the pitch of a vibrating string:

  • Length L: Shorter strings have higher fundamental frequency. This is why a guitarist presses frets — shortening the effective length raises the pitch.
  • Tension T: Higher tension means higher frequency. Turning the tuning peg tightens the string and raises the pitch. Since f1Tf_1 \propto \sqrt{T}, doubling the tension raises the pitch by a factor of 2\sqrt{2} (about a perfect fifth in music).
  • Mass density μ\mu: Heavier strings vibrate more slowly. This is why bass guitar strings are thicker than treble strings.
Pythagorean Insight: The frequency ratios 2:1 (octave), 3:2 (perfect fifth), and 4:3 (perfect fourth) are exactly the ratios of normal mode frequencies. The harmony in music is literally the harmony of integer ratios in the harmonic series. Pythagoras was right — nature speaks in ratios.

Nodes and Antinodes

For the nnth normal mode Xn(x)=sin(nπx/L)X_n(x) = \sin(n\pi x / L):

Node Positions

Nodes occur where Xn(x)=0X_n(x) = 0, i.e., where sin(nπx/L)=0\sin(n\pi x/L) = 0:

xk=kLn,k=0,1,2,,nx_k = \frac{kL}{n}, \quad k = 0, 1, 2, \ldots, n

The nnth mode has n+1n + 1 nodes (including the two fixed endpoints) and n1n - 1 interior nodes. These points never move, no matter how violently the rest of the string oscillates.

Antinode Positions

Antinodes occur midway between consecutive nodes:

xkanti=(2k+1)L2n,k=0,1,,n1x_k^{\text{anti}} = \frac{(2k+1)L}{2n}, \quad k = 0, 1, \ldots, n-1

These are the points of maximum displacement. At an antinode, the string oscillates between +An+A_n and An-A_n, where AnA_n is the amplitude of the nnth mode.

Practical consequence: If you lightly touch a vibrating string at a node of the nnth harmonic, you suppress all modes that do not have a node there, isolating the nnth harmonic. This is the technique of natural harmonics on guitar and violin.

The Superposition Principle: General Solution

The general solution to the wave equation with fixed ends is an infinite sum of normal modes:

u(x,t)=n=1sin ⁣(nπxL)[ancos(ωnt)+bnsin(ωnt)]u(x, t) = \sum_{n=1}^{\infty} \sin\!\left(\frac{n\pi x}{L}\right) \left[a_n \cos(\omega_n t) + b_n \sin(\omega_n t)\right]

The coefficients ana_n and bnb_n are determined by the initial conditions:

Initial displacement u(x,0)=f(x)u(x, 0) = f(x):

f(x)=n=1ansin ⁣(nπxL)f(x) = \sum_{n=1}^{\infty} a_n \sin\!\left(\frac{n\pi x}{L}\right)

Initial velocity ut(x,0)=g(x)u_t(x, 0) = g(x):

g(x)=n=1bnωnsin ⁣(nπxL)g(x) = \sum_{n=1}^{\infty} b_n \omega_n \sin\!\left(\frac{n\pi x}{L}\right)

Using the orthogonality of the eigenfunctions, we can extract each coefficient independently:

an=2L0Lf(x)sin ⁣(nπxL)dxa_n = \frac{2}{L} \int_0^L f(x) \sin\!\left(\frac{n\pi x}{L}\right) dx

bn=2nπc0Lg(x)sin ⁣(nπxL)dxb_n = \frac{2}{n\pi c} \int_0^L g(x) \sin\!\left(\frac{n\pi x}{L}\right) dx

The Power of Orthogonality. The eigenfunctions sin(nπx/L)\sin(n\pi x/L) are orthogonal on [0,L][0, L]: 0Lsin ⁣(mπxL)sin ⁣(nπxL)dx={L/2m=n0mn\int_0^L \sin\!\left(\frac{m\pi x}{L}\right) \sin\!\left(\frac{n\pi x}{L}\right) dx = \begin{cases} L/2 & m = n \\ 0 & m \neq n \end{cases}. This orthogonality is what allows us to compute each Fourier coefficient independently, as a simple inner product. Without it, the decomposition would be computationally intractable.

Connection to Fourier Series

The formulas above are precisely the Fourier sine series. For a string released from rest (g(x)=0g(x) = 0, so bn=0b_n = 0), the solution simplifies to:

u(x,t)=n=1ansin ⁣(nπxL)cos(ωnt)u(x, t) = \sum_{n=1}^{\infty} a_n \sin\!\left(\frac{n\pi x}{L}\right) \cos(\omega_n t)

This is a beautiful result: the initial shape f(x)f(x) decomposes into pure sinusoidal modes, and each mode oscillates independently at its own natural frequency. The Fourier coefficients ana_n tell us how much of each harmonic is present in the initial displacement.

Example: The Plucked String

A string plucked at position x=px = p to height hh has a triangular initial shape. The Fourier coefficients work out to:

an=2hL2n2π2p(Lp)sin ⁣(nπpL)a_n = \frac{2hL^2}{n^2 \pi^2 p(L-p)} \sin\!\left(\frac{n\pi p}{L}\right)

Several key physics insights emerge:

  • an1/n2a_n \propto 1/n^2: Higher harmonics contribute less, giving the plucked string its characteristic warm tone.
  • sin(nπp/L)\sin(n\pi p / L): If you pluck at p=L/np = L/n, the nnth harmonic is completely absent! Plucking at the center (p=L/2p = L/2) eliminates all even harmonics.
  • Plucking near the bridge (small pp) excites many harmonics, producing a brighter, more metallic sound.
🎸String Vibration Simulator

See how different initial shapes decompose into normal modes. The Fourier coefficients (spectrum below) show how much each mode contributes to the overall vibration pattern.

Fourier Coefficient Spectrum |bₙ|

Physics Insight

A plucked string excites many harmonics. Plucking near the center (50%) emphasizes odd harmonics (the even modes have a node there and are suppressed). Plucking near 1/3 from the end suppresses every 3rd harmonic.


Energy Distribution in Normal Modes

Each normal mode carries both kinetic energy (from the motion of the string) and potential energy (from the string's deformation). For the nnth mode:

En=14μLωn2(an2+bn2)E_n = \frac{1}{4} \mu L \omega_n^2 (a_n^2 + b_n^2)

Within each mode, energy oscillates between kinetic and potential forms, but the total energy of each mode is constant — energy is conserved mode by mode. This is a direct consequence of the independence of normal modes in a linear system.

The total energy of the vibrating string is the sum over all modes:

Etotal=n=1En=μL4n=1ωn2(an2+bn2)E_{\text{total}} = \sum_{n=1}^{\infty} E_n = \frac{\mu L}{4} \sum_{n=1}^{\infty} \omega_n^2 (a_n^2 + b_n^2)

This is Parseval's theorem for the wave equation: the total energy in physical space equals the sum of energies in spectral (frequency) space. It connects to the fundamental principle in signal processing that energy is preserved under the Fourier transform.


Applications Across Science and Engineering

Musical Instruments

Every stringed instrument produces sound through standing wave normal modes. The timbre (tone quality) of an instrument is determined by the relative amplitudes of its harmonics:

InstrumentHow It Excites ModesHarmonic Signature
Guitar (plucked)Triangular displacement at pluck pointaₙ ∝ 1/n² — warm, mellow
Piano (struck)Hammer impact near one endBroad spectrum — bright, rich
Violin (bowed)Continuous friction excitationSawtooth-like: aₙ ∝ 1/n — brilliant
Flute (blown)Air column resonanceNearly pure fundamental — clear, pure

Quantum Mechanics: Particle in a Box

The time-independent Schrödinger equation for a particle confined to a box of length LL is mathematically identical to the spatial eigenvalue problem we solved:

22md2ψdx2=Eψ,ψ(0)=ψ(L)=0-\frac{\hbar^2}{2m} \frac{d^2 \psi}{dx^2} = E \, \psi, \quad \psi(0) = \psi(L) = 0

The solutions are the same eigenfunctions ψn(x)=2/Lsin(nπx/L)\psi_n(x) = \sqrt{2/L} \, \sin(n\pi x/L), with quantized energy levels:

En=n2π222mL2E_n = \frac{n^2 \pi^2 \hbar^2}{2mL^2}

The energy scales as n2n^2, not nn as for the string frequencies. But the core idea is the same: boundary conditions force quantization.

Structural Engineering: Resonance

Every structure — a bridge, a building, an airplane wing — has normal modes. If an external force oscillates at a frequency matching a normal mode frequency, the amplitude grows without bound (in the absence of damping). This is resonance, and it can be catastrophic:

  • The Tacoma Narrows Bridge (1940) collapsed when wind-driven oscillations matched a torsional normal mode.
  • The Millennium Bridge in London (2000) swayed dangerously because pedestrian footsteps synchronized with a lateral normal mode.
  • Modern earthquake-resistant buildings use tuned mass dampers — devices designed to absorb energy at specific normal mode frequencies.

Connection to Machine Learning

The decomposition of a function into normal modes is the mathematical foundation for a wide range of techniques in modern machine learning and data science:

Spectral Methods and Feature Engineering

Fourier features map input data into a set of sinusoidal basis functions — exactly the normal modes we have been studying. In the influential paper "Fourier Features Let Networks Learn High Frequency Functions" (Tancik et al., 2020), the authors showed that mapping inputs through random Fourier features dramatically improves a neural network's ability to learn high-frequency patterns:

γ(x)=[sin(2πBx),cos(2πBx)]\gamma(x) = \left[\sin(2\pi \mathbf{B} x), \cos(2\pi \mathbf{B} x)\right]

This is precisely a normal mode expansion of the input, where the matrix B\mathbf{B} selects which frequencies (modes) to include.

Positional Encodings in Transformers

The sinusoidal positional encodings in the original Transformer architecture (Vaswani et al., 2017) use the same mathematics:

PE(pos,2i)=sin ⁣(pos100002i/d),PE(pos,2i+1)=cos ⁣(pos100002i/d)\text{PE}(\text{pos}, 2i) = \sin\!\left(\frac{\text{pos}}{10000^{2i/d}}\right), \quad \text{PE}(\text{pos}, 2i+1) = \cos\!\left(\frac{\text{pos}}{10000^{2i/d}}\right)

Each dimension of the positional encoding is a standing wave mode at a different frequency. Low-frequency modes capture long-range positional relationships, while high-frequency modes encode fine-grained position differences — exactly like the normal modes of a vibrating string, where the fundamental captures the gross shape and higher harmonics encode the fine details.

Graph Neural Networks and Spectral Convolutions

In spectral graph theory, the eigenvectors of the graph Laplacian play the role of normal modes. Graph spectral convolutions decompose signals on graphs into these modes, filter in the spectral domain, and reconstruct. This is the mathematical basis of Spectral Graph Convolutional Networks.

Physics-Informed Neural Networks (PINNs)

PINNs solve PDEs by embedding the governing equations into the loss function. For wave-equation problems, initializing the network to represent a superposition of normal modes provides a powerful inductive bias that dramatically accelerates convergence — the network starts with the correct spectral structure.


Python Implementation

The following implementation computes the normal modes, Fourier coefficients, and the full time evolution of a plucked string:

Standing Waves: Normal Modes and Fourier Analysis
🐍standing_waves.py
10Normal Mode Function

Each normal mode is a product of a spatial sine function (which satisfies the boundary conditions) and a temporal cosine (oscillation at frequency ωₙ). This is the key result of separation of variables.

15Angular Frequency

ωₙ = nπc/L gives the angular frequency of the nth mode. The frequencies are integer multiples of the fundamental ω₁, forming a harmonic series. This is what gives stringed instruments their musical character.

22Pluck Coefficients

The Fourier coefficients for a triangular (plucked) initial shape have a closed form. Notice bₙ ∝ 1/n², so higher harmonics contribute less — the plucked string has a warm, mellow tone compared to a struck string.

32Pluck Position Effect

The sin(nπp/L) factor means plucking at p = L/n makes bₙ = 0! Guitarists use this: plucking at the center (p=L/2) eliminates even harmonics; plucking near the bridge excites many harmonics for a brighter sound.

37Superposition Principle

The general solution is a sum of independent normal modes. Each mode carries its own amplitude (from initial conditions) and frequency (from the eigenvalue problem). This is the power of linearity.

48Fourier Sine Series

The coefficients bₙ come from projecting the initial displacement f(x) onto each eigenfunction sin(nπx/L). This is exactly the Fourier sine series — the bridge between initial conditions and modal amplitudes.

75Energy Spectrum

The energy in mode n is proportional to bₙ² × ωₙ². Even though bₙ decreases with n, the frequency factor ωₙ² ∝ n² partially compensates. This determines the timbre (tone quality) of the vibration.

111 lines without explanation
1import numpy as np
2import matplotlib.pyplot as plt
3
4# Physical parameters
5L = 1.0       # String length (m)
6c = 1.0       # Wave speed (m/s)
7N_modes = 6   # Number of normal modes to include
8
9# Spatial and temporal grids
10x = np.linspace(0, L, 500)
11t_values = [0, 0.25, 0.5, 0.75, 1.0]
12
13# ─── Normal mode functions ──────────────────────────────────
14def normal_mode(x, t, n, c, L, amplitude=1.0):
15    """
16    nth normal mode of a vibrating string with fixed ends.
17
18    u_n(x,t) = A_n * sin(n*pi*x/L) * cos(n*pi*c*t/L)
19
20    Spatial part: sin(n*pi*x/L) — satisfies u(0)=u(L)=0
21    Temporal part: cos(omega_n*t) — oscillation at frequency f_n
22    """
23    omega_n = n * np.pi * c / L   # Angular frequency of mode n
24    spatial = np.sin(n * np.pi * x / L)
25    temporal = np.cos(omega_n * t)
26    return amplitude * spatial * temporal
27
28# ─── Fourier coefficients for a plucked string ──────────────
29def pluck_coefficients(n, pluck_pos=0.3, L=1.0):
30    """
31    Fourier sine coefficients for a triangular (plucked) string.
32
33    For a string plucked at position p with unit height:
34      b_n = (2*L) / (n^2 * pi^2 * p * (L-p)) * sin(n*pi*p/L)
35
36    Key insight: Pluck position determines which harmonics
37    are excited. Plucking at L/n suppresses the nth harmonic!
38    """
39    p = pluck_pos * L
40    coeff = (2 * L / (n**2 * np.pi**2 * p * (L - p)))
41    coeff *= np.sin(n * np.pi * p / L)
42    return coeff
43
44# ─── General solution as superposition ──────────────────────
45def string_solution(x, t, N_modes, pluck_pos=0.3):
46    """
47    General solution: superposition of normal modes.
48
49    u(x,t) = sum_{n=1}^{N} b_n * sin(n*pi*x/L) * cos(omega_n*t)
50
51    Each mode vibrates independently at its own frequency.
52    The coefficients b_n come from the Fourier sine series
53    of the initial displacement f(x).
54    """
55    u = np.zeros_like(x)
56    for n in range(1, N_modes + 1):
57        b_n = pluck_coefficients(n, pluck_pos, L)
58        u += normal_mode(x, t, n, c, L, amplitude=b_n)
59    return u
60
61# ─── Visualization ──────────────────────────────────────────
62fig, axes = plt.subplots(2, 2, figsize=(14, 10))
63
64# Plot 1: Individual normal modes at t=0
65ax = axes[0, 0]
66colors = plt.cm.viridis(np.linspace(0.1, 0.9, N_modes))
67for n in range(1, N_modes + 1):
68    mode = np.sin(n * np.pi * x / L)
69    ax.plot(x, mode, color=colors[n-1], linewidth=2,
70            label=f'Mode {n}: f={n*c/(2*L):.2f} Hz')
71ax.set_title('Normal Modes (Spatial Part)')
72ax.set_xlabel('x'); ax.set_ylabel('X_n(x)')
73ax.legend(fontsize=8); ax.grid(True, alpha=0.3)
74
75# Plot 2: Superposition evolving in time
76ax = axes[0, 1]
77for t in t_values:
78    u = string_solution(x, t, N_modes)
79    ax.plot(x, u, linewidth=2, label=f't = {t:.2f}s')
80ax.set_title('String Vibration Over Time')
81ax.set_xlabel('x'); ax.set_ylabel('u(x,t)')
82ax.legend(); ax.grid(True, alpha=0.3)
83
84# Plot 3: Fourier coefficient spectrum
85ax = axes[1, 0]
86modes = np.arange(1, 16)
87coefficients = [pluck_coefficients(n) for n in modes]
88ax.bar(modes, [abs(c) for c in coefficients],
89       color='#6366f1', alpha=0.8, edgecolor='#4f46e5')
90ax.set_title('Fourier Coefficient Spectrum |b_n|')
91ax.set_xlabel('Mode number n')
92ax.set_ylabel('|b_n|')
93ax.grid(True, alpha=0.3, axis='y')
94
95# Plot 4: Energy per mode (proportional to b_n^2 * n^2)
96ax = axes[1, 1]
97energies = [(c**2) * (n * np.pi / L)**2 for n, c in
98            zip(modes, coefficients)]
99ax.bar(modes, energies, color='#10b981', alpha=0.8,
100       edgecolor='#059669')
101ax.set_title('Energy Distribution E_n ~ b_n² · ω_n²')
102ax.set_xlabel('Mode number n')
103ax.set_ylabel('Relative Energy')
104ax.grid(True, alpha=0.3, axis='y')
105
106plt.tight_layout()
107plt.show()
108
109# Print frequency table
110print("\nNormal Mode Frequencies (Harmonic Series)")
111print("=" * 50)
112print(f"{'Mode n':<10} {'f_n (Hz)':<12} {'λ_n (m)':<12} {'Nodes'}")
113print("-" * 50)
114for n in range(1, 9):
115    fn = n * c / (2 * L)
116    wavelength = 2 * L / n
117    nodes = n + 1  # including endpoints
118    print(f"{n:<10} {fn:<12.3f} {wavelength:<12.3f} {nodes}")

For numerical solutions of the wave equation using finite differences (important for complex geometries and nonlinear problems):

Finite Difference Method for the Wave Equation
🐍wave_fdm.py
6Leapfrog Scheme

The leapfrog method is second-order accurate in both space and time. It uses the current and previous time steps to compute the next step — a natural fit for second-order-in-time PDEs like the wave equation.

11CFL Condition

The Courant-Friedrichs-Lewy (CFL) condition r = c·dt/dx ≤ 1 is essential for stability. Physically, the numerical domain of dependence must include the physical domain of dependence. If r > 1, the scheme blows up exponentially.

EXAMPLE
For c=1, dx=0.005, we need dt ≤ 0.005. With dt=0.005, r=1 (marginally stable).
30Finite Difference Stencil

The spatial second derivative u_xx is approximated by the central difference: (u[i+1] - 2u[i] + u[i-1])/dx². Combined with the leapfrog for u_tt, this gives the classic three-level explicit scheme for the wave equation.

38Boundary Conditions

Fixed (Dirichlet) boundary conditions u(0,t) = u(L,t) = 0 model a string with both ends tied down. These are enforced at every time step, overriding the interior update.

72 lines without explanation
1import numpy as np
2
3def wave_equation_fdm(L, T_final, c, Nx, Nt, initial_shape):
4    """
5    Solve the 1D wave equation using finite differences.
6
7    u_tt = c^2 * u_xx
8
9    Uses the explicit leapfrog scheme:
10      u(i, n+1) = 2*u(i,n) - u(i,n-1) + r^2*(u(i+1,n) - 2*u(i,n) + u(i-1,n))
11
12    where r = c*dt/dx is the Courant number.
13    Stable when r <= 1 (CFL condition).
14    """
15    dx = L / Nx
16    dt = T_final / Nt
17    r = c * dt / dx    # Courant number
18
19    # Stability check (CFL condition)
20    if r > 1.0:
21        raise ValueError(
22            f"Unstable! Courant number r={r:.3f} > 1. "
23            f"Increase Nx or decrease dt."
24        )
25
26    # Initialize arrays
27    x = np.linspace(0, L, Nx + 1)
28    u_prev = initial_shape(x)        # u at time n-1
29    u_curr = initial_shape(x).copy() # u at time n (zero initial velocity)
30    u_next = np.zeros(Nx + 1)        # u at time n+1
31
32    # Apply boundary conditions
33    u_prev[0] = u_prev[-1] = 0
34    u_curr[0] = u_curr[-1] = 0
35
36    # Time stepping
37    snapshots = [(0, u_curr.copy())]
38    r2 = r * r
39
40    for n in range(1, Nt + 1):
41        # Interior points: leapfrog update
42        for i in range(1, Nx):
43            u_next[i] = (
44                2 * u_curr[i]
45                - u_prev[i]
46                + r2 * (u_curr[i+1] - 2*u_curr[i] + u_curr[i-1])
47            )
48
49        # Boundary conditions
50        u_next[0] = 0
51        u_next[Nx] = 0
52
53        # Shift arrays
54        u_prev[:] = u_curr
55        u_curr[:] = u_next
56
57        # Save snapshot every few steps
58        if n % (Nt // 10) == 0:
59            t = n * dt
60            snapshots.append((t, u_curr.copy()))
61
62    return x, snapshots
63
64# Example: plucked string
65def plucked_string(x, L=1.0, pluck_pos=0.3):
66    p = pluck_pos * L
67    return np.where(x <= p, x / p, (L - x) / (L - p))
68
69x, snapshots = wave_equation_fdm(
70    L=1.0, T_final=2.0, c=1.0,
71    Nx=200, Nt=400,
72    initial_shape=plucked_string
73)
74
75print(f"Courant number: {1.0 * (2.0/400) / (1.0/200):.3f}")
76print(f"Snapshots captured at: {[f't={t:.2f}' for t, _ in snapshots]}")

Common Pitfalls

Pitfall 1: Confusing mode number with number of nodes. The nnth mode has n+1n + 1 nodes (including endpoints), not nn nodes. The interior has n1n - 1 nodes. Be precise about whether you count boundary points.
Pitfall 2: Forgetting that frequency scales as T\sqrt{T}, not as TT. Since fT/μf \propto \sqrt{T/\mu}, doubling the tension does NOT double the frequency. It only increases it by a factor of 21.414\sqrt{2} \approx 1.414.
Pitfall 3: Assuming all initial conditions produce harmonics. The harmonic series fn=nf1f_n = n f_1 is specific to strings (and air columns). For a vibrating drum membrane or a stiff bar, the overtones are not integer multiples of the fundamental. The boundary geometry determines whether the spectrum is harmonic.
Pitfall 4: CFL instability in numerical methods. The explicit finite difference scheme for the wave equation requires the Courant number r=cΔt/Δx1r = c \, \Delta t / \Delta x \leq 1. Violating this condition causes the numerical solution to blow up exponentially. Always check stability before running a simulation.

Test Your Understanding

📝Test Your Understanding

Question 1 of 6 • Score: 0/0

What creates a standing wave on a string with fixed ends?


Summary

In this section we developed the complete theory of standing waves and normal modes for a vibrating string. Here are the essential results:

ConceptFormulaMeaning
Normal mode shapeXₙ(x) = sin(nπx/L)Eigenfunction satisfying fixed-end boundary conditions
Mode frequencyfₙ = nc/(2L)Frequencies form a harmonic series: integer multiples of f₁
Wave speedc = √(T/μ)Depends on tension T and linear density μ
Node positionsxₖ = kL/nn+1 nodes total (including endpoints)
General solutionu = Σ aₙ sin(nπx/L) cos(ωₙt)Superposition of all normal modes
Fourier coefficientsaₙ = (2/L)∫ f(x) sin(nπx/L) dxHow much of each mode is present in the initial shape
Mode energyEₙ = (μL/4)ωₙ² aₙ²Conserved independently for each mode
The Central Lesson: Boundary conditions quantize the allowed vibration patterns into discrete normal modes. Any vibration can be decomposed into these modes, each oscillating at its own frequency. This idea — decomposing complex behavior into independent spectral components — is the conceptual foundation for Fourier analysis, quantum mechanics, and modern spectral methods in machine learning.
Loading comments...