Complete PDE Examples
Topic:
advanced.pde.examples
Three complete, real-world examples demonstrating MathHook's PDE solving capabilities across heat, wave, and Laplace equations. Each example includes full problem setup, mathematical formulation, MathHook implementation, and physical interpretation.
Mathematical Definition
Example 1: Heat Diffusion
Example 2: Wave Propagation
Example 3: Electrostatic Potential
Complete PDE Examples
Three complete, real-world examples demonstrating MathHook's PDE solving capabilities.
Example 1: Heat Diffusion in Steel Rod
Physical Problem: A 1-meter steel rod is initially heated to 100°C. Both ends are plunged into ice water (0°C). How does temperature evolve?
Complete Solution
STEP 1: Define Variables
Temperature , position (0 to 1 meter), time
STEP 2: Create PDE
Heat equation:
STEP 3: Material Properties
Steel: m²/s
STEP 4: Boundary Conditions
- (left end in ice water)
- (right end in ice water)
STEP 5: Initial Condition
(uniform initial temperature)
STEP 6: Solve
Using HeatEquationSolver
STEP 7: Examine Solution
Solution structure shows eigenvalues and exponential decay modes.
Physical Interpretation:
- Eigenvalues determine spatial modes
- Higher modes decay faster (∝ )
- Temperature → 0°C as (boundary temperature)
Example 2: Vibrating Guitar String
Physical Problem: An E4 guitar string (0.65 m) is plucked 5 mm at the center and released. Describe the vibration.
Complete Solution
STEP 1: Define Variables
Displacement , position along string, time
STEP 2: Create PDE
Wave equation:
STEP 3: Physical Parameters
Steel E string: N, kg/m
Wave speed: m/s
STEP 4: Boundary Conditions
- (left end fixed)
- (right end fixed, m)
STEP 5: Initial Conditions
- Initial position: triangular pluck at center (5 mm displacement)
- Initial velocity: released from rest ()
STEP 6: Solve
Using WaveEquationSolver
STEP 7: Analyze Musical Properties
Musical Harmonics:
- Fundamental: Hz (close to E4 = 329.63 Hz)
- Overtones:
- Hz (octave)
- Hz (octave + fifth)
- Hz (two octaves)
Standing Wave Nodes:
- Mode 1: nodes at m
- Mode 2: nodes at m
- Mode 3: nodes at m
Example 3: Electrostatic Potential in Rectangular Plate
Physical Problem: A 10 cm × 5 cm conducting plate has bottom/sides grounded (0 V) and top edge at 100 V. Find the potential distribution.
Complete Solution
STEP 1: Define Variables
Electrostatic potential , horizontal position , vertical position
STEP 2: Create PDE
Laplace equation:
STEP 3: Boundary Conditions
- V (left edge grounded)
- V (right edge grounded, m)
- V (bottom edge grounded)
- V (top edge at fixed potential, m)
STEP 4: Solve
Using LaplaceEquationSolver
STEP 5: Examine Solution
Solution structure shows:
- X-direction eigenvalues:
- Hyperbolic sine functions in -direction
- Smooth variation from 0 V to 100 V
Physical Interpretation:
- Potential varies smoothly from 0 V (bottom/sides) to 100 V (top)
- No local maxima/minima inside (maximum principle)
- Electric field points from high to low potential
- Field strongest near top edge (steepest gradient)
Estimated potential at center (5 cm, 2.5 cm): V (halfway between 0 V and 100 V)
Common Pitfalls
Pitfall 1: Expecting Numerical Coefficients
❌ WRONG: Coefficients are symbolic
#![allow(unused)] fn main() { for coeff in result.coefficients { let numerical_value = coeff.evaluate()?; // ERROR: Can't evaluate A_1 } }
✅ CORRECT: Acknowledge symbolic nature
#![allow(unused)] fn main() { for (n, coeff) in result.coefficients.iter().enumerate() { println!("Coefficient A_{} (symbolic): {}", n + 1, coeff); } }
Pitfall 2: Using Non-Standard Variable Names
❌ MAY NOT CLASSIFY:
#![allow(unused)] fn main() { let r = symbol!(r); // Radial let theta = symbol!(theta); // Angular }
✅ USE STANDARD NAMES:
#![allow(unused)] fn main() { let x = symbol!(x); let y = symbol!(y); let t = symbol!(t); }
Pitfall 3: Non-Homogeneous BCs Without Transformation
❌ UNSUPPORTED DIRECTLY:
#![allow(unused)] fn main() { let bc = BoundaryCondition::dirichlet(expr!(50), ...); // Non-zero }
✅ TRANSFORM FIRST:
- Find steady-state satisfying BCs
- Solve for with homogeneous BCs
- Add back:
Summary
Three complete examples demonstrate:
- ✅ Heat equation: Thermal diffusion in steel
- ✅ Wave equation: Musical string vibrations
- ✅ Laplace equation: Electrostatic potential
All examples show:
- Correct eigenvalue computation
- Proper solution structure
- Physical interpretation
- Symbolic coefficient limitation
Next steps: Use these patterns for your own PDE problems, keeping limitations in mind (Dirichlet BCs only, symbolic coefficients).
Examples
Heat Diffusion in Steel Rod - Complete Implementation
1-meter steel rod cooling from 100°C with ice water at ends. Full implementation with error handling.
Rust
#![allow(unused)] fn main() { use mathhook::prelude::*; fn solve_cooling_rod() -> Result<(), Box<dyn std::error::Error>> { // Define Variables let u = symbol!(u); let x = symbol!(x); let t = symbol!(t); // Create PDE let equation = expr!(u); let pde = Pde::new(equation, u, vec![x.clone(), t.clone()]); // Material Properties let alpha = expr!(0.000013); // Steel thermal diffusivity // Boundary Conditions let bc_left = BoundaryCondition::dirichlet( expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0), }, ); let bc_right = BoundaryCondition::dirichlet( expr!(0), BoundaryLocation::Simple { variable: x, value: expr!(1), }, ); // Initial Condition let ic = InitialCondition::value(expr!(100)); // Solve let solver = HeatEquationSolver::new(); let result = solver.solve_heat_equation_1d( &pde, &alpha, &[bc_left, bc_right], &ic, )?; // Examine Solution println!("Heat Equation Solution for Cooling Steel Rod"); println!("Solution structure: {}", result.solution); println!("Eigenvalues: {:?}", result.eigenvalues.iter().take(5).collect::<Vec<_>>()); println!("Fourier coefficients: {:?}", result.coefficients.iter().take(5).collect::<Vec<_>>()); Ok(()) } }
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, HeatEquationSolver
def solve_cooling_rod():
# Define Variables
u = symbol('u')
x = symbol('x')
t = symbol('t')
# Create PDE
equation = expr(u)
pde = Pde(equation, u, [x, t])
# Material Properties
alpha = expr(0.000013)
# Boundary Conditions
bc_left = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple(variable=x, value=expr(0))
)
bc_right = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple(variable=x, value=expr(1))
)
# Initial Condition
ic = InitialCondition.value(expr(100))
# Solve
solver = HeatEquationSolver()
result = solver.solve_heat_equation_1d(pde, alpha, [bc_left, bc_right], ic)
print(f"Solution: {result.solution}")
print(f"Eigenvalues: {result.eigenvalues[:5]}")
print(f"Coefficients: {result.coefficients[:5]}")
JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, HeatEquationSolver } = require('mathhook');
function solveCoolingRod() {
// Define Variables
const u = symbol('u');
const x = symbol('x');
const t = symbol('t');
// Create PDE
const equation = expr(u);
const pde = new Pde(equation, u, [x, t]);
// Material Properties
const alpha = expr(0.000013);
// Boundary Conditions
const bcLeft = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple({ variable: x, value: expr(0) })
);
const bcRight = BoundaryCondition.dirichlet(
expr(0),
BoundaryLocation.simple({ variable: x, value: expr(1) })
);
// Initial Condition
const ic = InitialCondition.value(expr(100));
// Solve
const solver = new HeatEquationSolver();
const result = solver.solveHeatEquation1d(pde, alpha, [bcLeft, bcRight], ic);
console.log(`Solution: ${result.solution}`);
console.log(`Eigenvalues: ${result.eigenvalues.slice(0, 5)}`);
console.log(`Coefficients: ${result.coefficients.slice(0, 5)}`);
}
Vibrating Guitar String - Musical Analysis
E4 guitar string with musical frequency analysis and standing wave nodes.
Rust
#![allow(unused)] fn main() { use mathhook::prelude::*; fn solve_vibrating_string() -> Result<(), Box<dyn std::error::Error>> { let u = symbol!(u); let x = symbol!(x); let t = symbol!(t); let equation = expr!(u); let pde = Pde::new(equation, u, vec![x.clone(), t.clone()]); let c = expr!(442); // Wave speed 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) }, ); let ic_position = InitialCondition::value(expr!(0.005)); let ic_velocity = InitialCondition::derivative(expr!(0)); let solver = WaveEquationSolver::new(); let result = solver.solve_wave_equation_1d( &pde, &c, &[bc1, bc2], &ic_position, &ic_velocity )?; println!("Wave Equation Solution for Vibrating Guitar String"); println!("Solution: {}", result.solution); // Compute musical frequencies let L = 0.65; let c_val = 442.0; for n in 1..=5 { let f_n = (n as f64) * c_val / (2.0 * L); println!("f_{} = {:.2} Hz (mode {})", n, f_n, n); } Ok(()) } }
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver
def solve_vibrating_string():
u = symbol('u')
x = symbol('x')
t = symbol('t')
equation = expr(u)
pde = Pde(equation, u, [x, t])
c = expr(442)
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)))
ic_position = InitialCondition.value(expr(0.005))
ic_velocity = InitialCondition.derivative(expr(0))
solver = WaveEquationSolver()
result = solver.solve_wave_equation_1d(pde, c, [bc1, bc2], ic_position, ic_velocity)
print(f"Solution: {result.solution}")
# Musical frequencies
L = 0.65
c_val = 442.0
for n in range(1, 6):
f_n = n * c_val / (2.0 * L)
print(f"f_{n} = {f_n:.2f} Hz (mode {n})")
JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver } = require('mathhook');
function solveVibratingString() {
const u = symbol('u');
const x = symbol('x');
const t = symbol('t');
const equation = expr(u);
const pde = new Pde(equation, u, [x, t]);
const c = expr(442);
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) }));
const icPosition = InitialCondition.value(expr(0.005));
const icVelocity = InitialCondition.derivative(expr(0));
const solver = new WaveEquationSolver();
const result = solver.solveWaveEquation1d(pde, c, [bc1, bc2], icPosition, icVelocity);
console.log(`Solution: ${result.solution}`);
// Musical frequencies
const L = 0.65;
const cVal = 442.0;
for (let n = 1; n <= 5; n++) {
const fn = n * cVal / (2.0 * L);
console.log(`f_${n} = ${fn.toFixed(2)} Hz (mode ${n})`);
}
}
Electrostatic Potential in Rectangular Plate
10cm × 5cm plate with grounded sides and fixed potential top edge.
Rust
#![allow(unused)] fn main() { use mathhook::prelude::*; fn solve_electrostatic_potential() -> Result<(), Box<dyn std::error::Error>> { let u = symbol!(u); let x = symbol!(x); let y = symbol!(y); let equation = expr!(u); let pde = Pde::new(equation, u, vec![x.clone(), y.clone()]); let bc_left = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0) }); let bc_right = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0.1) }); let bc_bottom = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: y.clone(), value: expr!(0) }); let bc_top = BoundaryCondition::dirichlet(expr!(100), BoundaryLocation::Simple { variable: y, value: expr!(0.05) }); let solver = LaplaceEquationSolver::new(); let result = solver.solve_laplace_equation_2d(&pde, &[bc_left, bc_right, bc_bottom, bc_top])?; println!("Laplace Equation Solution for Electrostatic Potential"); println!("Solution: {}", result.solution); println!("X-eigenvalues: {:?}", result.x_eigenvalues.iter().take(5).collect::<Vec<_>>()); Ok(()) } }
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, LaplaceEquationSolver
def solve_electrostatic_potential():
u = symbol('u')
x = symbol('x')
y = symbol('y')
equation = expr(u)
pde = Pde(equation, u, [x, y])
bc_left = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0)))
bc_right = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0.1)))
bc_bottom = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=y, value=expr(0)))
bc_top = BoundaryCondition.dirichlet(expr(100), BoundaryLocation.simple(variable=y, value=expr(0.05)))
solver = LaplaceEquationSolver()
result = solver.solve_laplace_equation_2d(pde, [bc_left, bc_right, bc_bottom, bc_top])
print(f"Solution: {result.solution}")
print(f"X-eigenvalues: {result.x_eigenvalues[:5]}")
JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, LaplaceEquationSolver } = require('mathhook');
function solveElectrostaticPotential() {
const u = symbol('u');
const x = symbol('x');
const y = symbol('y');
const equation = expr(u);
const pde = new Pde(equation, u, [x, y]);
const bcLeft = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0) }));
const bcRight = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0.1) }));
const bcBottom = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: y, value: expr(0) }));
const bcTop = BoundaryCondition.dirichlet(expr(100), BoundaryLocation.simple({ variable: y, value: expr(0.05) }));
const solver = new LaplaceEquationSolver();
const result = solver.solveLaplaceEquation2d(pde, [bcLeft, bcRight, bcBottom, bcTop]);
console.log(`Solution: ${result.solution}`);
console.log(`X-eigenvalues: ${result.xEigenvalues.slice(0, 5)}`);
}
Performance
Time Complexity: Varies by example: O(n) for n modes
API Reference
- Rust:
mathhook_core::pde - Python:
mathhook.pde - JavaScript:
mathhook.pde