Wave Equation Solver
Topic:
advanced.pde.wave_equation
The wave equation governs oscillatory phenomena and wave propagation in physical systems. Solves hyperbolic PDEs with boundary conditions and two initial conditions (position and velocity).
Mathematical Definition
where:
- is displacement at position and time
- is wave speed (m/s)
- (1D)
Newton's Second Law for string element:
Wave speed: where = linear mass density, = tension
Wave Equation Solver
Mathematical Model
The wave equation governs oscillatory phenomena and wave propagation:
where:
- is displacement at position and time
- is wave speed (m/s)
- (1D)
Physical Interpretation
Newton's Second Law applied to small element of string/membrane:
where = linear mass density, = tension.
Wave speed:
Key property: Waves propagate at finite speed (unlike heat equation's infinite speed).
Real-World Example: Vibrating Guitar String
Problem Setup
A guitar string of length m (standard scale length) is plucked at the center, displaced mm, and released from rest.
Material (steel E string):
- Tension: N
- Linear density: kg/m
- Wave speed: m/s
Mathematical Formulation
PDE:
Boundary Conditions (fixed ends):
Initial Position (triangular pluck at center):
where m (5 mm displacement).
Initial Velocity (released from rest):
Analytical Solution
General solution:
where:
- Eigenvalues:
- Angular frequencies:
- Physical frequencies:
Fourier coefficients from initial position:
For triangular pluck:
From initial velocity (released from rest: ):
Final solution:
Musical Harmonics
Fundamental Frequency (n=1)
This is close to E4 note (329.63 Hz) - the open E string frequency.
Overtones (n=2, 3, 4, ...)
- Hz (octave)
- Hz (octave + fifth)
- Hz (two octaves)
Timbre: Combination of harmonics determines sound quality. Triangular pluck emphasizes odd harmonics.
Standing Waves
Physical interpretation: Superposition of left-traveling and right-traveling waves.
D'Alembert solution:
where is the initial shape extended periodically.
Standing wave form: Separation of variables gives standing waves (nodes don't move).
Nodes: Points where for all :
Mode has nodes (including endpoints).
Energy Conservation
Total energy (kinetic + potential):
Theorem: For wave equation with fixed BCs, (constant).
Proof sketch: using PDE and integration by parts.
Physical meaning: No energy dissipation (ideal string). Real strings have damping → telegraph equation.
Limitations
⚠️ Symbolic coefficients only (same as heat equation)
⚠️ Damped waves NOT supported: Telegraph equation requires different solver.
⚠️ Forcing terms NOT supported: requires inhomogeneous solution methods.
Examples
Vibrating Guitar String
A 0.65m guitar string plucked at center with 5mm displacement, demonstrating wave propagation and standing waves.
Rust
#![allow(unused)] fn main() { use mathhook::prelude::*; // Variables let u = symbol!(u); let x = symbol!(x); let t = symbol!(t); // PDE let equation = expr!(u); let pde = Pde::new(equation, u, vec![x.clone(), t.clone()]); // Wave speed let c = expr!(442); // m/s for steel E string // Boundary conditions let bc1 = BoundaryCondition::dirichlet( expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0), }, ); let bc2 = BoundaryCondition::dirichlet( expr!(0), BoundaryLocation::Simple { variable: x, value: expr!(0.65), // L = 0.65 m }, ); // Initial conditions let ic_position = InitialCondition::value( // Triangular function (symbolic - not yet computable) expr!(0.005) // Placeholder for triangular shape ); let ic_velocity = InitialCondition::derivative(expr!(0)); // Released from rest // Solve let solver = WaveEquationSolver::new(); let result = solver.solve_wave_equation_1d( &pde, &c, &[bc1, bc2], &ic_position, &ic_velocity )?; // What you get: println!("Solution: {}", result.solution); // u(x,t) = [A_1*cos(ω₁*t) + B_1*sin(ω₁*t)]*sin(π*x/L) + ... println!("Eigenvalues: {:?}", result.eigenvalues); // [λ₁, λ₂, λ₃, ...] where λₙ = (nπ/L)² println!("Position coefficients (A_n): {:?}", result.position_coefficients); println!("Velocity coefficients (B_n): {:?}", result.velocity_coefficients); }
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver
# Variables
u = symbol('u')
x = symbol('x')
t = symbol('t')
# PDE
equation = expr(u)
pde = Pde(equation, u, [x, t])
# Wave speed
c = expr(442)
# Boundary conditions
bc1 = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple(variable=x, value=expr(0))
)
bc2 = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple(variable=x, value=expr(0.65))
)
# Initial conditions
ic_position = InitialCondition.value(expr(0.005))
ic_velocity = InitialCondition.derivative(expr(0))
# Solve
solver = WaveEquationSolver()
result = solver.solve_wave_equation_1d(pde, c, [bc1, bc2], ic_position, ic_velocity)
print(f"Solution: {result.solution}")
print(f"Eigenvalues: {result.eigenvalues}")
JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver } = require('mathhook');
// Variables
const u = symbol('u');
const x = symbol('x');
const t = symbol('t');
// PDE
const equation = expr(u);
const pde = new Pde(equation, u, [x, t]);
// Wave speed
const c = expr(442);
// Boundary conditions
const bc1 = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple({ variable: x, value: expr(0) })
);
const bc2 = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple({ variable: x, value: expr(0.65) })
);
// Initial conditions
const icPosition = InitialCondition.value(expr(0.005));
const icVelocity = InitialCondition.derivative(expr(0));
// Solve
const solver = new WaveEquationSolver();
const result = solver.solveWaveEquation1d(pde, c, [bc1, bc2], icPosition, icVelocity);
console.log(`Solution: ${result.solution}`);
console.log(`Eigenvalues: ${result.eigenvalues}`);
Performance
Time Complexity: O(n) for n Fourier modes
API Reference
- Rust:
mathhook_core::pde::WaveEquationSolver - Python:
mathhook.pde.wave_equation_solver - JavaScript:
mathhook.pde.waveEquationSolver